Question:
The documentation for with say "no re-ordering of reads and writes across this point is allowed". As I understand it, for a single thread doesn't give anything more than . E.g., a store before the fence could be moved past a load after then fence. Is that correct? cc
Hmm, that's a good point, though the details are a little subtle. From the : I think what this translates into is that guarantees that: no subsequent operations can be moved before this operation if it is a load, and no operations can be moved after this operation if it is a store. The italic parts there aren't present in the current documentation, so that should probably be rectified. I think some annotated source code would really help here!
It actually depends on the other operation, does it not? stores after the fence can be moved up, but stores cannot. TBH I have a hard time thinking in terms of reorderings; I usually think in terms of what actually happens in the underlying memory model. Some of these models can be fully characterized by the allowed reorderings, but not all of them can (as far as we know). And anyway, SC fences are broken in the C11 memory model and probably going to change in the next version, so...^^ On top of that, all are in a total order, and that is the entire point of . (The website says it but you left it away in your quote. Just making sure nobody thinks that a load is the same as an load. It is not.)
I'm actually not entirely sure about that. Another store to the same memory location shouldn't be ordered before, but I don't see from the reference text why an unrelated store with couldn't be. I'd be happy for this to be rephrased this in terms of the memory model, but I'm not entirely sure how we'd even do that. Proposals welcome. I think talking about what can and cannot happen, with examples, is probably the most understandable way to present what the different orderings do. I left off the total order part because it didn't seem directly related to the original question. But you're right that it's a vital part of that shouldn't get lost in the docs!
It says The sequentially-consistent ordering consists of all operation, across all locations, and the order in which they are observed must be consistent across all threads. In particular, if one thread performs two operations (i.e., they are ordered by program-order), then the order in which it does them must match the order in which every other thread observes them. That rules out reordering them. This is the sole justification for the existence of .
Yes, good point. So how about we move the bullet point to bottom and change it to say

} } <del> /// A compiler memory fence. </del> <ins> /// A "compiler-only" atomic fence. </ins> /// <del> /// `compiler_fence` does not emit any machine code, but restricts the kinds /// of memory re-ordering the compiler is allowed to do. Specifically, depending on /// the given [`Ordering`] semantics, the compiler may be disallowed from moving reads /// or writes from before or after the call to the other side of the call to /// `compiler_fence`. Note that it does **not** prevent the *hardware* /// from doing such re-ordering. This is not a problem in a single-threaded, /// execution context, but when other threads may modify memory at the same /// time, stronger synchronization primitives such as [`fence`] are required. </del> <ins> /// Like [`fence`], this function establishes synchronization with other atomic operations and /// fences. However, unlike [`fence`], `compiler_fence` only establishes synchronization with /// operations *in the same thread*. This may at first sound rather useless, since code within a /// thread is typically already totally ordered and does not need any further synchronization. /// However, there are cases where code can run on the same thread without being ordered: /// - The most common case is that of a *signal handler*: a signal handler runs in the same thread ///   as the code it interrupted, but it is not ordered with respect to that code. `compiler_fence` ///   can be used to establish synchronization between a thread and its signal handler, the same way ///   that `fence` can be used to establish synchronization across threads. /// - Similar situations can arise in embedded programming with interrupt handlers, or in custom ///   implementations of preemptive green threads. In general, `compiler_fence` can establish ///   synchronization with code that is guaranteed to run on the same hardware CPU. </ins> /// <del> /// The re-ordering prevented by the different ordering semantics are: </del> <ins> /// See [`fence`] for how a fence can be used to achieve synchronization. Note that just like /// [`fence`], synchronization still requires atomic operations to be used in both threads -- it is /// not possible to perform synchronization entirely with fences and non-atomic operations. </ins> /// <del> ///  - with [`SeqCst`], no re-ordering of reads and writes across this point is allowed. ///  - with [`Release`], preceding reads and writes cannot be moved past subsequent writes. ///  - with [`Acquire`], subsequent reads and writes cannot be moved ahead of preceding reads. ///  - with [`AcqRel`], both of the above rules are enforced. </del> <ins> /// `compiler_fence` does not emit any machine code, but restricts the kinds of memory re-ordering /// the compiler is allowed to do. `compiler_fence` corresponds to [`atomic_signal_fence`] in C and /// C++. </ins> /// <del> /// `compiler_fence` is generally only useful for preventing a thread from /// racing *with itself*. That is, if a given thread is executing one piece /// of code, and is then interrupted, and starts executing code elsewhere /// (while still in the same thread, and conceptually still on the same /// core). In traditional programs, this can only occur when a signal /// handler is registered. In more low-level code, such situations can also /// arise when handling interrupts, when implementing green threads with /// pre-emption, etc. Curious readers are encouraged to read the Linux kernel's /// discussion of [memory barriers]. </del> <ins> /// [`atomic_signal_fence`]: https://en.cppreference.com/w/cpp/atomic/atomic_signal_fence </ins> /// /// # Panics ///


Question:
The documentation for with say "no re-ordering of reads and writes across this point is allowed". As I understand it, for a single thread doesn't give anything more than . E.g., a store before the fence could be moved past a load after then fence. Is that correct? cc
Hmm, that's a good point, though the details are a little subtle. From the : I think what this translates into is that guarantees that: no subsequent operations can be moved before this operation if it is a load, and no operations can be moved after this operation if it is a store. The italic parts there aren't present in the current documentation, so that should probably be rectified. I think some annotated source code would really help here!
It actually depends on the other operation, does it not? stores after the fence can be moved up, but stores cannot. TBH I have a hard time thinking in terms of reorderings; I usually think in terms of what actually happens in the underlying memory model. Some of these models can be fully characterized by the allowed reorderings, but not all of them can (as far as we know). And anyway, SC fences are broken in the C11 memory model and probably going to change in the next version, so...^^ On top of that, all are in a total order, and that is the entire point of . (The website says it but you left it away in your quote. Just making sure nobody thinks that a load is the same as an load. It is not.)
I'm actually not entirely sure about that. Another store to the same memory location shouldn't be ordered before, but I don't see from the reference text why an unrelated store with couldn't be. I'd be happy for this to be rephrased this in terms of the memory model, but I'm not entirely sure how we'd even do that. Proposals welcome. I think talking about what can and cannot happen, with examples, is probably the most understandable way to present what the different orderings do. I left off the total order part because it didn't seem directly related to the original question. But you're right that it's a vital part of that shouldn't get lost in the docs!
It says The sequentially-consistent ordering consists of all operation, across all locations, and the order in which they are observed must be consistent across all threads. In particular, if one thread performs two operations (i.e., they are ordered by program-order), then the order in which it does them must match the order in which every other thread observes them. That rules out reordering them. This is the sole justification for the existence of .
Yes, good point. So how about we move the bullet point to bottom and change it to say

///     } /// } /// ``` <del> /// /// [memory barriers]: https://www.kernel.org/doc/Documentation/memory-barriers.txt </del> #[inline] #[stable(feature = "compiler_fences", since = "1.21.0")] #[rustc_diagnostic_item = "compiler_fence"]


Question: Given: results in: Is this intentional due to some soundness issue with having it otherwise? (I cannot think of any...) We could fix this by attaching to manually. While having be structurally matchable is quite boring and useless on its lonesome it prevents other types that contain it from being structurally matchable. (not likely to occur very often, but when it occur it seems like it would be annoying...) r? cc

#![feature(const_transmute)] #![feature(reverse_bits)] #![feature(non_exhaustive)] <ins> #![feature(structural_match)] </ins> #[prelude_import] #[allow(unused)]


Question: Given: results in: Is this intentional due to some soundness issue with having it otherwise? (I cannot think of any...) We could fix this by attaching to manually. While having be structurally matchable is quite boring and useless on its lonesome it prevents other types that contain it from being structurally matchable. (not likely to occur very often, but when it occur it seems like it would be annoying...) r? cc

/// /// [drop check]: ../../nomicon/dropck.html #[lang = "phantom_data"] <ins> #[structural_match] </ins> #[stable(feature = "rust1", since = "1.0.0")] pub struct PhantomData<T:?Sized>;


Question: Given: results in: Is this intentional due to some soundness issue with having it otherwise? (I cannot think of any...) We could fix this by attaching to manually. While having be structurally matchable is quite boring and useless on its lonesome it prevents other types that contain it from being structurally matchable. (not likely to occur very often, but when it occur it seems like it would be annoying...) r? cc

<ins> // run-pass // This file checks that `PhantomData` is considered structurally matchable. use std::marker::PhantomData; fn main() { let mut count = 0; // A type which is not structurally matchable: struct NotSM; // And one that is: #[derive(PartialEq, Eq)] struct SM; // Check that SM is #[structural_match]: const CSM: SM = SM; match SM { CSM => count += 1, }; // Check that PhantomData<T> is #[structural_match] even if T is not. const CPD1: PhantomData<NotSM> = PhantomData; match PhantomData { CPD1 => count += 1, }; // Check that PhantomData<T> is #[structural_match] when T is. const CPD2: PhantomData<SM> = PhantomData; match PhantomData { CPD2 => count += 1, }; // Check that a type which has a PhantomData is `#[structural_match]`. #[derive(PartialEq, Eq, Default)] struct Foo { alpha: PhantomData<NotSM>, beta: PhantomData<SM>, } const CFOO: Foo = Foo { alpha: PhantomData, beta: PhantomData, }; match Foo::default() { CFOO => count += 1, }; // Final count must be 4 now if all assert_eq!(count, 4); } </ins>


Question: The output from , at the top of the page for a or a , etc., includes a line like, Clicking the on a browser w/ restrictive cookie settings (which typically includes ) results in an error similar to the following: Additionally, the section fails to expand or contract, as the exception isn't handled. is attempting to store the collapse/expand state, s.t. later visits to the page presumably maintain that state for the user's convenience. I browse the web with an admittedly somewhat atypical setup: I whitelist cookies. , in most browsers, counts, since it is a similar mechanism of persistence. I think Rust's use of here is fine, but I would request that, if is forbidden by the user agent, that the documentation gracefully "degrade" to just expanding or contracting the requested item, but not persist it. As it is, the JS crashes while storing the state, and appears to never make it to actually expanding/contracting the item.

return false; } <ins> function usableLocalStorage() { // Check if the browser supports localStorage at all: if (typeof(Storage) === "undefined") { return false; } // Check if we can access it; this access will fail if the browser // preferences deny access to localStorage, e.g., to prevent storage of // "cookies" (or cookie-likes, as is the case here). try { window.localStorage; } catch(err) { // Storage is supported, but browser preferences deny access to it. return false; } return true; } </ins> function updateLocalStorage(name, value) { <del> if (typeof(Storage) !== "undefined") { </del> <ins> if (usableLocalStorage()) { </ins> localStorage[name] = value; } else { // No Web Storage support so we do nothing


Question: The output from , at the top of the page for a or a , etc., includes a line like, Clicking the on a browser w/ restrictive cookie settings (which typically includes ) results in an error similar to the following: Additionally, the section fails to expand or contract, as the exception isn't handled. is attempting to store the collapse/expand state, s.t. later visits to the page presumably maintain that state for the user's convenience. I browse the web with an admittedly somewhat atypical setup: I whitelist cookies. , in most browsers, counts, since it is a similar mechanism of persistence. I think Rust's use of here is fine, but I would request that, if is forbidden by the user agent, that the documentation gracefully "degrade" to just expanding or contracting the requested item, but not persist it. As it is, the JS crashes while storing the state, and appears to never make it to actually expanding/contracting the item.

} function getCurrentValue(name) { <del> if (typeof(Storage) !== "undefined" && localStorage[name] !== undefined) { </del> <ins> if (usableLocalStorage() && localStorage[name] !== undefined) { </ins> return localStorage[name]; } return null;


Question:
Spawned off of 's on :
to be clear: we don't need to use to reproduce the problem, right? I.e. hypothetically examples exist that don't use that feature? In particular I know this problem is in some way related to , which is definitely a true regression of stable code.
Right, this here is not really a regression. It is just an ICE that should be an error and it is fixed by We can probably do this without const_let, but I couldn't come up with an example.
A user is the
I have tried to reduce the problem. This repository is smaller, but still fails on : . The same crate builds on stable.
I think you are encountering which has a fix in (making everything work again) This issue is different, even though the symptom is the same right now. When this issue is fixed (via ), the ICE will become a hard error.

if self.alloc_map.contains_key(&alloc) { // Not yet interned, so proceed recursively self.intern_static(alloc, mutability)?; <ins> } else if self.dead_alloc_map.contains_key(&alloc) { // dangling pointer return err!(ValidationFailure( "encountered dangling pointer in final constant".into(), )) </ins> } } Ok(())


Question:
Spawned off of 's on :
to be clear: we don't need to use to reproduce the problem, right? I.e. hypothetically examples exist that don't use that feature? In particular I know this problem is in some way related to , which is definitely a true regression of stable code.
Right, this here is not really a regression. It is just an ICE that should be an error and it is fixed by We can probably do this without const_let, but I couldn't come up with an example.
A user is the
I have tried to reduce the problem. This repository is smaller, but still fails on : . The same crate builds on stable.
I think you are encountering which has a fix in (making everything work again) This issue is different, even though the symptom is the same right now. When this issue is fixed (via ), the ICE will become a hard error.

<ins> // https://github.com/rust-lang/rust/issues/55223 #![feature(const_let)] union Foo<'a> { y: &'a (), long_live_the_unit: &'static (), } const FOO: &() = { //~ ERROR any use of this value will cause an error let y = (); unsafe { Foo { y: &y }.long_live_the_unit } }; fn main() {} </ins>


Question:
Spawned off of 's on :
to be clear: we don't need to use to reproduce the problem, right? I.e. hypothetically examples exist that don't use that feature? In particular I know this problem is in some way related to , which is definitely a true regression of stable code.
Right, this here is not really a regression. It is just an ICE that should be an error and it is fixed by We can probably do this without const_let, but I couldn't come up with an example.
A user is the
I have tried to reduce the problem. This repository is smaller, but still fails on : . The same crate builds on stable.
I think you are encountering which has a fix in (making everything work again) This issue is different, even though the symptom is the same right now. When this issue is fixed (via ), the ICE will become a hard error.

<ins> error: any use of this value will cause an error --> $DIR/dangling-alloc-id-ice.rs:10:1 | LL | / const FOO: &() = { //~ ERROR any use of this value will cause an error LL | |     let y = (); LL | |     unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; | |__^ type validation failed: encountered dangling pointer in final constant | = note: #[deny(const_err)] on by default error: aborting due to previous error </ins>


Question:
Spawned off of 's on :
to be clear: we don't need to use to reproduce the problem, right? I.e. hypothetically examples exist that don't use that feature? In particular I know this problem is in some way related to , which is definitely a true regression of stable code.
Right, this here is not really a regression. It is just an ICE that should be an error and it is fixed by We can probably do this without const_let, but I couldn't come up with an example.
A user is the
I have tried to reduce the problem. This repository is smaller, but still fails on : . The same crate builds on stable.
I think you are encountering which has a fix in (making everything work again) This issue is different, even though the symptom is the same right now. When this issue is fixed (via ), the ICE will become a hard error.

<ins> #![feature(const_let)] const FOO: *const u32 = { //~ ERROR any use of this value will cause an error let x = 42; &x }; fn main() { let x = FOO; } </ins>


Question:
Spawned off of 's on :
to be clear: we don't need to use to reproduce the problem, right? I.e. hypothetically examples exist that don't use that feature? In particular I know this problem is in some way related to , which is definitely a true regression of stable code.
Right, this here is not really a regression. It is just an ICE that should be an error and it is fixed by We can probably do this without const_let, but I couldn't come up with an example.
A user is the
I have tried to reduce the problem. This repository is smaller, but still fails on : . The same crate builds on stable.
I think you are encountering which has a fix in (making everything work again) This issue is different, even though the symptom is the same right now. When this issue is fixed (via ), the ICE will become a hard error.

<ins> error: any use of this value will cause an error --> $DIR/dangling_raw_ptr.rs:3:1 | LL | / const FOO: *const u32 = { //~ ERROR any use of this value will cause an error LL | |     let x = 42; LL | |     &x LL | | }; | |__^ type validation failed: encountered dangling pointer in final constant | = note: #[deny(const_err)] on by default error: aborting due to previous error </ins>


Question:
On the surface, these functions seem very similar. When is it appropriate to use one vs. the other?
Anyone able to describe the differences and use-cases for these functions? I'd be willing to add docs for this, I just don't know when to use either
My understanding for these two functions is: Both are probably not needed in general. While can be a debugging utility in some situations they're largely only needed when writing some form of a spin loop. The function is for very tight spin loops. It is ideally used in situations where you know that a contended lock is held by another thread and you're sure the other thread is running on a different CPU. If the other thread holding a lock (or whatever condition is being waited on in a spin loop) isn't actually running then spinning with this function will eat the entire time slice allocated for the OS until that thread starts running again. This is a CPU instruction on some platforms, and a noop on other platforms. The function invokes the OS scheduler, asking the current thread to basically be put into the back of the run queue. This is best for spin loops where you're pretty certain the lock/condition will become available soon, but you're not sure if the thread holding the lock is running or not. I believe the general wisdom is that on lock contention you for a bit, then a little bit, and finally sleep for real. All of these are pretty advanced functions, though, and the documentation should be very clear that these are largely just current-practice-guidelines and benchmarking and further understanding is highly encouraged
One use case for is a bunch of threads blocked on . potentially needs a large number of cycles to execute but it is also executed in performance-sensitive code (graphics, crypto, etc.) where a full or would not be wanted.
Are you still interested in writing docs for this?
I still don't feel confident to write them given my current level of understanding with these APIs. But if you want to try, go for it!
I will give it a try! I am sure others will correct me if I write some things that are wrong :) I hope I'll be able to deliver a PR somewhere this week.
It seems like you always pop up on my screen when people are talking about technical details so I thought you might be the right man for this question :) When diving into the details of I found this: So basically does a call to which is defined like this: Question: What is the difference in semantics between and ? Or to ask it differently, why should we not deprecate and only use ? The documentation of both functions is exactly the same as well. (Aside being experimental). Or we could maybe re-export as in ?
I did an attempt! I hope it clarifies some things. I didn't edit the documentation to not bloat the documentation there too much. But if that is desired as well, please let me know. The pull is here:

intrinsics::unreachable() } <del> /// Save power or switch hyperthreads in a busy-wait spin-loop. </del> <ins> /// Signals the processor that it is entering a busy-wait spin-loop. </ins> /// <del> /// This function is deliberately more primitive than /// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and /// does not directly yield to the system's scheduler. /// In some cases it might be useful to use a combination of both functions. /// Careful benchmarking is advised. </del> <ins> /// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving /// power or switching hyper-threads. </ins> /// <del> /// On some platforms this function may not do anything at all. </del> <ins> /// This function is different than [`std::thread::yield_now`] which directly yields to the /// system's scheduler, whereas `spin_loop` only signals the processor that it is entering a /// busy-wait spin-loop without yielding control to the system's scheduler. /// /// Using a busy-wait spin-loop with `spin_loop` is ideally used in situations where a /// contended lock is held by another thread executed on a different CPU and where the waiting /// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's /// scheduler, no overhead for switching threads occurs. However, if the thread holding the /// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice /// before switching to the thread that holds the lock. If the contending lock is held by a thread /// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to /// use [`std::thread::yield_now`]. /// /// **Note**: On platforms that do not support receiving spin-loop hints this function does not /// do anything at all. /// /// [`std::thread::yield_now`]: ../../std/thread/fn.yield_now.html </ins> #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() {


Question:
On the surface, these functions seem very similar. When is it appropriate to use one vs. the other?
Anyone able to describe the differences and use-cases for these functions? I'd be willing to add docs for this, I just don't know when to use either
My understanding for these two functions is: Both are probably not needed in general. While can be a debugging utility in some situations they're largely only needed when writing some form of a spin loop. The function is for very tight spin loops. It is ideally used in situations where you know that a contended lock is held by another thread and you're sure the other thread is running on a different CPU. If the other thread holding a lock (or whatever condition is being waited on in a spin loop) isn't actually running then spinning with this function will eat the entire time slice allocated for the OS until that thread starts running again. This is a CPU instruction on some platforms, and a noop on other platforms. The function invokes the OS scheduler, asking the current thread to basically be put into the back of the run queue. This is best for spin loops where you're pretty certain the lock/condition will become available soon, but you're not sure if the thread holding the lock is running or not. I believe the general wisdom is that on lock contention you for a bit, then a little bit, and finally sleep for real. All of these are pretty advanced functions, though, and the documentation should be very clear that these are largely just current-practice-guidelines and benchmarking and further understanding is highly encouraged
One use case for is a bunch of threads blocked on . potentially needs a large number of cycles to execute but it is also executed in performance-sensitive code (graphics, crypto, etc.) where a full or would not be wanted.
Are you still interested in writing docs for this?
I still don't feel confident to write them given my current level of understanding with these APIs. But if you want to try, go for it!
I will give it a try! I am sure others will correct me if I write some things that are wrong :) I hope I'll be able to deliver a PR somewhere this week.
It seems like you always pop up on my screen when people are talking about technical details so I thought you might be the right man for this question :) When diving into the details of I found this: So basically does a call to which is defined like this: Question: What is the difference in semantics between and ? Or to ask it differently, why should we not deprecate and only use ? The documentation of both functions is exactly the same as well. (Aside being experimental). Or we could maybe re-export as in ?
I did an attempt! I hope it clarifies some things. I didn't edit the documentation to not bloat the documentation there too much. But if that is desired as well, please let me know. The pull is here:

use hint::spin_loop; <del> /// Save power or switch hyperthreads in a busy-wait spin-loop. </del> <ins> /// Signals the processor that it is entering a busy-wait spin-loop. </ins> /// <del> /// This function is deliberately more primitive than /// [`std::thread::yield_now`](../../../std/thread/fn.yield_now.html) and /// does not directly yield to the system's scheduler. /// In some cases it might be useful to use a combination of both functions. /// Careful benchmarking is advised. </del> <ins> /// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving /// power or switching hyper-threads. </ins> /// <del> /// On some platforms this function may not do anything at all. </del> <ins> /// This function is different than [`std::thread::yield_now`] which directly yields to the /// system's scheduler, whereas `spin_loop_hint` only signals the processor that it is entering a /// busy-wait spin-loop without yielding control to the system's scheduler. /// /// Using a busy-wait spin-loop with `spin_loop_hint` is ideally used in situations where a /// contended lock is held by another thread executed on a different CPU and where the waiting /// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's /// scheduler, no overhead for switching threads occurs. However, if the thread holding the /// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice /// before switching to the thread that holds the lock. If the contending lock is held by a thread /// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to /// use [`std::thread::yield_now`]. /// /// **Note**: On platforms that do not support receiving spin-loop hints this function does not /// do anything at all. /// /// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html </ins> #[inline] #[stable(feature = "spin_loop_hint", since = "1.24.0")] pub fn spin_loop_hint() {


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

self.unclosed_delims.extend(snapshot.unclosed_delims.clone()); } <ins> pub fn unclosed_delims(&self) -> &[UnmatchedBrace] { &self.unclosed_delims } </ins> /// Create a snapshot of the `Parser`. pub(super) fn create_snapshot_for_diagnostic(&self) -> SnapshotParser<'a> { let mut snapshot = self.clone();


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; <ins> use rustc_parse::maybe_new_parser_from_source_str; use rustc_parse::parser::attr::InnerAttrPolicy; </ins> use rustc_session::config::{self, CrateType, ErrorOutputType}; <ins> use rustc_session::parse::ParseSess; </ins> use rustc_session::{lint, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap;


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

edition: Edition, test_id: Option<&str>, ) -> (String, usize, bool) { <del> let (crate_attrs, everything_else, crates) = partition_source(s); </del> <ins> let (crate_attrs, everything_else, crates) = partition_source(s, edition); </ins> let everything_else = everything_else.trim(); let mut line_offset = 0; let mut prog = String::new();


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

rustc_span::create_session_if_not_set_then(edition, |_| { use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::Handler; <del> use rustc_parse::maybe_new_parser_from_source_str; </del> use rustc_parse::parser::ForceCollect; <del> use rustc_session::parse::ParseSess; </del> use rustc_span::source_map::FilePathMapping; let filename = FileName::anon_source_code(s);


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

(prog, line_offset, supports_color) } <del> // FIXME(aburka): use a real parser to deal with multiline attributes fn partition_source(s: &str) -> (String, String, String) { </del> <ins> fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { if source.is_empty() { // Empty content so nothing to check in here... return true; } rustc_span::create_session_if_not_set_then(edition, |_| { let filename = FileName::anon_source_code(source); let sess = ParseSess::with_silent_emitter(None); let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) { Ok(p) => p, Err(_) => { debug!("Cannot build a parser to check mod attr so skipping..."); return true; } }; // If a parsing error happened, it's very likely that the attribute is incomplete. if !parser.parse_attribute(InnerAttrPolicy::Permitted).is_ok() { return false; } // We now check if there is an unclosed delimiter for the attribute. To do so, we look at // the `unclosed_delims` and see if the opening square bracket was closed. parser .unclosed_delims() .get(0) .map(|unclosed| { unclosed.unclosed_span.map(|s| s.lo()).unwrap_or(BytePos(0)) != BytePos(2) }) .unwrap_or(true) }) } fn partition_source(s: &str, edition: Edition) -> (String, String, String) { </ins> #[derive(Copy, Clone, PartialEq)] enum PartitionState { Attrs,


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

let mut crates = String::new(); let mut after = String::new(); <ins> let mut mod_attr_pending = String::new(); </ins> for line in s.lines() { let trimline = line.trim();


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

// shunted into "everything else" match state { PartitionState::Attrs => { <del> state = if trimline.starts_with("#![") || trimline.chars().all(|c| c.is_whitespace()) </del> <ins> state = if trimline.starts_with("#![") { if !check_if_attr_is_complete(line, edition) { mod_attr_pending = line.to_owned(); } else { mod_attr_pending.clear(); } PartitionState::Attrs } else if trimline.chars().all(|c| c.is_whitespace()) </ins> || (trimline.starts_with("//") && !trimline.starts_with("///")) { PartitionState::Attrs


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

{ PartitionState::Crates } else { <del> PartitionState::Other </del> <ins> // First we check if the previous attribute was "complete"... if !mod_attr_pending.is_empty() { // If not, then we append the new line into the pending attribute to check // if this time it's complete... mod_attr_pending.push_str(line); if !trimline.is_empty() && check_if_attr_is_complete(line, edition) { // If it's complete, then we can clear the pending content. mod_attr_pending.clear(); } // In any case, this is considered as `PartitionState::Attrs` so it's // prepended before rustdoc's inserts. PartitionState::Attrs } else { PartitionState::Other } </ins> }; } PartitionState::Crates => {


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

<ins> // compile-flags:--test // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // normalize-stdout-test "finished in d+.d+s" -> "finished in $$TIME" // check-pass /// ``` /// # #![cfg_attr(not(dox), deny(missing_abi, /// # non_ascii_idents))] /// /// pub struct Bar; /// ``` pub struct Bar; </ins>


Question:
With following doctest, where the cfg attribute spans multiple lines, the final program is invalid: the wrapping method doesn't take into account the dangling line that closes the attribute. rust /// # #![cfgattr(not(dox), feature(cfgtargetfeature, targetfeature, /// # stdsimd))] /// /// fn foo() { /// let mut dst = [0]; /// addquickly(&[1], &[2], &mut dst); /// asserteq!(dst[0], 3); /// } ///
cc
cc
I don't see a message associated with the stack trace, is that missing?
The problem lies in how rustdoc parses doctests. It scans lines for crate-level attributes and statements, but it doesn't do anything more intelligent than checking the beginning of each line: We recently changed the parsing for and detection to use the libsyntax parser, but this initial scan is still a string-based search. The way to fix the test in the OP is to actually remove the part of it - rustdoc doesn't pass on any information into doctest compilation, so those features are going to be enabled regardless.
This is the associated message:

<ins> running 1 test test $DIR/doc-comment-multi-line-cfg-attr.rs - Bar (line 6) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME </ins>


Question:
This is intended to be a tracking issue to incorporate into the current beta branch for the Rust 2018 release, as we'll be relying on that in documentation that we're writing.
The Cargo backport is happening here - , and after that needs a PR to the beta branch in this repository
This is now submitted as
Done!

<del> Subproject commit 5d967343acae16fd7b53a61e6cd4e93a1ac6f199 </del> <ins> Subproject commit 569507ef2beefcce4b666af41e09276f06445e96 </ins>


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

/// kept separate because of issue #42760. #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] pub enum DocFragment { <del> // FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once // hoedown is completely removed from rustdoc. </del> /// A doc fragment created from a `///` or `//!` doc comment. SugaredDoc(usize, syntax_pos::Span, String), /// A doc fragment created from a "raw" `#[doc=""]` attribute.


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

start.to(end) } <ins> /// Reports a resolution failure diagnostic. /// /// Ideally we can report the diagnostic with the actual span in the source where the link failure /// occurred. However, there's a mismatch between the span in the source code and the span in the /// markdown, so we have to do a bit of work to figure out the correspondence. /// /// It's not too hard to find the span for sugared doc comments (`///` and `/**`), because the /// source will match the markdown exactly, excluding the comment markers. However, it's much more /// difficult to calculate the spans for unsugared docs, because we have to deal with escaping and /// other source features. So, we attempt to find the exact source span of the resolution failure /// in sugared docs, but use the span of the documentation attributes themselves for unsugared /// docs. Because this span might be overly large, we display the markdown line containing the /// failure as a note. </ins> fn resolution_failure( cx: &DocContext, attrs: &Attributes,


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

let sp = span_of_attrs(attrs); let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str); <del> let code_dox = sp.to_src(cx); let doc_comment_padding = 3; </del> let mut diag = if let Some(link_range) = link_range { <del> // blah blah blahnblahnblah [blah] blah blahnblah blah //                       ^    ~~~~~~ //                       |    link_range //                       last_new_line_offset let mut diag; if dox.lines().count() == code_dox.lines().count() { let line_offset = dox[..link_range.start].lines().count(); // The span starts in the `///`, so we don't have to account for the leading whitespace. let code_dox_len = if line_offset <= 1 { doc_comment_padding } else { // The first `///`. doc_comment_padding + // Each subsequent leading whitespace and `///`. code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| { sum + doc_comment_padding + line.len() - line.trim_start().len() }) }; </del> <ins> let src = cx.sess().source_map().span_to_snippet(sp); let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag { DocFragment::SugaredDoc(..) => true, _ => false, }); if let (Ok(src), true) = (src, is_all_sugared_doc) { // The number of markdown lines up to and including the resolution failure. let num_lines = dox[..link_range.start].lines().count(); // We use `split_terminator('n')` instead of `lines()` when counting bytes to ensure // that DOS-style line endings do not cause the spans to be calculated incorrectly. let mut src_lines = src.split_terminator('n'); let mut md_lines = dox.split_terminator('n').take(num_lines).peekable(); // The number of bytes from the start of the source span to the resolution failure that // are *not* part of the markdown, like comment markers. let mut extra_src_bytes = 0; while let Some(md_line) = md_lines.next() { loop { let source_line = src_lines .next() .expect("could not find markdown line in source"); match source_line.find(md_line) { Some(offset) => { extra_src_bytes += if md_lines.peek().is_some() { source_line.len() - md_line.len() } else { offset }; break; } None => { // Since this is a source line that doesn't include a markdown line, // we have to count the newline that we split from earlier. extra_src_bytes += source_line.len() + 1; } } } } </ins> <del> // Extract the specific span. </del> let sp = sp.from_inner_byte_pos( <del> link_range.start + code_dox_len, link_range.end + code_dox_len, </del> <ins> link_range.start + extra_src_bytes, link_range.end + extra_src_bytes, </ins> ); <del> diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, NodeId::from_u32(0), sp, &msg); </del> <ins> let mut diag = cx.tcx.struct_span_lint_node( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, NodeId::from_u32(0), sp, &msg, ); </ins> diag.span_label(sp, "cannot be resolved, ignoring"); <ins> diag </ins> } else { <del> diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, NodeId::from_u32(0), sp, &msg); </del> <ins> let mut diag = cx.tcx.struct_span_lint_node( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, NodeId::from_u32(0), sp, &msg, ); // blah blah blahnblahnblah [blah] blah blahnblah blah //                       ^     ~~~~ //                       |     link_range //                       last_new_line_offset </ins> let last_new_line_offset = dox[..link_range.start].rfind('n').map_or(0, |n| n + 1); let line = dox[last_new_line_offset..].lines().next().unwrap_or("");


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

before=link_range.start - last_new_line_offset, found=link_range.len(), )); <ins> diag </ins> } <del> diag </del> } else { cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, NodeId::from_u32(0),


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

<ins> intra-links-warning-crlf.rs eol=crlf </ins>


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

<ins> // ignore-tidy-cr // compile-pass // This file checks the spans of intra-link warnings in a file with CRLF line endings. The // .gitattributes file in this directory should enforce it. /// [error] pub struct A; /// /// docs [error1] /// docs [error2] /// pub struct B; /** * This is a multi-line comment. * * It also has an [error]. */ pub struct C; </ins>


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

<ins> warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:8:6 | LL | /// [error] |      ^^^^^ cannot be resolved, ignoring | = note: #[warn(intra_doc_link_resolution_failure)] on by default = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error1]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:12:11 | LL | /// docs [error1] |           ^^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error2]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:14:11 | LL | /// docs [error2] |           ^^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:21:20 | LL |  * It also has an [error]. |                    ^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` </ins>


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

} } f!("Foonbar [BarF] barnbaz"); <ins> /** # for example, * * time to introduce a link [error]*/ pub struct A; /** * # for example, * * time to introduce a link [error] */ pub struct B; #[doc = "single line [error]"] pub struct C; #[doc = "single line with "escaping" [error]"] pub struct D; /// Item docs. #[doc="Hello there!"] /// [error] pub struct E; /// /// docs [error1] /// docs [error2] /// pub struct F; </ins>


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

| = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` <ins> warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:61:30 | LL |  * time to introduce a link [error]*/ |                              ^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:67:30 | LL |  * time to introduce a link [error] |                              ^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:71:1 | LL | #[doc = "single line [error]"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: single line [error] ^^^^^ = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:74:1 | LL | #[doc = "single line with /"escaping/" [error]"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: single line with "escaping" [error] ^^^^^ = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:77:1 | LL | / /// Item docs. LL | | #[doc="Hello there!"] LL | | /// [error] | |___________^ | = note: the link appears in this line: [error] ^^^^^ = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error1]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:83:11 | LL | /// docs [error1] |           ^^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error2]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:85:11 | LL | /// docs [error2] |           ^^^^^^ cannot be resolved, ignoring | = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` </ins> warning: `[BarA]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:24:10 |


Question:
Given the following source: The span conversion calculation in the error reporting will give the wrong offset when reporting the resolution failure, leading to a confusing report: Strangely enough, putting either the leading or the closing on its own line will cause the report to change to something that looks correct, if a little too broad: I believe the code at fault is this section here: Because it assumes that every doc comment will have a padding of 3 characters (the or ), it includes that in its calculation of each line's offset. However, for block-style comments, this assumption is false.
I'm working on this.
You can also reproduce this with unsugared docs:

= help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[BarB]` cannot be resolved, ignoring it... <del> --> $DIR/intra-links-warning.rs:28:1 </del> <ins> --> $DIR/intra-links-warning.rs:30:9 </ins> | <del> LL | / /** LL | |  * Foo LL | |  * bar [BarB] bar LL | |  * baz LL | |  */ | |___^ </del> <ins> LL |  * bar [BarB] bar |         ^^^^ cannot be resolved, ignoring </ins> | <del> = note: the link appears in this line: bar [BarB] bar ^^^^ </del> = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[BarC]` cannot be resolved, ignoring it... <del> --> $DIR/intra-links-warning.rs:35:1 </del> <ins> --> $DIR/intra-links-warning.rs:37:6 </ins> | <del> LL | / /** Foo LL | | LL | | bar [BarC] bar LL | | baz ...  | LL | | LL | | */ | |__^ </del> <ins> LL | bar [BarC] bar |      ^^^^ cannot be resolved, ignoring </ins> | <del> = note: the link appears in this line: bar [BarC] bar ^^^^ </del> = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[BarD]` cannot be resolved, ignoring it...


Question:
<details </summary<p</p is empty <details<summaryerror </summary<p<pre<font color="#AB4642"<b </b</font<font color="C1B9"<bice</b</font<font color="CAFC2"<bgit:(</b</font<font color="#AB4642"<bmaster</b</font<font color="CAFC2"<b) </b</font<font color="#F7CA88"<b</b</fontRUSTBACKTRACE=1 cargo +beta build <font color="#A1B56C"<bCompiling</b</fontice v0.1.0 (/home/shadlock0133/projects/rust/ice) thread 'main' panicked at 'byte index 45 is out of bounds of ', stack backtrace: 0: std::sys::unix::backtrace::tracing::imp::unwindbacktrace at 1: std::syscommon::backtrace::print at at 2: std::panicking::defaulthook::{{closure}} at 3: std::panicking::defaulthook at 4: rustc::util::common::panichook 5: std::panicking::rustpanicwithhook at 6: std::panicking::continuepanicfmt at 7: rustbeginunwind at 8: core::panicking::panicfmt at 9: core::str::sliceerrorfail at 10: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::RangeTo<usize>>::index::{{closure}} 11: rustcresolve::Resolver::reportconflict 12: rustcresolve::resolveimports::ImportResolver::resolveimports 13: rustcresolve::macros::<impl syntax::ext::base::Resolver for rustcresolve::Resolver<'a, 'crateloader>>::resolveimports 14: syntax::ext::expand::MacroExpander::expandfragment 15: syntax::ext::expand::MacroExpander::expandcrate 16: rustcdriver::driver::phase2configureandexpandinner::{{closure}} 17: rustc::util::common::time 18: rustcdriver::driver::phase2configureandexpand 19: rustcdriver::driver::compileinput 20: rustcdriver::runcompilerwithpool 21: rustcdriver::driver::spawnthreadpool 22: rustcdriver::runcompiler 23: <scopedtls::ScopedKey<T>>::set 24: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::callonce 25: rustmaybecatchpanic at 26: rustcdriver::run 27: rustcdriver::main 28: std::rt::langstart::{{closure}} 29: std::panicking::try::docall at at 30: rustmaybecatchpanic at 31: std::rt::langstartinternal at at at 32: main 33: libcstartmain 34: <unknown> query stack during panic: end of query stack error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: note: rustc 1.31.0-beta.19 ( 2018-11-26) running on x8664-unknown-linux-gnu note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib note: some of the compiler flags provided by cargo are hidden <font color="#AB4642"<berror:</b</fontCould not compile . To learn more, run the command again with --verbose. </pre</p</details
More or less same as should stop doing span arithmetics. cc
I don't see how not to do span arithmetics here ? In , the snippet is , source is and the binding is . By taking the snippet that starts at the beginning of the binding span and end at the end of source span, we have In this case, I think it would be better to remove the suggestion when the issue happens in a macro because the suggestion will be wrong anyway.
we could completely avoid span arithmetics by giving more useful spans, instead of having to come up with them on the spot. The counterarguments to that would be that it would increase memory usage in every import and that this suggestion is already useless in macro context (especially in this case).

); // See https://github.com/rust-lang/rust/issues/32354 <del> if old_binding.is_import() || new_binding.is_import() { let binding = if new_binding.is_import() && !new_binding.span.is_dummy() { new_binding </del> <ins> let directive = match (&new_binding.kind, &old_binding.kind) { (NameBindingKind::Import { directive, .. }, _) if !new_binding.span.is_dummy() => Some((directive, new_binding.span)), (_, NameBindingKind::Import { directive, .. }) if !old_binding.span.is_dummy() => Some((directive, old_binding.span)), _ => None, }; if let Some((directive, binding_span)) = directive { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { format!("Other{}", name) </ins> } else { <del> old_binding </del> <ins> format!("other_{}", name) </ins> }; <del> let cm = self.session.source_map(); let rename_msg = "you can use `as` to change the binding name of the import"; if let ( Ok(snippet), NameBindingKind::Import { directive, ..}, _dummy @ false, ) = ( cm.span_to_snippet(binding.span), binding.kind.clone(), binding.span.is_dummy(), ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { format!("Other{}", name) } else { format!("other_{}", name) }; </del> <ins> let mut suggestion = None; match directive.subclass { ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => suggestion = Some(format!("self as {}", suggested_name)), ImportDirectiveSubclass::SingleImport { source, .. } => { if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0) .map(|pos| pos as usize) { if let Ok(snippet) = self.session.source_map() .span_to_snippet(binding_span) { if pos <= snippet.len() { suggestion = Some(format!( "{} as {}{}", &snippet[..pos], suggested_name, if snippet.ends_with(";") { ";" } else { "" } )) } } } } ImportDirectiveSubclass::ExternCrate { source, target, .. } => suggestion = Some(format!( "extern crate {} as {};", source.unwrap_or(target.name), suggested_name, )), _ => unreachable!(), } let rename_msg = "you can use `as` to change the binding name of the import"; if let Some(suggestion) = suggestion { </ins> err.span_suggestion_with_applicability( <del> binding.span, &rename_msg, match directive.subclass { ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => format!("self as {}", suggested_name), ImportDirectiveSubclass::SingleImport { source, .. } => format!( "{} as {}{}", &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)], suggested_name, if snippet.ends_with(";") { ";" } else { "" } ), ImportDirectiveSubclass::ExternCrate { source, target, .. } => format!( "extern crate {} as {};", source.unwrap_or(target.name), suggested_name, ), _ => unreachable!(), }, </del> <ins> binding_span, rename_msg, suggestion, </ins> Applicability::MaybeIncorrect, ); } else { <del> err.span_label(binding.span, rename_msg); </del> <ins> err.span_label(binding_span, rename_msg); </ins> } }


Question:
<details </summary<p</p is empty <details<summaryerror </summary<p<pre<font color="#AB4642"<b </b</font<font color="C1B9"<bice</b</font<font color="CAFC2"<bgit:(</b</font<font color="#AB4642"<bmaster</b</font<font color="CAFC2"<b) </b</font<font color="#F7CA88"<b</b</fontRUSTBACKTRACE=1 cargo +beta build <font color="#A1B56C"<bCompiling</b</fontice v0.1.0 (/home/shadlock0133/projects/rust/ice) thread 'main' panicked at 'byte index 45 is out of bounds of ', stack backtrace: 0: std::sys::unix::backtrace::tracing::imp::unwindbacktrace at 1: std::syscommon::backtrace::print at at 2: std::panicking::defaulthook::{{closure}} at 3: std::panicking::defaulthook at 4: rustc::util::common::panichook 5: std::panicking::rustpanicwithhook at 6: std::panicking::continuepanicfmt at 7: rustbeginunwind at 8: core::panicking::panicfmt at 9: core::str::sliceerrorfail at 10: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::RangeTo<usize>>::index::{{closure}} 11: rustcresolve::Resolver::reportconflict 12: rustcresolve::resolveimports::ImportResolver::resolveimports 13: rustcresolve::macros::<impl syntax::ext::base::Resolver for rustcresolve::Resolver<'a, 'crateloader>>::resolveimports 14: syntax::ext::expand::MacroExpander::expandfragment 15: syntax::ext::expand::MacroExpander::expandcrate 16: rustcdriver::driver::phase2configureandexpandinner::{{closure}} 17: rustc::util::common::time 18: rustcdriver::driver::phase2configureandexpand 19: rustcdriver::driver::compileinput 20: rustcdriver::runcompilerwithpool 21: rustcdriver::driver::spawnthreadpool 22: rustcdriver::runcompiler 23: <scopedtls::ScopedKey<T>>::set 24: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::callonce 25: rustmaybecatchpanic at 26: rustcdriver::run 27: rustcdriver::main 28: std::rt::langstart::{{closure}} 29: std::panicking::try::docall at at 30: rustmaybecatchpanic at 31: std::rt::langstartinternal at at at 32: main 33: libcstartmain 34: <unknown> query stack during panic: end of query stack error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: note: rustc 1.31.0-beta.19 ( 2018-11-26) running on x8664-unknown-linux-gnu note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib note: some of the compiler flags provided by cargo are hidden <font color="#AB4642"<berror:</b</fontCould not compile . To learn more, run the command again with --verbose. </pre</p</details
More or less same as should stop doing span arithmetics. cc
I don't see how not to do span arithmetics here ? In , the snippet is , source is and the binding is . By taking the snippet that starts at the beginning of the binding span and end at the end of source span, we have In this case, I think it would be better to remove the suggestion when the issue happens in a macro because the suggestion will be wrong anyway.
we could completely avoid span arithmetics by giving more useful spans, instead of having to come up with them on the spot. The counterarguments to that would be that it would increase memory usage in every import and that this suggestion is already useless in macro context (especially in this case).

<ins> macro_rules! import { ( $($name:ident),* ) => { $( mod $name; pub use self::$name; //~^ ERROR the name `issue_56411_aux` is defined multiple times //~| ERROR `issue_56411_aux` is private, and cannot be re-exported )* } } import!(issue_56411_aux); fn main() { println!("Hello, world!"); } </ins>


Question:
<details </summary<p</p is empty <details<summaryerror </summary<p<pre<font color="#AB4642"<b </b</font<font color="C1B9"<bice</b</font<font color="CAFC2"<bgit:(</b</font<font color="#AB4642"<bmaster</b</font<font color="CAFC2"<b) </b</font<font color="#F7CA88"<b</b</fontRUSTBACKTRACE=1 cargo +beta build <font color="#A1B56C"<bCompiling</b</fontice v0.1.0 (/home/shadlock0133/projects/rust/ice) thread 'main' panicked at 'byte index 45 is out of bounds of ', stack backtrace: 0: std::sys::unix::backtrace::tracing::imp::unwindbacktrace at 1: std::syscommon::backtrace::print at at 2: std::panicking::defaulthook::{{closure}} at 3: std::panicking::defaulthook at 4: rustc::util::common::panichook 5: std::panicking::rustpanicwithhook at 6: std::panicking::continuepanicfmt at 7: rustbeginunwind at 8: core::panicking::panicfmt at 9: core::str::sliceerrorfail at 10: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::RangeTo<usize>>::index::{{closure}} 11: rustcresolve::Resolver::reportconflict 12: rustcresolve::resolveimports::ImportResolver::resolveimports 13: rustcresolve::macros::<impl syntax::ext::base::Resolver for rustcresolve::Resolver<'a, 'crateloader>>::resolveimports 14: syntax::ext::expand::MacroExpander::expandfragment 15: syntax::ext::expand::MacroExpander::expandcrate 16: rustcdriver::driver::phase2configureandexpandinner::{{closure}} 17: rustc::util::common::time 18: rustcdriver::driver::phase2configureandexpand 19: rustcdriver::driver::compileinput 20: rustcdriver::runcompilerwithpool 21: rustcdriver::driver::spawnthreadpool 22: rustcdriver::runcompiler 23: <scopedtls::ScopedKey<T>>::set 24: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::callonce 25: rustmaybecatchpanic at 26: rustcdriver::run 27: rustcdriver::main 28: std::rt::langstart::{{closure}} 29: std::panicking::try::docall at at 30: rustmaybecatchpanic at 31: std::rt::langstartinternal at at at 32: main 33: libcstartmain 34: <unknown> query stack during panic: end of query stack error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: note: rustc 1.31.0-beta.19 ( 2018-11-26) running on x8664-unknown-linux-gnu note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib note: some of the compiler flags provided by cargo are hidden <font color="#AB4642"<berror:</b</fontCould not compile . To learn more, run the command again with --verbose. </pre</p</details
More or less same as should stop doing span arithmetics. cc
I don't see how not to do span arithmetics here ? In , the snippet is , source is and the binding is . By taking the snippet that starts at the beginning of the binding span and end at the end of source span, we have In this case, I think it would be better to remove the suggestion when the issue happens in a macro because the suggestion will be wrong anyway.
we could completely avoid span arithmetics by giving more useful spans, instead of having to come up with them on the spot. The counterarguments to that would be that it would increase memory usage in every import and that this suggestion is already useless in macro context (especially in this case).

<ins> error[E0255]: the name `issue_56411_aux` is defined multiple times --> $DIR/issue-56411.rs:5:21 | LL |             mod $name; |             ---------- previous definition of the module `issue_56411_aux` here LL |             pub use self::$name; |                     ^^^^^^^^^^^ |                     | |                     `issue_56411_aux` reimported here |                     you can use `as` to change the binding name of the import ... LL | import!(issue_56411_aux); | ------------------------- in this macro invocation | = note: `issue_56411_aux` must be defined only once in the type namespace of this module error[E0365]: `issue_56411_aux` is private, and cannot be re-exported --> $DIR/issue-56411.rs:5:21 | LL |             pub use self::$name; |                     ^^^^^^^^^^^ re-export of private `issue_56411_aux` ... LL | import!(issue_56411_aux); | ------------------------- in this macro invocation | = note: consider declaring type or module `issue_56411_aux` with `pub` error: aborting due to 2 previous errors Some errors occurred: E0255, E0365. For more information about an error, try `rustc --explain E0255`. </ins>


Question:
<details </summary<p</p is empty <details<summaryerror </summary<p<pre<font color="#AB4642"<b </b</font<font color="C1B9"<bice</b</font<font color="CAFC2"<bgit:(</b</font<font color="#AB4642"<bmaster</b</font<font color="CAFC2"<b) </b</font<font color="#F7CA88"<b</b</fontRUSTBACKTRACE=1 cargo +beta build <font color="#A1B56C"<bCompiling</b</fontice v0.1.0 (/home/shadlock0133/projects/rust/ice) thread 'main' panicked at 'byte index 45 is out of bounds of ', stack backtrace: 0: std::sys::unix::backtrace::tracing::imp::unwindbacktrace at 1: std::syscommon::backtrace::print at at 2: std::panicking::defaulthook::{{closure}} at 3: std::panicking::defaulthook at 4: rustc::util::common::panichook 5: std::panicking::rustpanicwithhook at 6: std::panicking::continuepanicfmt at 7: rustbeginunwind at 8: core::panicking::panicfmt at 9: core::str::sliceerrorfail at 10: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::RangeTo<usize>>::index::{{closure}} 11: rustcresolve::Resolver::reportconflict 12: rustcresolve::resolveimports::ImportResolver::resolveimports 13: rustcresolve::macros::<impl syntax::ext::base::Resolver for rustcresolve::Resolver<'a, 'crateloader>>::resolveimports 14: syntax::ext::expand::MacroExpander::expandfragment 15: syntax::ext::expand::MacroExpander::expandcrate 16: rustcdriver::driver::phase2configureandexpandinner::{{closure}} 17: rustc::util::common::time 18: rustcdriver::driver::phase2configureandexpand 19: rustcdriver::driver::compileinput 20: rustcdriver::runcompilerwithpool 21: rustcdriver::driver::spawnthreadpool 22: rustcdriver::runcompiler 23: <scopedtls::ScopedKey<T>>::set 24: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::callonce 25: rustmaybecatchpanic at 26: rustcdriver::run 27: rustcdriver::main 28: std::rt::langstart::{{closure}} 29: std::panicking::try::docall at at 30: rustmaybecatchpanic at 31: std::rt::langstartinternal at at at 32: main 33: libcstartmain 34: <unknown> query stack during panic: end of query stack error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: note: rustc 1.31.0-beta.19 ( 2018-11-26) running on x8664-unknown-linux-gnu note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib note: some of the compiler flags provided by cargo are hidden <font color="#AB4642"<berror:</b</fontCould not compile . To learn more, run the command again with --verbose. </pre</p</details
More or less same as should stop doing span arithmetics. cc
I don't see how not to do span arithmetics here ? In , the snippet is , source is and the binding is . By taking the snippet that starts at the beginning of the binding span and end at the end of source span, we have In this case, I think it would be better to remove the suggestion when the issue happens in a macro because the suggestion will be wrong anyway.
we could completely avoid span arithmetics by giving more useful spans, instead of having to come up with them on the spot. The counterarguments to that would be that it would increase memory usage in every import and that this suggestion is already useless in macro context (especially in this case).

<ins> // compile-pass struct T {} fn main() {} </ins>


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

#![feature(cfg_target_vendor)] #![feature(char_error_internals)] #![feature(compiler_builtins_lib)] <ins> #![feature(concat_idents)] </ins> #![feature(const_int_ops)] #![feature(const_ip)] #![feature(const_raw_ptr_deref)]


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

// Linux. This was added in 2.6.28, however, and because we support // 2.6.18 we must detect this support dynamically. if cfg!(target_os = "linux") { <del> weak! { fn accept4(c_int, *mut sockaddr, *mut socklen_t, c_int) -> c_int </del> <ins> syscall! { fn accept4( fd: c_int, addr: *mut sockaddr, addr_len: *mut socklen_t, flags: c_int ) -> c_int </ins> } <del> if let Some(accept) = accept4.get() { let res = cvt_r(|| unsafe { accept(self.0.raw(), storage, len, SOCK_CLOEXEC) }); match res { Ok(fd) => return Ok(Socket(FileDesc::new(fd))), Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} Err(e) => return Err(e), } </del> <ins> let res = cvt_r(|| unsafe { accept4(self.0.raw(), storage, len, SOCK_CLOEXEC) }); match res { Ok(fd) => return Ok(Socket(FileDesc::new(fd))), Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} Err(e) => return Err(e), </ins> } }


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

} /// Sets the platform-specific value of errno <del> #[cfg(any(target_os = "solaris", target_os = "fuchsia"))] // only needed for readdir so far </del> <ins> #[cfg(all(not(target_os = "linux"), not(target_os = "dragonfly")))] // needed for readdir and syscall! </ins> pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

unsafe { errno as i32 } } <ins> #[cfg(target_os = "dragonfly")] pub fn set_errno(e: i32) { extern { #[thread_local] static mut errno: c_int; } unsafe { errno = e; } } </ins> /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { extern {


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { <del> weak! { fn pipe2(*mut c_int, c_int) -> c_int } </del> <ins> syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int } </ins> static INVALID: AtomicBool = ATOMIC_BOOL_INIT; let mut fds = [0; 2];


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

!INVALID.load(Ordering::SeqCst) { <del> if let Some(pipe) = pipe2.get() { // Note that despite calling a glibc function here we may still // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to // emulate on older kernels, so if you happen to be running on // an older kernel you may see `pipe2` as a symbol but still not // see the syscall. match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { Ok(_) => { return Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))); } Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { INVALID.store(true, Ordering::SeqCst); } Err(e) => return Err(e), </del> <ins> // Note that despite calling a glibc function here we may still // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to // emulate on older kernels, so if you happen to be running on // an older kernel you may see `pipe2` as a symbol but still not // see the syscall. match cvt(unsafe { pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { Ok(_) => { return Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))); } Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { INVALID.store(true, Ordering::SeqCst); </ins> } <ins> Err(e) => return Err(e), </ins> } } cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;


Question:
Sorry for the cryptic title, didn't knew exactly what to put there. On musl targets (well and (hf)) for some reason pipe2 is not used (even on kernels that support it). Pipe2 is important to protect against race condition when multiple threads run external commands. The following is an example that due to this bug will deadlock on the musl targets listed above (and probably all linux musl ones). Running with strace proves that pipe2 is not used, and that instead the fallback is: vs the target: Versions affected: 1.30.1 1.31.0 - Current stable rustc 1.32.0-nightly ( 2018-12-07) Later Edit: Just to be clear, if I compile a C file with the same musl toolchain that rust uses pipe2 works, so it's not a bug in Musl (or doesn't look like one to me).
cc
Did some investigation regarding this bug: The culprit seems to be: More specifically the following comment: “It assumes that //! we've been dynamically linked to the library the symbol comes from, but that //! is currently always the case for things like libpthread/libc.” Well this is not the case for musl target binaries. pipe2 is one of the symbols rust uses this mechanism to check for existence.(for fair reasons, the symbol is not there on old kernels). But on any musl target this symbol does exist because musl is emulating it in it’s standard library in case the systemcall is missing. A solution would thus be to assume this symbol always exists on musl targets (and it’s probably the same for the other ones) and make the weak! macro return the symbol directly for such targets. I could do it myself if this sounds resonable.
Thanks for the report Your investigation sounds right to me and I agree that we can probably just assume these symbols always exist on the musl target (as we're mostly pulling in the libc anyway). Should be fine to update the standard library to assume so!
Is this kind of what you had in mind? I wanna know if I should go like this, or I understood you wrong.

}; libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize } <ins> #[cfg(not(target_os = "linux"))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name: $t),*) -> $ret { use libc; use super::os; weak! { fn $name($($t),*) -> $ret } if let Some(fun) = $name.get() { fun($($arg_name),*) } else { os::set_errno(libc::ENOSYS); -1 } } ) } #[cfg(target_os = "linux")] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { // This looks like a hack, but concat_idents only accepts idents // (not paths). use libc::*; syscall( concat_idents!(SYS_, $name), $($arg_name as c_long),* ) as $ret } ) } </ins>


Question:
https://crater-
cc Repro I'm going to fix the regression, but I just want to note that is very dangerous to use. This looks like another argument for
FWIW the code in question is some mechanically translated C with the translation performed by . I have pretty much abandoned that project.
triage: P-high.

// Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { <del> if context.is_mutating_use() { </del> <ins> if self.mode == Mode::Static && context.is_mutating_use() { </ins> // this is not strictly necessary as miri will also bail out // For interior mutability we can't really catch this statically as that // goes through raw pointers and intermediate temporaries, so miri has


Question:
https://crater-
cc Repro I'm going to fix the regression, but I just want to note that is very dangerous to use. This looks like another argument for
FWIW the code in question is some mechanically translated C with the translation performed by . I have pretty much abandoned that project.
triage: P-high.

<ins> // compile-pass static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE }; fn main() {} </ins>