Question:
This seems to be related to , though not entirely the same. I am in the process of ing my crate (multiple crates in a workspace project) v0.5.0 (from ). Instead of a normal compile process, I got this: :
I experienced this error now multiple times. Maybe it is a good idea to include the complete build output here:
With I get this error in a different form:
For the record: works on all crates where this bug was triggered (though I did not test all of them, just some).
For whatever reason, this is making it effectively impossible for me to package projects with lots of dependencies for Nix.
I can reliably hit this bug when compiling my project () with Nix
I believe this is a bug in our rustc package in nixpkgs, we appear to build it against which is bugged: https://nix- Maybe it would be a good idea to have a hard dependency on for rustc?
There is an issue here: rustc version 1.22.1 has in its lockfile, and the nix build appears to reliably trigger this bug while compiling . So we have a problem in nixpkgs that we cannot bootstrap using the binary distribution from rust- you are the author of , is there something we could do to workaround this bug for bootstrapping ? Or is it necessary to use a patched for compiling ?
the workaround would be to remove any ambient jobservers and let cargo/rustc manage it, if any
Can't we bootstrap using 1.23.0 binaries?
I can reliably hit this bug as well in nix
I can reliably hit this bug using . As far as I am aware I don't have any jobservers running.
I realized that the following issue was only occurring on nightly. However after the latest update this is now occurring on stable as well.
still persists using seems to happen because of this:
Can you please take another look at this. It appears that your diagnosis is wrong and many people are experiencing this issue. There is no workaround as far as I can tell and this is seriously workflow disrupting.
A misconfigured jobserver can still cause issues in rustc, and this error is indicative of a misconfigured jobserver in one way or another. This indicates an environmental problem rather than a problem in rustc AFAIK. If someone else manages to fix rustc we can of course merge, but I don't personally believe there's much we can do in rustc for this.
There is no other jobserver in my environment. I have checked numerous ways and am highly confident.
I am also getting the same error as when running entr with the reload flag. Throws the following error: According to the entr documentation whats happening is : 1) immediately start the server 2) block until any of the listed files change 3) terminate the background process 4) wait for the server to exit before restarting
I created an upstream issue for as well - it surrounds closing STDIN, which was in later versions for compatibility with some programs reasons - seems it then breaks with .
It sounds like the underlying issue is
A workaround for those using : It works for me with and 1.40.0 on Linux.
This is no longer happening for me. I don't know what has changed but I don't see this anymore.
It still happens for me with and . Just tested it with and got a panic starting with the same bit.
So, I've found an entirely legitimate way to trigger this error (the "early EOF on jobserver pipe" case) on new versions of , without having stdin closed or anything other exotic setup. If you call from an outer -based build system then will receive file descriptors for the jobserver pipe through an env var called . Except that new versions of will mark those descriptors as so they will be either dead or, worse, replaced with other random files when tries to access them :D The solution is to prevent from closing the pipe by using string anywhere in the command. (Yep, that's how works - ) This is silly, but it seems like doesn't leave any other way to inherit jobserver (at least not readily available from higher level makefile generators).
was recently facing similar issue while trying to run cargo build inside a makefile with buildroot was facing this everytime when i run cargo build Build fails: error: failed to acquire jobserver token: Bad file descriptor (os error 9) This worked for me. MAKEFLAGS= JOBS= cargo build
If you are actually running cargo inside of make you are hitting a different problem and I recommend opening a different issue. This issue was about a bug where no job server was running. This issue was fixed.

reset_sigpipe(); } <ins> // In the case when all file descriptors are open, the poll has been // observed to perform better than fcntl (on GNU/Linux). #[cfg(not(any( miri, target_os = "emscripten", target_os = "fuchsia", // The poll on Darwin doesn't set POLLNVAL for closed fds. target_os = "macos", target_os = "ios", target_os = "redox", )))] unsafe fn sanitize_standard_fds() { use crate::sys::os::errno; let pfds: &mut [_] = &mut [ libc::pollfd { fd: 0, events: 0, revents: 0 }, libc::pollfd { fd: 1, events: 0, revents: 0 }, libc::pollfd { fd: 2, events: 0, revents: 0 }, ]; while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { if errno() == libc::EINTR { continue; } libc::abort(); } for pfd in pfds { if pfd.revents & libc::POLLNVAL == 0 { continue; } if libc::open("/dev/null0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or // Stderr. libc::abort(); } } } #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] unsafe fn sanitize_standard_fds() { use crate::sys::os::errno; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { if libc::open("/dev/null0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { libc::abort(); } } } } #[cfg(any( // The standard fds are always available in Miri. miri, target_os = "emscripten", target_os = "fuchsia"))] unsafe fn sanitize_standard_fds() {} </ins> #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] unsafe fn reset_sigpipe() { assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);


Question:
This seems to be related to , though not entirely the same. I am in the process of ing my crate (multiple crates in a workspace project) v0.5.0 (from ). Instead of a normal compile process, I got this: :
I experienced this error now multiple times. Maybe it is a good idea to include the complete build output here:
With I get this error in a different form:
For the record: works on all crates where this bug was triggered (though I did not test all of them, just some).
For whatever reason, this is making it effectively impossible for me to package projects with lots of dependencies for Nix.
I can reliably hit this bug when compiling my project () with Nix
I believe this is a bug in our rustc package in nixpkgs, we appear to build it against which is bugged: https://nix- Maybe it would be a good idea to have a hard dependency on for rustc?
There is an issue here: rustc version 1.22.1 has in its lockfile, and the nix build appears to reliably trigger this bug while compiling . So we have a problem in nixpkgs that we cannot bootstrap using the binary distribution from rust- you are the author of , is there something we could do to workaround this bug for bootstrapping ? Or is it necessary to use a patched for compiling ?
the workaround would be to remove any ambient jobservers and let cargo/rustc manage it, if any
Can't we bootstrap using 1.23.0 binaries?
I can reliably hit this bug as well in nix
I can reliably hit this bug using . As far as I am aware I don't have any jobservers running.
I realized that the following issue was only occurring on nightly. However after the latest update this is now occurring on stable as well.
still persists using seems to happen because of this:
Can you please take another look at this. It appears that your diagnosis is wrong and many people are experiencing this issue. There is no workaround as far as I can tell and this is seriously workflow disrupting.
A misconfigured jobserver can still cause issues in rustc, and this error is indicative of a misconfigured jobserver in one way or another. This indicates an environmental problem rather than a problem in rustc AFAIK. If someone else manages to fix rustc we can of course merge, but I don't personally believe there's much we can do in rustc for this.
There is no other jobserver in my environment. I have checked numerous ways and am highly confident.
I am also getting the same error as when running entr with the reload flag. Throws the following error: According to the entr documentation whats happening is : 1) immediately start the server 2) block until any of the listed files change 3) terminate the background process 4) wait for the server to exit before restarting
I created an upstream issue for as well - it surrounds closing STDIN, which was in later versions for compatibility with some programs reasons - seems it then breaks with .
It sounds like the underlying issue is
A workaround for those using : It works for me with and 1.40.0 on Linux.
This is no longer happening for me. I don't know what has changed but I don't see this anymore.
It still happens for me with and . Just tested it with and got a panic starting with the same bit.
So, I've found an entirely legitimate way to trigger this error (the "early EOF on jobserver pipe" case) on new versions of , without having stdin closed or anything other exotic setup. If you call from an outer -based build system then will receive file descriptors for the jobserver pipe through an env var called . Except that new versions of will mark those descriptors as so they will be either dead or, worse, replaced with other random files when tries to access them :D The solution is to prevent from closing the pipe by using string anywhere in the command. (Yep, that's how works - ) This is silly, but it seems like doesn't leave any other way to inherit jobserver (at least not readily available from higher level makefile generators).
was recently facing similar issue while trying to run cargo build inside a makefile with buildroot was facing this everytime when i run cargo build Build fails: error: failed to acquire jobserver token: Bad file descriptor (os error 9) This worked for me. MAKEFLAGS= JOBS= cargo build
If you are actually running cargo inside of make you are hitting a different problem and I recommend opening a different issue. This issue was about a bug where no job server was running. This issue was fixed.

return r } <ins> #[cfg(unix)] fn assert_fd_is_valid(fd: libc::c_int) { if unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 } { panic!("file descriptor {} is not valid: {}", fd, io::Error::last_os_error()); } } #[cfg(windows)] fn assert_fd_is_valid(_fd: libc::c_int) {} </ins> #[cfg(windows)] unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R { type DWORD = u32;


Question:
This seems to be related to , though not entirely the same. I am in the process of ing my crate (multiple crates in a workspace project) v0.5.0 (from ). Instead of a normal compile process, I got this: :
I experienced this error now multiple times. Maybe it is a good idea to include the complete build output here:
With I get this error in a different form:
For the record: works on all crates where this bug was triggered (though I did not test all of them, just some).
For whatever reason, this is making it effectively impossible for me to package projects with lots of dependencies for Nix.
I can reliably hit this bug when compiling my project () with Nix
I believe this is a bug in our rustc package in nixpkgs, we appear to build it against which is bugged: https://nix- Maybe it would be a good idea to have a hard dependency on for rustc?
There is an issue here: rustc version 1.22.1 has in its lockfile, and the nix build appears to reliably trigger this bug while compiling . So we have a problem in nixpkgs that we cannot bootstrap using the binary distribution from rust- you are the author of , is there something we could do to workaround this bug for bootstrapping ? Or is it necessary to use a patched for compiling ?
the workaround would be to remove any ambient jobservers and let cargo/rustc manage it, if any
Can't we bootstrap using 1.23.0 binaries?
I can reliably hit this bug as well in nix
I can reliably hit this bug using . As far as I am aware I don't have any jobservers running.
I realized that the following issue was only occurring on nightly. However after the latest update this is now occurring on stable as well.
still persists using seems to happen because of this:
Can you please take another look at this. It appears that your diagnosis is wrong and many people are experiencing this issue. There is no workaround as far as I can tell and this is seriously workflow disrupting.
A misconfigured jobserver can still cause issues in rustc, and this error is indicative of a misconfigured jobserver in one way or another. This indicates an environmental problem rather than a problem in rustc AFAIK. If someone else manages to fix rustc we can of course merge, but I don't personally believe there's much we can do in rustc for this.
There is no other jobserver in my environment. I have checked numerous ways and am highly confident.
I am also getting the same error as when running entr with the reload flag. Throws the following error: According to the entr documentation whats happening is : 1) immediately start the server 2) block until any of the listed files change 3) terminate the background process 4) wait for the server to exit before restarting
I created an upstream issue for as well - it surrounds closing STDIN, which was in later versions for compatibility with some programs reasons - seems it then breaks with .
It sounds like the underlying issue is
A workaround for those using : It works for me with and 1.40.0 on Linux.
This is no longer happening for me. I don't know what has changed but I don't see this anymore.
It still happens for me with and . Just tested it with and got a panic starting with the same bit.
So, I've found an entirely legitimate way to trigger this error (the "early EOF on jobserver pipe" case) on new versions of , without having stdin closed or anything other exotic setup. If you call from an outer -based build system then will receive file descriptors for the jobserver pipe through an env var called . Except that new versions of will mark those descriptors as so they will be either dead or, worse, replaced with other random files when tries to access them :D The solution is to prevent from closing the pipe by using string anywhere in the command. (Yep, that's how works - ) This is silly, but it seems like doesn't leave any other way to inherit jobserver (at least not readily available from higher level makefile generators).
was recently facing similar issue while trying to run cargo build inside a makefile with buildroot was facing this everytime when i run cargo build Build fails: error: failed to acquire jobserver token: Bad file descriptor (os error 9) This worked for me. MAKEFLAGS= JOBS= cargo build
If you are actually running cargo inside of make you are hitting a different problem and I recommend opening a different issue. This issue was about a bug where no job server was running. This issue was fixed.

fn main() { if env::args().len() > 1 { <ins> // Writing to stdout & stderr should not panic. </ins> println!("test"); assert!(io::stdout().write(b"testn").is_ok()); assert!(io::stderr().write(b"testn").is_ok()); <ins> // Stdin should be at EOF. </ins> assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0); <ins> // Standard file descriptors should be valid on UNIX: assert_fd_is_valid(0); assert_fd_is_valid(1); assert_fd_is_valid(2); </ins> return }


Question:
This seems to be related to , though not entirely the same. I am in the process of ing my crate (multiple crates in a workspace project) v0.5.0 (from ). Instead of a normal compile process, I got this: :
I experienced this error now multiple times. Maybe it is a good idea to include the complete build output here:
With I get this error in a different form:
For the record: works on all crates where this bug was triggered (though I did not test all of them, just some).
For whatever reason, this is making it effectively impossible for me to package projects with lots of dependencies for Nix.
I can reliably hit this bug when compiling my project () with Nix
I believe this is a bug in our rustc package in nixpkgs, we appear to build it against which is bugged: https://nix- Maybe it would be a good idea to have a hard dependency on for rustc?
There is an issue here: rustc version 1.22.1 has in its lockfile, and the nix build appears to reliably trigger this bug while compiling . So we have a problem in nixpkgs that we cannot bootstrap using the binary distribution from rust- you are the author of , is there something we could do to workaround this bug for bootstrapping ? Or is it necessary to use a patched for compiling ?
the workaround would be to remove any ambient jobservers and let cargo/rustc manage it, if any
Can't we bootstrap using 1.23.0 binaries?
I can reliably hit this bug as well in nix
I can reliably hit this bug using . As far as I am aware I don't have any jobservers running.
I realized that the following issue was only occurring on nightly. However after the latest update this is now occurring on stable as well.
still persists using seems to happen because of this:
Can you please take another look at this. It appears that your diagnosis is wrong and many people are experiencing this issue. There is no workaround as far as I can tell and this is seriously workflow disrupting.
A misconfigured jobserver can still cause issues in rustc, and this error is indicative of a misconfigured jobserver in one way or another. This indicates an environmental problem rather than a problem in rustc AFAIK. If someone else manages to fix rustc we can of course merge, but I don't personally believe there's much we can do in rustc for this.
There is no other jobserver in my environment. I have checked numerous ways and am highly confident.
I am also getting the same error as when running entr with the reload flag. Throws the following error: According to the entr documentation whats happening is : 1) immediately start the server 2) block until any of the listed files change 3) terminate the background process 4) wait for the server to exit before restarting
I created an upstream issue for as well - it surrounds closing STDIN, which was in later versions for compatibility with some programs reasons - seems it then breaks with .
It sounds like the underlying issue is
A workaround for those using : It works for me with and 1.40.0 on Linux.
This is no longer happening for me. I don't know what has changed but I don't see this anymore.
It still happens for me with and . Just tested it with and got a panic starting with the same bit.
So, I've found an entirely legitimate way to trigger this error (the "early EOF on jobserver pipe" case) on new versions of , without having stdin closed or anything other exotic setup. If you call from an outer -based build system then will receive file descriptors for the jobserver pipe through an env var called . Except that new versions of will mark those descriptors as so they will be either dead or, worse, replaced with other random files when tries to access them :D The solution is to prevent from closing the pipe by using string anywhere in the command. (Yep, that's how works - ) This is silly, but it seems like doesn't leave any other way to inherit jobserver (at least not readily available from higher level makefile generators).
was recently facing similar issue while trying to run cargo build inside a makefile with buildroot was facing this everytime when i run cargo build Build fails: error: failed to acquire jobserver token: Bad file descriptor (os error 9) This worked for me. MAKEFLAGS= JOBS= cargo build
If you are actually running cargo inside of make you are hitting a different problem and I recommend opening a different issue. This issue was about a bug where no job server was running. This issue was fixed.

.stdout(Stdio::null()) .stderr(Stdio::null()) .status().unwrap(); <del> assert!(status.success(), "{:?} isn't a success", status); </del> <ins> assert!(status.success(), "{} isn't a success", status); </ins> // Finally, close everything then spawn a child to make sure everything is // *still* ok. let status = unsafe { without_stdio(|| Command::new(&me).arg("next").status()) }.unwrap(); <del> assert!(status.success(), "{:?} isn't a success", status); </del> <ins> assert!(status.success(), "{} isn't a success", status); </ins> }


Question:
Irrefutable slice patterns with a may cause the compiler to ICE. I expected to see this happen: the code compiled (however silly this example is) Instead, this happened: : rustc 1.24.0-nightly ( 2017-12-30) binary: rustc commit-hash: commit-date: 2017-12-30 host: x86_64-unknown-linux-gnu release: 1.24.0-nightly LLVM version: 4.0 Backtrace:
It also occurs with:

end: RangeEnd, }, <del> /// matches against a slice, checking the length and extracting elements </del> <ins> /// matches against a slice, checking the length and extracting elements. /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. /// e.g. `&[ref xs..]`. </ins> Slice { prefix: Vec<Pattern<'tcx>>, slice: Option<Pattern<'tcx>>,


Question:
Irrefutable slice patterns with a may cause the compiler to ICE. I expected to see this happen: the code compiled (however silly this example is) Instead, this happened: : rustc 1.24.0-nightly ( 2017-12-30) binary: rustc commit-hash: commit-date: 2017-12-30 host: x86_64-unknown-linux-gnu release: 1.24.0-nightly LLVM version: 4.0 Backtrace:
It also occurs with:

Err(match_pair) } <del> PatternKind::Range { .. } | PatternKind::Slice { .. } => { </del> <ins> PatternKind::Range { .. } => { </ins> Err(match_pair) } <ins> PatternKind::Slice { ref prefix, ref slice, ref suffix } => { if prefix.is_empty() && slice.is_some() && suffix.is_empty() { // irrefutable self.prefix_slice_suffix(&mut candidate.match_pairs, &match_pair.place, prefix, slice.as_ref(), suffix); Ok(()) } else { Err(match_pair) } } </ins> PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || {


Question:
Irrefutable slice patterns with a may cause the compiler to ICE. I expected to see this happen: the code compiled (however silly this example is) Instead, this happened: : rustc 1.24.0-nightly ( 2017-12-30) binary: rustc commit-hash: commit-date: 2017-12-30 host: x86_64-unknown-linux-gnu release: 1.24.0-nightly LLVM version: 4.0 Backtrace:
It also occurs with:

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // #47096 #![feature(slice_patterns)] fn foo(s: &[i32]) -> &[i32] { let &[ref xs..] = s; xs } fn main() { let x = [1, 2, 3]; let y = foo(&x); assert_eq!(x, y); } </ins>


Question:
Former-XXXes say "is this right?"
Clearing milestone because it's not obviously blocking anything. -- what test case(s) would answer the question you asked in a comment ("is this right?")?
Visiting for triage; FIXMEs are still there.

#[test] #[should_fail] fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); } <ins> #[test] </ins> fn test_opt() { assert_eq!(65u8.to_ascii_opt(), Some(Ascii { chr: 65u8 })); assert_eq!(255u8.to_ascii_opt(), None);


Question:
Former-XXXes say "is this right?"
Clearing milestone because it's not obviously blocking anything. -- what test case(s) would answer the question you asked in a comment ("is this right?")?
Visiting for triage; FIXMEs are still there.

#[cfg(test)] mod test { use super::*; <del> use io::net::ip::{Ipv4Addr, SocketAddr}; </del> <ins> use io::net::ip::{SocketAddr}; </ins> use io::*; <del> use io::test::*; </del> use prelude::*; iotest!(fn bind_error() {


Question:
Former-XXXes say "is this right?"
Clearing milestone because it's not obviously blocking anything. -- what test case(s) would answer the question you asked in a comment ("is this right?")?
Visiting for triage; FIXMEs are still there.

use unstable::run_in_bare_thread; use super::*; use rt::task::Task; <del> use rt::local_ptr; </del> #[test] fn thread_local_task_smoke_test() {


Question:
Former-XXXes say "is this right?"
Clearing milestone because it's not obviously blocking anything. -- what test case(s) would answer the question you asked in a comment ("is this right?")?
Visiting for triage; FIXMEs are still there.

fn visit_estr_uniq(&mut self) -> bool { true } fn visit_estr_slice(&mut self) -> bool { true } fn visit_estr_fixed(&mut self, <del> _sz: uint, _sz: uint, </del> <ins> _sz: uint, _sz2: uint, </ins> _align: uint) -> bool { true } fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

&substs[..] )); } <del> DefiningTy::Const(ty) => { </del> <ins> DefiningTy::Const(def_id, substs) => { </ins> err.note(&format!( <del> "defining type: {:?}", ty </del> <ins> "defining constant type: {:?} with substs {:#?}", def_id, &substs[..] </ins> )); } }


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

/// The MIR represents some form of constant. The signature then /// is that it has no inputs and a single return value, which is /// the value of the constant. <del> Const(Ty<'tcx>), </del> <ins> Const(DefId, &'tcx Substs<'tcx>), </ins> } #[derive(Debug)]


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

/// see `DefiningTy` for details. fn defining_ty(&self) -> DefiningTy<'tcx> { let tcx = self.infcx.tcx; let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); <del> let defining_ty = if self.mir_def_id == closure_base_def_id { tcx.type_of(closure_base_def_id) } else { let tables = tcx.typeck_tables_of(self.mir_def_id); tables.node_id_to_type(self.mir_hir_id) }; let defining_ty = self.infcx .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); </del> match tcx.hir.body_owner_kind(self.mir_node_id) { <del> BodyOwnerKind::Fn => match defining_ty.sty { ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs), ty::TyGenerator(def_id, substs, interior) => { DefiningTy::Generator(def_id, substs, interior) </del> <ins> BodyOwnerKind::Fn => { let defining_ty = if self.mir_def_id == closure_base_def_id { tcx.type_of(closure_base_def_id) } else { let tables = tcx.typeck_tables_of(self.mir_def_id); tables.node_id_to_type(self.mir_hir_id) }; let defining_ty = self.infcx .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); match defining_ty.sty  { ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs), ty::TyGenerator(def_id, substs, interior) => { DefiningTy::Generator(def_id, substs, interior) } ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), _ => span_bug!( tcx.def_span(self.mir_def_id), "expected defining type for `{:?}`: `{:?}`", self.mir_def_id, defining_ty ), </ins> } <del> ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), _ => span_bug!( tcx.def_span(self.mir_def_id), "expected defining type for `{:?}`: `{:?}`", self.mir_def_id, defining_ty ), }, BodyOwnerKind::Const | BodyOwnerKind::Static(..) => DefiningTy::Const(defining_ty), </del> <ins> } BodyOwnerKind::Const | BodyOwnerKind::Static(..) => { assert_eq!(closure_base_def_id, self.mir_def_id); let identity_substs = Substs::identity_for_item(tcx, closure_base_def_id); let substs = self.infcx .replace_free_regions_with_nll_infer_vars(FR, &identity_substs); DefiningTy::Const(self.mir_def_id, substs) } </ins> } }


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

substs.substs } <del> DefiningTy::FnDef(_, substs) => substs, // When we encounter a constant body, just return whatever // substitutions are in scope for that constant. DefiningTy::Const(_) => { identity_substs } </del> <ins> DefiningTy::FnDef(_, substs) | DefiningTy::Const(_, substs) => substs, </ins> }; let global_mapping = iter::once((gcx.types.re_static, fr_static));


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

sig.inputs_and_output() } <del> // For a constant body, there are no inputs, and one // "output" (the type of the constant). DefiningTy::Const(ty) => ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))), </del> <ins> DefiningTy::Const(def_id, _) => { // For a constant body, there are no inputs, and one // "output" (the type of the constant). assert_eq!(self.mir_def_id, def_id); let ty = tcx.type_of(def_id); let ty = indices.fold_to_region_vids(tcx, &ty); ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))) } </ins> } }


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Test cases where we put various lifetime constraints on trait // associated constants. #![feature(rustc_attrs)] use std::option::Option; trait Anything<'a: 'b, 'b> { const AC: Option<&'b str>; } struct OKStruct { } impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct { const AC: Option<&'b str> = None; } struct FailStruct1 { } impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { const AC: Option<&'c str> = None; //~^ ERROR: mismatched types } struct FailStruct2 { } impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { const AC: Option<&'a str> = None; //~^ ERROR: mismatched types } fn main() {} </ins>


Question:
is probably the same issue.
Not a dup of
or rather, with the fix applied, I get another ICE =)
That new ICE seems similar to :)
Hmm, yes, but it's definitely not an issue with
This probably has something to do with the fact that consts use the identity substitutions when computing universal regions substitutions: since those are always going to be generating regions: I have yet to track down the code that should be resolving those early bounds and why it isn't doing so.
Hmm, you are in the right area of the code. But I think the problem runs just a touch deeper. Actually the comments here are not that great. I should do a pass to improve them. But let me try to first explain what's happening a bit and then how to fix it. The role of the enum (which should perhaps be renamed?) is to kind of capture the "external signature" for a given piece of MIR, and ideally in a way that identifies all of the "degrees of freedom" that the code has (and just those degrees of freedom). Based just on the defining-type, we should be able to identify the following information: The universally bound regions (i.e., lifetime parameters), both early and (where relevant) late bound The types of all the MIR inputs (expressed in terms of these universally bound regions) The types of the MIR output (expressed in terms of these universally bound regions) This is perhaps easiest to explain with a function item. Assume that we are working with the MIR for this function : In that case, the defining type will be the variant: You can see that it is actually sort of minimal: just a def-id and a substs array. In this case, the substs array will consist of three things, first a lifetime variable (representing ) and then two types (, as it happens): (This array gets created in ; this will basically replace the formal lifetime parameter of (represented as an ) with a fresh variable .) Given the array, we can easily compute the set of region variables representing universally bound regions in a function signature -- it's just the region variables appearing in the substs array. That's what we use to build the map in . Note that this substs array does not, for example, include the types of the arguments etc. That's because those types can be reconstructed using queries. For example, the function includes this code, which extracts the function signature (using the query) and then basically substitutes (the call has that effect) from the formal lifetime parameters: Part of the reason it is done this way is that then the types of both arguments ( and ) will reference the same lifetime (). If, when creating the defining type, we had on something that contained the types of those arguments separately, then they would have been rewritten to use two different lifetime variables. This would have been too many "degrees of freedom". For constants, our defining-type variant is currently the type of the constant: This is actually wrong, and is roughly the equivalent of storing the types of the arguments directly in the . The fault arises from in -- it was written with functions and closures in mind. It fetches the "type" associated with the def-id and rewrites all the regions in it. This is ok for functions and closures because the type of a function or closure is already a kind of indirection; e.g., a is . We probably want to change that variant to something more like Fn: then we want to do is to refactor somewhat. I would expect it to look more like the following. This is the same as the existing code, just rearranged so that it only executes for : meanwhile, for and , we'll do something slightly different. We don't want to start by fetching , because that gets the type associated with the static. Instead, we'll do: Then we can change the other bits of code to match. For example: becomes When we wish to compute the "return type" of the closure, then we can do the query: becomes: I think that ought to work. cc

<ins> error[E0308]: mismatched types --> $DIR/trait-associated-constant.rs:31:5 | 31 |     const AC: Option<&'c str> = None; |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected type `std::option::Option<&'b str>` found type `std::option::Option<&'c str>` note: the lifetime 'c as defined on the impl at 30:1... --> $DIR/trait-associated-constant.rs:30:1 | 30 | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 30:1 --> $DIR/trait-associated-constant.rs:30:1 | 30 | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/trait-associated-constant.rs:38:5 | 38 |     const AC: Option<&'a str> = None; |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected type `std::option::Option<&'b str>` found type `std::option::Option<&'a str>` note: the lifetime 'a as defined on the impl at 37:1... --> $DIR/trait-associated-constant.rs:37:1 | 37 | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 37:1 --> $DIR/trait-associated-constant.rs:37:1 | 37 | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors </ins>


Question: The code around opt-levels indicates only nightly can use or . Non-nightly s should not even report those values as possible options.

} OptLevel::Default } else { <del> match ( cg.opt_level.as_ref().map(String::as_ref), nightly_options::is_nightly_build(), ) { (None, _) => OptLevel::No, (Some("0"), _) => OptLevel::No, (Some("1"), _) => OptLevel::Less, (Some("2"), _) => OptLevel::Default, (Some("3"), _) => OptLevel::Aggressive, (Some("s"), true) => OptLevel::Size, (Some("z"), true) => OptLevel::SizeMin, (Some("s"), false) | (Some("z"), false) => { early_error( error_format, &format!( "the optimizations s or z are only  accepted on the nightly compiler" ), ); } (Some(arg), _) => { </del> <ins> match cg.opt_level.as_ref().map(String::as_ref) { None => OptLevel::No, Some("0") => OptLevel::No, Some("1") => OptLevel::Less, Some("2") => OptLevel::Default, Some("3") => OptLevel::Aggressive, Some("s") => OptLevel::Size, Some("z") => OptLevel::SizeMin, Some(arg) => { </ins> early_error( error_format, &format!(


Question:
Repro: The same happens for 1.23-stable.
does this still reproduce?
no repro for .

pub use run::{cmd, run, run_fail, run_with_args}; /// Helpers for checking target information. <del> pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname}; </del> <ins> pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os}; </ins> /// Helpers for building names of output artifacts that are potentially target-specific. pub use artifact_names::{


Question:
Repro: The same happens for 1.23-stable.
does this still reproduce?
no repro for .

target().contains("darwin") } <ins> /// Get the target OS on Apple operating systems. #[must_use] pub fn apple_os() -> &'static str { if target().contains("darwin") { "macos" } else if target().contains("ios") { "ios" } else if target().contains("tvos") { "tvos" } else if target().contains("watchos") { "watchos" } else if target().contains("visionos") { "visionos" } else { panic!("not an Apple OS") } } </ins> /// Check if `component` is within `LLVM_COMPONENTS` #[must_use] pub fn llvm_components_contain(component: &str) -> bool {


Question:
Repro: The same happens for 1.23-stable.
does this still reproduce?
no repro for .

run-make/issue-84395-lto-embed-bitcode/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile <del> run-make/macos-deployment-target/Makefile </del> run-make/split-debuginfo/Makefile run-make/symbol-mangling-hashed/Makefile run-make/translation/Makefile


Question:
Repro: The same happens for 1.23-stable.
does this still reproduce?
no repro for .

<ins> //! Test codegen when setting deployment targets on Apple platforms. //! //! This is important since its a compatibility hazard. The linker will //! generate load commands differently based on what minimum OS it can assume. //! //! See https://github.com/rust-lang/rust/pull/105123. //@ only-apple use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target}; /// Run vtool to check the `minos` field in LC_BUILD_VERSION. /// /// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar /// are used instead of LC_BUILD_VERSION - these have a `version` field, so also check that. #[track_caller] fn minos(file: &str, version: &str) { cmd("vtool") .arg("-show-build") .arg(file) .run() .assert_stdout_contains_regex(format!("(minos|version) {version}")); } fn main() { // These versions should generally be higher than the default versions let (env_var, example_version, higher_example_version) = match apple_os() { "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"), // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0 "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => { ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0") } "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"), "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"), "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"), "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"), _ => unreachable!(), }; let default_version = rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8(); let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim(); // Test that version makes it to the object file. run_in_tmpdir(|| { let rustc = || { let mut rustc = rustc(); rustc.target(target()); rustc.crate_type("lib"); rustc.emit("obj"); rustc.input("foo.rs"); rustc.output("foo.o"); rustc }; rustc().env(env_var, example_version).run(); minos("foo.o", example_version); // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. if !target().contains("macabi") && !target().contains("sim") { rustc().env_remove(env_var).run(); minos("foo.o", default_version); } }); // Test that version makes it to the linker when linking dylibs. run_in_tmpdir(|| { // Certain watchOS targets don't support dynamic linking, so we disable the test on those. if apple_os() == "watchos" { return; } let rustc = || { let mut rustc = rustc(); rustc.target(target()); rustc.crate_type("dylib"); rustc.input("foo.rs"); rustc.output("libfoo.dylib"); rustc }; rustc().env(env_var, example_version).run(); minos("libfoo.dylib", example_version); // FIXME(madsmtm): Deployment target is not currently passed properly to linker // rustc().env_remove(env_var).run(); // minos("libfoo.dylib", default_version); // Test with ld64 instead rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run(); minos("libfoo.dylib", example_version); rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run(); minos("libfoo.dylib", default_version); }); // Test that version makes it to the linker when linking executables. run_in_tmpdir(|| { let rustc = || { let mut rustc = rustc(); rustc.target(target()); rustc.crate_type("bin"); rustc.input("foo.rs"); rustc.output("foo"); rustc }; // FIXME(madsmtm): Doesn't work on watchOS for some reason? if !target().contains("watchos") { rustc().env(env_var, example_version).run(); minos("foo", example_version); // FIXME(madsmtm): Deployment target is not currently passed properly to linker // rustc().env_remove(env_var).run(); // minos("foo", default_version); } // Test with ld64 instead rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run(); minos("foo", example_version); rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run(); minos("foo", default_version); }); // Test that changing the deployment target busts the incremental cache. run_in_tmpdir(|| { let rustc = || { let mut rustc = rustc(); rustc.target(target()); rustc.incremental("incremental"); rustc.crate_type("lib"); rustc.emit("obj"); rustc.input("foo.rs"); rustc.output("foo.o"); rustc }; // FIXME(madsmtm): Incremental cache is not yet busted // https://github.com/rust-lang/rust/issues/118204 let higher_example_version = example_version; let default_version = example_version; rustc().env(env_var, example_version).run(); minos("foo.o", example_version); rustc().env(env_var, higher_example_version).run(); minos("foo.o", higher_example_version); // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. if !target().contains("macabi") && !target().contains("sim") { rustc().env_remove(env_var).run(); minos("foo.o", default_version); } }); } </ins>


Question:
Repro: The same happens for 1.23-stable.
does this still reproduce?
no repro for .

<del> # only-macos # # Check that a set deployment target actually makes it to the linker. # This is important since its a compatibility hazard. The linker will # generate load commands differently based on what minimum OS it can assume. include ../tools.mk ifeq ($(strip $(shell uname -m)),arm64) GREP_PATTERN = "minos 11.0" else GREP_PATTERN = "version 10.13" endif OUT_FILE=$(TMPDIR)/with_deployment_target.dylib all: env MACOSX_DEPLOYMENT_TARGET=10.13 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE) # XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11). # They also use different load commands, so we let that change with each too. The aarch64 check # isn't as robust as the x86 one, but testing both seems unneeded. vtool -show-build $(OUT_FILE) | $(CGREP) -e $(GREP_PATTERN) </del>


Question:
Repro: The same happens for 1.23-stable.
does this still reproduce?
no repro for .

<del> #![crate_type = "cdylib"] #[allow(dead_code)] fn something_and_nothing() {} </del>


Question: is implemented for Range<T. TrustedLen that the upper bound of is None if the iterator produces more than elements. to produce its result. The of subtracts the lower from the upper value and casts it to usize. This is for u32. On 16bit platforms, the result of the subtraction of two u32 values may not fit inside , producing an invalid . This means, that e.g. collecting into a Vec using its allows writing beyond its reserved buffer. One such example input would be . Reference: /cc

)*) } <del> step_impl_unsigned!(usize u8 u16 u32); step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]); </del> <ins> step_impl_unsigned!(usize u8 u16); #[cfg(not(target_pointer_witdth = "16"))] step_impl_unsigned!(u32); #[cfg(target_pointer_witdth = "16")] step_impl_no_between!(u32); step_impl_signed!([isize: usize] [i8: u8] [i16: u16]); #[cfg(not(target_pointer_witdth = "16"))] step_impl_signed!([i32: u32]); #[cfg(target_pointer_witdth = "16")] step_impl_no_between!(i32); </ins> #[cfg(target_pointer_width = "64")] step_impl_unsigned!(u64); #[cfg(target_pointer_width = "64")]


Question: is implemented for Range<T. TrustedLen that the upper bound of is None if the iterator produces more than elements. to produce its result. The of subtracts the lower from the upper value and casts it to usize. This is for u32. On 16bit platforms, the result of the subtraction of two u32 values may not fit inside , producing an invalid . This means, that e.g. collecting into a Vec using its allows writing beyond its reserved buffer. One such example input would be . Reference: /cc

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(step_trait)] use std::iter::Step; #[cfg(target_pointer_width = "16")] fn main() { assert!(Step::steps_between(&0u32, &::std::u32::MAX).is_none()); } #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] fn main() { assert!(Step::steps_between(&0u32, &::std::u32::MAX).is_some()); } </ins>


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

cfg.file("../rustllvm/PassWrapper.cpp") .file("../rustllvm/RustWrapper.cpp") .file("../rustllvm/ArchiveWrapper.cpp") <ins> .file("../rustllvm/Linker.cpp") </ins> .cpp(true) .cpp_link_stdlib(None) // we handle this below .compile("rustllvm");


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

#[allow(missing_copy_implementations)] pub enum OperandBundleDef_opaque {} pub type OperandBundleDefRef = *mut OperandBundleDef_opaque; <ins> #[allow(missing_copy_implementations)] pub enum Linker_opaque {} pub type LinkerRef = *mut Linker_opaque; </ins> pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void); pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

pub fn LLVMRustPrintPasses(); pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool); <del> pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef, bc: *const c_char, len: size_t) -> bool; </del> pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t); pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

CU2: *mut *mut c_void); pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void); pub fn LLVMRustThinLTORemoveAvailableExternally(M: ModuleRef); <ins> pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef; pub fn LLVMRustLinkerAdd(linker: LinkerRef, bytecode: *const c_char, bytecode_len: usize) -> bool; pub fn LLVMRustLinkerFree(linker: LinkerRef); </ins> }


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

// know much about the memory management here so we err on the side of being // save and persist everything with the original module. let mut serialized_bitcode = Vec::new(); <ins> let mut linker = Linker::new(llmod); </ins> for (bc_decoded, name) in serialized_modules { info!("linking {:?}", name); <del> time(cgcx.time_passes, &format!("ll link {:?}", name), || unsafe { </del> <ins> time(cgcx.time_passes, &format!("ll link {:?}", name), || { </ins> let data = bc_decoded.data(); <del> if llvm::LLVMRustLinkInExternalBitcode(llmod, data.as_ptr() as *const libc::c_char, data.len() as libc::size_t) { Ok(()) } else { </del> <ins> linker.add(&data).map_err(|()| { </ins> let msg = format!("failed to load bc of {:?}", name); <del> Err(write::llvm_err(&diag_handler, msg)) } </del> <ins> write::llvm_err(&diag_handler, msg) }) </ins> })?; timeline.record(&format!("link {:?}", name)); serialized_bitcode.push(bc_decoded); } <ins> drop(linker); </ins> cgcx.save_temp_bitcode(&module, "lto.input"); // Internalize everything that *isn't* in our whitelist to help strip out


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

}]) } <ins> struct Linker(llvm::LinkerRef); impl Linker { fn new(llmod: ModuleRef) -> Linker { unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } } fn add(&mut self, bytecode: &[u8]) -> Result<(), ()> { unsafe { if llvm::LLVMRustLinkerAdd(self.0, bytecode.as_ptr() as *const libc::c_char, bytecode.len()) { Ok(()) } else { Err(()) } } } } impl Drop for Linker { fn drop(&mut self) { unsafe { llvm::LLVMRustLinkerFree(self.0); } } } </ins> /// Prepare "thin" LTO to get run on these modules. /// /// The general structure of ThinLTO is quite different from the structure of


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #include "llvm/Linker/Linker.h" #include "rustllvm.h" using namespace llvm; struct RustLinker { Linker L; LLVMContext &Ctx; RustLinker(Module &M) : L(M), Ctx(M.getContext()) {} }; extern "C" RustLinker* LLVMRustLinkerNew(LLVMModuleRef DstRef) { Module *Dst = unwrap(DstRef); auto Ret = llvm::make_unique<RustLinker>(*Dst); return Ret.release(); } extern "C" void LLVMRustLinkerFree(RustLinker *L) { delete L; } extern "C" bool LLVMRustLinkerAdd(RustLinker *L, char *BC, size_t Len) { std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBufferCopy(StringRef(BC, Len)); #if LLVM_VERSION_GE(4, 0) Expected<std::unique_ptr<Module>> SrcOrError = llvm::getLazyBitcodeModule(Buf->getMemBufferRef(), L->Ctx); if (!SrcOrError) { LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str()); return false; } auto Src = std::move(*SrcOrError); #else ErrorOr<std::unique_ptr<Module>> Src = llvm::getLazyBitcodeModule(std::move(Buf), L->Ctx); if (!Src) { LLVMRustSetLastError(Src.getError().message().c_str()); return false; } #endif #if LLVM_VERSION_GE(4, 0) if (L->L.linkInModule(std::move(Src))) { #else if (L->L.linkInModule(std::move(Src.get()))) { #endif LLVMRustSetLastError(""); return false; } return true; } </ins>


Question:
I noticed my project took noticeably longer to build with "lto=true" at some point. I benchmarked link time (touch ; cargo build --release) which appear to blow up as soon as we have several codegen units. link times: So it seem codegen-units=1 makes for bad parallelism while building but speeds up lto because less translation units need to be merged. Maybe it is possible to dynamically use as little codegen units as possible (but still enough to utilize all cores) when building? //cc
Or maybe just don't use multiple codegen units by default when monolithic LTO is enabled.
I think the optimal "balance" for linktime/buildtime with monolithic lto would be to 1) compile all crates with codgen-units=1 as long as we can compile several crates in parallel. 2) if we have to compile a single crate at a time, use ${thread_number} codegen units. However this will probably introduce indeterministic builds depending on the number of threads a host machine has. So a single core machine would optimize better than a 8 core machine when building the same crate with monolithic lto. :/
I made some benchmarks (cpu: i5-2540M dual core), rustc 1.25.0-nightly ( 2018-02-11) `
I believe this is fixed in
er, didn't mean to close yet

} } <del> extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef DstRef, char *BC, size_t Len) { Module *Dst = unwrap(DstRef); std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBufferCopy(StringRef(BC, Len)); #if LLVM_VERSION_GE(4, 0) Expected<std::unique_ptr<Module>> SrcOrError = llvm::getLazyBitcodeModule(Buf->getMemBufferRef(), Dst->getContext()); if (!SrcOrError) { LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str()); return false; } auto Src = std::move(*SrcOrError); #else ErrorOr<std::unique_ptr<Module>> Src = llvm::getLazyBitcodeModule(std::move(Buf), Dst->getContext()); if (!Src) { LLVMRustSetLastError(Src.getError().message().c_str()); return false; } #endif std::string Err; raw_string_ostream Stream(Err); DiagnosticPrinterRawOStream DP(Stream); #if LLVM_VERSION_GE(4, 0) if (Linker::linkModules(*Dst, std::move(Src))) { #else if (Linker::linkModules(*Dst, std::move(Src.get()))) { #endif LLVMRustSetLastError(Err.c_str()); return false; } return true; } </del> // Note that the two following functions look quite similar to the // LLVMGetSectionName function. Sadly, it appears that this function only // returns a char* pointer, which isn't guaranteed to be null-terminated. The


Question:
In , the NLL checker incorrectly judges to be borrowed more than once: I get this error: This works without NLL. This was found while trying to bootstrap rustc with NLL enabled, where it manifests as:
cc
This is a case where our debug flags are very helpful for isolating the cause of a bug like this. Step 1: Remove from the example. Step 2: Incrementally work way to recreating effect of ; my hypothesis is (well, was) that this bug was injected by either mir-borrowck or, somehow, by NLL itself... lets test that hypothesis: I was scratching my head at this point... and then it hit me:
ah, good catch! I guess this is because those mutable borrows are "activating" at this later point? Fascinating.
I'm going to take a look at this bug.
Here's the MIR dump I managed to extract: <details</detailsAnd its corresponding MIR dump looks like the following: <details</detailsIt's probably not that important to look at the MIR dump, because the second line of the RUSTLOG output contained this: Where the last parameter is the value of , which strikes me as odd since a Reserved borrow should be able to be mutated... Oh wait, perhaps I'm wrong? Is this supposed to be activated before being mutated? Note that _4 is a temporary created by MIR that will be used to call .emit() upon.
I think what is happening is not that surprising. I don't think it's related to the flag, really. can prob confirm, but I think it goes something like this. Let's simplify to two arms. I think you'll find this has the same error: I've also labeled the two borrows that occur. Now, the control-flow is something like this: As you can see from the diagram, borrow B2 is already active when borrow B1 is activated. This is in part why the initial RFC for two-phase borrows was limited to the temporaries created for method calls: I wanted to ensure that the temporary was (a) assigned once and (b) that assigned was postdominated by a use which was dominated by the one assignment.
I'm a bit surprised though that this doesn't work now. Maybe PR that limits two-phase borrows hasn't yet made it into nightly? Would be good to verify whether this still activates with the latest master.
So I just rebased against master, and I still run into this exact same bug. which PR were you referring to?
I was referring to cc thoughts?
Hmm I wonder if is still too naive? I’ll try to investigate tomorrow
(I've started looking at the dataflow state, via . The initial information I'm getting from there is confusing me at best, so I'm not sure yet what conclusion to draw from it. Will report more later once I've delved into it a little more deeply.)
So, looking at the dataflow graph (after the dataflow has been run, so the entry sets contain the fixed point results), generated via , and also inspecting the debug output immediately before the error is issued: ... (this data is based on niko's reduced example from The dataflow is concluding, on entry to bb7, that both of the borrow (bb3[2]) and the borrow (bb2[0]) are reserved, and the bb3[2] is also active (since it was used in the invocation of on the bb3 terminator). Thus we get an error that it is not valid to have two simultaneous multiple borrows of . One logical step to take next would be to compare against the dataflow that is derived when we do not have two-phase-borrows turned on. I am going to do that in a bit.
The bug here is probably that we are erroring on having two mutable-borrows of the same path reach the use of in (bb7[0]). I often get the details wrong; I suspect that the issue is that we should solely be detecting conflicts between mutable borrows of a given path at the point where the borrow is taken (i.e. the points were we do ). Or to use the two-phase borrow terminology, the point where the borrow is reserved. Here, we are checking for it at the point where the borrow is activated (the use of in ). And so that explains why we do not see the problem without two-phase borrows turned on. When two-phase borrows are turned off, the check in question is performed at the point of reservation (since activation points are irrelevant when two-phase borrows are turned off).
I believe that is roughly the same , right?
Well, let me read your comments more closely, because I'm confused which borrow is not activating.
there's some differences compared to your diagnosis, but I don't know if they matter. For example, your hypothesized control flow graph has two activations that reach the same control flow point. The actual graph has a reservation on one path (but no activation), and the other path has a reservation and an activation.
So, the thing that is confusing me from the output is that the borrow appears not to be activating. However, I believe that comes from , and that (per your recent changes) ought not to be two-phase. (Note: this might also need )
An update regarding the previous comment: We discussed further on ; to summarize, I think that the intention is that two-phase borrows have no effect on the dataflow -- instead, their effect is meant to be encoded solely in the borrowcheck code itself. Specific to this case, the dataflow only shows a reservation, not an activation, at the statement , because that is indeed just the initial borrow of , not the use of `4, and its the job of the borrowcheck code to actually react properly to that reservation.
After even further discussion on gitter and also in video chat, and came to the conclusion that the answer here is probably not a surgical fix covering a small number of lines, but rather a slightly larger-scale (but mentorable) effort to redo two-phase borrows so that it more closely matches the original intention of the RFC. See

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // run-pass // revisions: lxl nll #![cfg_attr(nll, feature(nll))] struct Foo { x: u32 } impl Foo { fn twiddle(&mut self) -> &mut Self { self } fn twaddle(&mut self) -> &mut Self { self } fn emit(&mut self) { self.x += 1; } } fn main() { let mut foo = Foo { x: 0 }; match 22 { 22 => &mut foo, 44 => foo.twiddle(), _ => foo.twaddle(), }.emit(); } </ins>


Question:
should document that , , and are all mutually exclusive. (and that it may also be the case that none of them are true) Why? Because returns true for both files and symlinks to files, and this tends to make me paranoid that a will share similar characteristics and perhaps claim that both and . The only way to convince myself that FileType's behavior is indeed sane is to write a little test program---again. Surely I can't be alone in this.
is calling not (and equivalent on Windows), so if the path is a symlink, then it returns the results based on what the symlink points to, not the symlink itself. So respects the same mutual exclusivity rules as . But yes, this ought to be documented, especially given that the mutually exclusive behavior may be surprising to Windows developers.
Similar goes for , which should document that these are always false for a obtained by calling on a symlink.
Well you can always call on something that is not a symlink, in which case or could be true.

FileType(self.0.file_type()) } <del> /// Returns whether this metadata is for a directory. </del> <ins> /// Returns whether this metadata is for a directory. The /// result is mutually exclusive to the result of /// [`is_file`], and will be false for symlink metadata /// obtained from [`symlink_metadata`]. /// /// [`is_file`]: struct.Metadata.html#method.is_file /// [`symlink_metadata`]: fn.symlink_metadata.html </ins> /// /// # Examples ///


Question:
should document that , , and are all mutually exclusive. (and that it may also be the case that none of them are true) Why? Because returns true for both files and symlinks to files, and this tends to make me paranoid that a will share similar characteristics and perhaps claim that both and . The only way to convince myself that FileType's behavior is indeed sane is to write a little test program---again. Surely I can't be alone in this.
is calling not (and equivalent on Windows), so if the path is a symlink, then it returns the results based on what the symlink points to, not the symlink itself. So respects the same mutual exclusivity rules as . But yes, this ought to be documented, especially given that the mutually exclusive behavior may be surprising to Windows developers.
Similar goes for , which should document that these are always false for a obtained by calling on a symlink.
Well you can always call on something that is not a symlink, in which case or could be true.

#[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() } <del> /// Returns whether this metadata is for a regular file. </del> <ins> /// Returns whether this metadata is for a regular file. The /// result is mutually exclusive to the result of /// [`is_dir`], and will be false for symlink metadata /// obtained from [`symlink_metadata`]. /// /// [`is_dir`]: struct.Metadata.html#method.is_dir /// [`symlink_metadata`]: fn.symlink_metadata.html </ins> /// /// # Examples ///


Question:
should document that , , and are all mutually exclusive. (and that it may also be the case that none of them are true) Why? Because returns true for both files and symlinks to files, and this tends to make me paranoid that a will share similar characteristics and perhaps claim that both and . The only way to convince myself that FileType's behavior is indeed sane is to write a little test program---again. Surely I can't be alone in this.
is calling not (and equivalent on Windows), so if the path is a symlink, then it returns the results based on what the symlink points to, not the symlink itself. So respects the same mutual exclusivity rules as . But yes, this ought to be documented, especially given that the mutually exclusive behavior may be surprising to Windows developers.
Similar goes for , which should document that these are always false for a obtained by calling on a symlink.
Well you can always call on something that is not a symlink, in which case or could be true.

} impl FileType { <del> /// Test whether this file type represents a directory. </del> <ins> /// Test whether this file type represents a directory. The /// result is mutually exclusive to the results of /// [`is_file`] and [`is_symlink`]; only zero or one of these /// tests may pass. /// /// [`is_file`]: struct.FileType.html#method.is_file /// [`is_symlink`]: struct.FileType.html#method.is_symlink </ins> /// /// # Examples ///


Question:
should document that , , and are all mutually exclusive. (and that it may also be the case that none of them are true) Why? Because returns true for both files and symlinks to files, and this tends to make me paranoid that a will share similar characteristics and perhaps claim that both and . The only way to convince myself that FileType's behavior is indeed sane is to write a little test program---again. Surely I can't be alone in this.
is calling not (and equivalent on Windows), so if the path is a symlink, then it returns the results based on what the symlink points to, not the symlink itself. So respects the same mutual exclusivity rules as . But yes, this ought to be documented, especially given that the mutually exclusive behavior may be surprising to Windows developers.
Similar goes for , which should document that these are always false for a obtained by calling on a symlink.
Well you can always call on something that is not a symlink, in which case or could be true.

pub fn is_dir(&self) -> bool { self.0.is_dir() } /// Test whether this file type represents a regular file. <ins> /// The result is  mutually exclusive to the results of /// [`is_dir`] and [`is_symlink`]; only zero or one of these /// tests may pass. /// /// [`is_dir`]: struct.FileType.html#method.is_dir /// [`is_symlink`]: struct.FileType.html#method.is_symlink </ins> /// /// # Examples ///


Question:
should document that , , and are all mutually exclusive. (and that it may also be the case that none of them are true) Why? Because returns true for both files and symlinks to files, and this tends to make me paranoid that a will share similar characteristics and perhaps claim that both and . The only way to convince myself that FileType's behavior is indeed sane is to write a little test program---again. Surely I can't be alone in this.
is calling not (and equivalent on Windows), so if the path is a symlink, then it returns the results based on what the symlink points to, not the symlink itself. So respects the same mutual exclusivity rules as . But yes, this ought to be documented, especially given that the mutually exclusive behavior may be surprising to Windows developers.
Similar goes for , which should document that these are always false for a obtained by calling on a symlink.
Well you can always call on something that is not a symlink, in which case or could be true.

pub fn is_file(&self) -> bool { self.0.is_file() } /// Test whether this file type represents a symbolic link. <ins> /// The result is mutually exclusive to the results of /// [`is_dir`] and [`is_file`]; only zero or one of these /// tests may pass. </ins> /// /// The underlying [`Metadata`] struct needs to be retrieved /// with the [`fs::symlink_metadata`] function and not the