Question:
If I return a direct type that is , I get a helpful compiler warning: The equivalent (and I believe preferred) code using gives no such useful feedback: Amusingly, this isn't a new problem, as returning a boxed trait object also has the same problem. It's arguably worse there because you've performed an allocation for no good reason, but it's also less likely because people are more reluctant to introduce unneeded allocations.
Since Rust 1.27 stabilizes (on functions), one possible solution would be a lint that checks the compiler-known type underneath the and the function returning it. If the type has the annotation but the function does not, it could suggest adding the attribute to the function.
I think it would make sense for to quickly review and agree on how we should handle this. A lint seems plausible. Inside the same module, where we know the concrete underlying type, it would definitely make sense to pass through the . I'd love to know if it makes sense to automatically pass through the on the concrete type when used from outside the module, so that this can work automatically without needing a lint and a manual additional on the function.
Why is the not on, say, ?
I agree with that traits seem like the better solution here than trying to "leak" must-used-ness.
In that case, is it fine that returning an of real type will drop the must-used-ness? Maybe we should suggest to the author of the function to add the attribute to the function if the real type is
Right, there's nothing meaningfully tying such a function to , if is hidden.
The new thing being stabilized in 1.27 is specifically on functions and methods (). on types, including the iterator-adapter structs like , are .
We may need to add an arm for in this match?
So, I'd absolutely support adding for traits, which would have the same effect on a function returning as on a type T would have for a function returning . However, I also think we ought to handle this case somehow, preferably in a way that doesn't require the user to manually propagate outward on every function that returns a type.
I don't think we should. The type, including its must-use'dness, is not a part of the public API in that context. If you want the function return to be treated as must-use, the solution in that case is to tag the function as must-use.
Then in that case, would it make sense to have a lint suggesting propagation of from the type to the function that returns that concrete type?
I don't think so. The point of returning impl Trait is to hide the return type and the facts of its API, the fact that the type is must-use seems no different from other facts about the return type.
As alluded to above, I argue that this is a bug in the must-use lint due to its antedating impl-Trait; I don't see sufficient cause here to complicate the language with another lint or feature. A pull request is forthcoming.
Hm, perhaps this was too confidently worded: see description of the new pull request .
So let me summarize to see if I understand correctly what you're planning for must_use for traits:
I think expanding the applicability of mustuse should probably be introduced using an RFC. It seems to me that there are two different approaches proposed and an RFC could clarify why we chose a certain approach: proposes to evaluate the lint using the concrete type and provided a PR to this effect. This is incompatible with statement with which I agree with: "The type, including its must-use'dness, is not a part of the public API in that context [i.e. return impl Trait]". I also agree with that mustuse for traits is something we should investigate and pursue. This would be extremely helpful for futures because forgetting to poll needs to be obvious.
Can you provide an example of a case where it is the correct thing to return a concrete type that is tagged as through and not use the result of the function? My original premise is that this is an unintentional mistake in 95-99% of the cases, which feels like the ideal case for a lint. In the (rare) case where the author of the -returning function deliberately wants to allow forgetting to use the return value, they can allow the lint. I don't know exactly which "other facts" you mean, but I can think of two primary things: "sub" traits, which are not automagically propagated: traits, which are automagically propagated: I think that the case is different from the "sub trait" case because you will rather quickly run into "well, my code doesn't compile" errors when you forget to return the "sub trait". You then have to decide if you meant to expose that interface. I know the auto trait aspect was much discussed, so I don't wish to re-litigate it. My point here is that we : I think there's a case to be made that is already an ergonomics-based feature as it helps prevent the user from writing code they didn't mean to.
As a concrete side note, I opened this because I did it myself: I wrote some code that returned and was confused for a minute because the compiler didn't have any warnings. I'm used to those warnings and they are part of my development flow. Having them "suddenly go missing" just because I wanted to use felt like trying to step on the last stair that isn't there. For me, it's right up there with in that my "normal" flow of programming that I've established since ~Rust 0.12 doesn't quite work the same with .
IMO the more conservative approach would be to not leak mustuse on the concrete type. If that turns out to be the wrong call, it can always be later. I think defining mustuse on traits (e.g. on and ) will already be enough to catch all the bugs we're trying to prevent. The big advantage of defining mustuse on the trait is that this system can also work for unnameable types like the return type of an async function. Additionally it also avoids all the boilerplate code that defines each concrete iterator or future type as muchuse.
I think the current approach of "stick on the dozens of types implementing and " just doesn't scale and this is an example where it goes wrong. Also consider type parameters or associated types that are known implement those traits. IMO they should get the same treatment by , without knowing the concrete type.
To be clear, I'm totally happy with implementing for traits, but that particular option has been available "forever" but doesn't seem to be implemented for whichever reason. On the flip side, fairly quickly. I really just don't want to see this particular feature held up by a months (years?) long discussion of the ideal Platonic implementation of for traits. Isn't that what the current implementation does? Am I missing something? I believe that's what I'm proposing... Yes, I believe that that's a better option, and I'll add one more: presumably it will also work for trait objects. I just don't want to lose what existing ergonomics we have until someone implements for traits. These don't even have to be mutually exclusive options! The lint can catch cases that a trait wouldn't — such as when a given instance of a trait should be must use but not the trait itself. The lint could even be removed once the better solution is created, if we felt it didn't carry its weight anymore.
I also want to suggest a more aggressive approach: existential is always no matter of its underlying type. If a function is returning an thing, you were probably meant to use it in some way.
I wonder how hard it would be to turn such a thing on to see the impact.
Thanks for the compelling argument! I agree with what I think is the implication of your post: this question boils down to "Is more like an auto trait, or a regular API fact?" I'm not sure of the answer. What is the distinction with vs any other return type? Isn't it plausible that something that returns also has a useful side effect, and the return is not relevant all the time?

}; if let Some(def) = maybe_def { let def_id = def.def_id(); <del> fn_warned = check_must_use(cx, def_id, s.span, "return value of "); } else if type_permits_no_use { </del> <ins> fn_warned = check_must_use(cx, def_id, s.span, "return value of ", ""); } else if type_permits_lack_of_use { </ins> // We don't warn about unused unit or uninhabited types. // (See https://github.com/rust-lang/rust/issues/43806 for details.) return;


Question:
If I return a direct type that is , I get a helpful compiler warning: The equivalent (and I believe preferred) code using gives no such useful feedback: Amusingly, this isn't a new problem, as returning a boxed trait object also has the same problem. It's arguably worse there because you've performed an allocation for no good reason, but it's also less likely because people are more reluctant to introduce unneeded allocations.
Since Rust 1.27 stabilizes (on functions), one possible solution would be a lint that checks the compiler-known type underneath the and the function returning it. If the type has the annotation but the function does not, it could suggest adding the attribute to the function.
I think it would make sense for to quickly review and agree on how we should handle this. A lint seems plausible. Inside the same module, where we know the concrete underlying type, it would definitely make sense to pass through the . I'd love to know if it makes sense to automatically pass through the on the concrete type when used from outside the module, so that this can work automatically without needing a lint and a manual additional on the function.
Why is the not on, say, ?
I agree with that traits seem like the better solution here than trying to "leak" must-used-ness.
In that case, is it fine that returning an of real type will drop the must-used-ness? Maybe we should suggest to the author of the function to add the attribute to the function if the real type is
Right, there's nothing meaningfully tying such a function to , if is hidden.
The new thing being stabilized in 1.27 is specifically on functions and methods (). on types, including the iterator-adapter structs like , are .
We may need to add an arm for in this match?
So, I'd absolutely support adding for traits, which would have the same effect on a function returning as on a type T would have for a function returning . However, I also think we ought to handle this case somehow, preferably in a way that doesn't require the user to manually propagate outward on every function that returns a type.
I don't think we should. The type, including its must-use'dness, is not a part of the public API in that context. If you want the function return to be treated as must-use, the solution in that case is to tag the function as must-use.
Then in that case, would it make sense to have a lint suggesting propagation of from the type to the function that returns that concrete type?
I don't think so. The point of returning impl Trait is to hide the return type and the facts of its API, the fact that the type is must-use seems no different from other facts about the return type.
As alluded to above, I argue that this is a bug in the must-use lint due to its antedating impl-Trait; I don't see sufficient cause here to complicate the language with another lint or feature. A pull request is forthcoming.
Hm, perhaps this was too confidently worded: see description of the new pull request .
So let me summarize to see if I understand correctly what you're planning for must_use for traits:
I think expanding the applicability of mustuse should probably be introduced using an RFC. It seems to me that there are two different approaches proposed and an RFC could clarify why we chose a certain approach: proposes to evaluate the lint using the concrete type and provided a PR to this effect. This is incompatible with statement with which I agree with: "The type, including its must-use'dness, is not a part of the public API in that context [i.e. return impl Trait]". I also agree with that mustuse for traits is something we should investigate and pursue. This would be extremely helpful for futures because forgetting to poll needs to be obvious.
Can you provide an example of a case where it is the correct thing to return a concrete type that is tagged as through and not use the result of the function? My original premise is that this is an unintentional mistake in 95-99% of the cases, which feels like the ideal case for a lint. In the (rare) case where the author of the -returning function deliberately wants to allow forgetting to use the return value, they can allow the lint. I don't know exactly which "other facts" you mean, but I can think of two primary things: "sub" traits, which are not automagically propagated: traits, which are automagically propagated: I think that the case is different from the "sub trait" case because you will rather quickly run into "well, my code doesn't compile" errors when you forget to return the "sub trait". You then have to decide if you meant to expose that interface. I know the auto trait aspect was much discussed, so I don't wish to re-litigate it. My point here is that we : I think there's a case to be made that is already an ergonomics-based feature as it helps prevent the user from writing code they didn't mean to.
As a concrete side note, I opened this because I did it myself: I wrote some code that returned and was confused for a minute because the compiler didn't have any warnings. I'm used to those warnings and they are part of my development flow. Having them "suddenly go missing" just because I wanted to use felt like trying to step on the last stair that isn't there. For me, it's right up there with in that my "normal" flow of programming that I've established since ~Rust 0.12 doesn't quite work the same with .
IMO the more conservative approach would be to not leak mustuse on the concrete type. If that turns out to be the wrong call, it can always be later. I think defining mustuse on traits (e.g. on and ) will already be enough to catch all the bugs we're trying to prevent. The big advantage of defining mustuse on the trait is that this system can also work for unnameable types like the return type of an async function. Additionally it also avoids all the boilerplate code that defines each concrete iterator or future type as muchuse.
I think the current approach of "stick on the dozens of types implementing and " just doesn't scale and this is an example where it goes wrong. Also consider type parameters or associated types that are known implement those traits. IMO they should get the same treatment by , without knowing the concrete type.
To be clear, I'm totally happy with implementing for traits, but that particular option has been available "forever" but doesn't seem to be implemented for whichever reason. On the flip side, fairly quickly. I really just don't want to see this particular feature held up by a months (years?) long discussion of the ideal Platonic implementation of for traits. Isn't that what the current implementation does? Am I missing something? I believe that's what I'm proposing... Yes, I believe that that's a better option, and I'll add one more: presumably it will also work for trait objects. I just don't want to lose what existing ergonomics we have until someone implements for traits. These don't even have to be mutually exclusive options! The lint can catch cases that a trait wouldn't — such as when a given instance of a trait should be must use but not the trait itself. The lint could even be removed once the better solution is created, if we felt it didn't carry its weight anymore.
I also want to suggest a more aggressive approach: existential is always no matter of its underlying type. If a function is returning an thing, you were probably meant to use it in some way.
I wonder how hard it would be to turn such a thing on to see the impact.
Thanks for the compelling argument! I agree with what I think is the implication of your post: this question boils down to "Is more like an auto trait, or a regular API fact?" I'm not sure of the answer. What is the distinction with vs any other return type? Isn't it plausible that something that returns also has a useful side effect, and the return is not relevant all the time?

op_warned = true; } <del> if !(type_permits_no_use || fn_warned || op_warned) { </del> <ins> if !(type_permits_lack_of_use || fn_warned || op_warned) { </ins> cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } <del> fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span, describe_path: &str) -> bool { </del> <ins> fn check_must_use( cx: &LateContext, def_id: DefId, sp: Span, descr_pre_path: &str, descr_post_path: &str, ) -> bool { </ins> for attr in cx.tcx.get_attrs(def_id).iter() { if attr.check_name("must_use") { <del> let msg = format!("unused {}`{}` that must be used", describe_path, cx.tcx.item_path_str(def_id)); </del> <ins> let msg = format!("unused {}`{}`{} that must be used", descr_pre_path, cx.tcx.item_path_str(def_id), descr_post_path); </ins> let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg); // check for #[must_use = "..."] if let Some(note) = attr.value_str() {


Question:
If I return a direct type that is , I get a helpful compiler warning: The equivalent (and I believe preferred) code using gives no such useful feedback: Amusingly, this isn't a new problem, as returning a boxed trait object also has the same problem. It's arguably worse there because you've performed an allocation for no good reason, but it's also less likely because people are more reluctant to introduce unneeded allocations.
Since Rust 1.27 stabilizes (on functions), one possible solution would be a lint that checks the compiler-known type underneath the and the function returning it. If the type has the annotation but the function does not, it could suggest adding the attribute to the function.
I think it would make sense for to quickly review and agree on how we should handle this. A lint seems plausible. Inside the same module, where we know the concrete underlying type, it would definitely make sense to pass through the . I'd love to know if it makes sense to automatically pass through the on the concrete type when used from outside the module, so that this can work automatically without needing a lint and a manual additional on the function.
Why is the not on, say, ?
I agree with that traits seem like the better solution here than trying to "leak" must-used-ness.
In that case, is it fine that returning an of real type will drop the must-used-ness? Maybe we should suggest to the author of the function to add the attribute to the function if the real type is
Right, there's nothing meaningfully tying such a function to , if is hidden.
The new thing being stabilized in 1.27 is specifically on functions and methods (). on types, including the iterator-adapter structs like , are .
We may need to add an arm for in this match?
So, I'd absolutely support adding for traits, which would have the same effect on a function returning as on a type T would have for a function returning . However, I also think we ought to handle this case somehow, preferably in a way that doesn't require the user to manually propagate outward on every function that returns a type.
I don't think we should. The type, including its must-use'dness, is not a part of the public API in that context. If you want the function return to be treated as must-use, the solution in that case is to tag the function as must-use.
Then in that case, would it make sense to have a lint suggesting propagation of from the type to the function that returns that concrete type?
I don't think so. The point of returning impl Trait is to hide the return type and the facts of its API, the fact that the type is must-use seems no different from other facts about the return type.
As alluded to above, I argue that this is a bug in the must-use lint due to its antedating impl-Trait; I don't see sufficient cause here to complicate the language with another lint or feature. A pull request is forthcoming.
Hm, perhaps this was too confidently worded: see description of the new pull request .
So let me summarize to see if I understand correctly what you're planning for must_use for traits:
I think expanding the applicability of mustuse should probably be introduced using an RFC. It seems to me that there are two different approaches proposed and an RFC could clarify why we chose a certain approach: proposes to evaluate the lint using the concrete type and provided a PR to this effect. This is incompatible with statement with which I agree with: "The type, including its must-use'dness, is not a part of the public API in that context [i.e. return impl Trait]". I also agree with that mustuse for traits is something we should investigate and pursue. This would be extremely helpful for futures because forgetting to poll needs to be obvious.
Can you provide an example of a case where it is the correct thing to return a concrete type that is tagged as through and not use the result of the function? My original premise is that this is an unintentional mistake in 95-99% of the cases, which feels like the ideal case for a lint. In the (rare) case where the author of the -returning function deliberately wants to allow forgetting to use the return value, they can allow the lint. I don't know exactly which "other facts" you mean, but I can think of two primary things: "sub" traits, which are not automagically propagated: traits, which are automagically propagated: I think that the case is different from the "sub trait" case because you will rather quickly run into "well, my code doesn't compile" errors when you forget to return the "sub trait". You then have to decide if you meant to expose that interface. I know the auto trait aspect was much discussed, so I don't wish to re-litigate it. My point here is that we : I think there's a case to be made that is already an ergonomics-based feature as it helps prevent the user from writing code they didn't mean to.
As a concrete side note, I opened this because I did it myself: I wrote some code that returned and was confused for a minute because the compiler didn't have any warnings. I'm used to those warnings and they are part of my development flow. Having them "suddenly go missing" just because I wanted to use felt like trying to step on the last stair that isn't there. For me, it's right up there with in that my "normal" flow of programming that I've established since ~Rust 0.12 doesn't quite work the same with .
IMO the more conservative approach would be to not leak mustuse on the concrete type. If that turns out to be the wrong call, it can always be later. I think defining mustuse on traits (e.g. on and ) will already be enough to catch all the bugs we're trying to prevent. The big advantage of defining mustuse on the trait is that this system can also work for unnameable types like the return type of an async function. Additionally it also avoids all the boilerplate code that defines each concrete iterator or future type as muchuse.
I think the current approach of "stick on the dozens of types implementing and " just doesn't scale and this is an example where it goes wrong. Also consider type parameters or associated types that are known implement those traits. IMO they should get the same treatment by , without knowing the concrete type.
To be clear, I'm totally happy with implementing for traits, but that particular option has been available "forever" but doesn't seem to be implemented for whichever reason. On the flip side, fairly quickly. I really just don't want to see this particular feature held up by a months (years?) long discussion of the ideal Platonic implementation of for traits. Isn't that what the current implementation does? Am I missing something? I believe that's what I'm proposing... Yes, I believe that that's a better option, and I'll add one more: presumably it will also work for trait objects. I just don't want to lose what existing ergonomics we have until someone implements for traits. These don't even have to be mutually exclusive options! The lint can catch cases that a trait wouldn't — such as when a given instance of a trait should be must use but not the trait itself. The lint could even be removed once the better solution is created, if we felt it didn't carry its weight anymore.
I also want to suggest a more aggressive approach: existential is always no matter of its underlying type. If a function is returning an thing, you were probably meant to use it in some way.
I wonder how hard it would be to turn such a thing on to see the impact.
Thanks for the compelling argument! I agree with what I think is the implication of your post: this question boils down to "Is more like an auto trait, or a regular API fact?" I'm not sure of the answer. What is the distinction with vs any other return type? Isn't it plausible that something that returns also has a useful side effect, and the return is not relevant all the time?

<ins> #![deny(unused_must_use)] #[must_use] trait Critical {} trait NotSoCritical {} trait DecidedlyUnimportant {} struct Anon; impl Critical for Anon {} impl NotSoCritical for Anon {} impl DecidedlyUnimportant for Anon {} fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant { Anon {} } fn main() { get_critical(); //~ ERROR unused implementer of `Critical` that must be used } </ins>


Question:
If I return a direct type that is , I get a helpful compiler warning: The equivalent (and I believe preferred) code using gives no such useful feedback: Amusingly, this isn't a new problem, as returning a boxed trait object also has the same problem. It's arguably worse there because you've performed an allocation for no good reason, but it's also less likely because people are more reluctant to introduce unneeded allocations.
Since Rust 1.27 stabilizes (on functions), one possible solution would be a lint that checks the compiler-known type underneath the and the function returning it. If the type has the annotation but the function does not, it could suggest adding the attribute to the function.
I think it would make sense for to quickly review and agree on how we should handle this. A lint seems plausible. Inside the same module, where we know the concrete underlying type, it would definitely make sense to pass through the . I'd love to know if it makes sense to automatically pass through the on the concrete type when used from outside the module, so that this can work automatically without needing a lint and a manual additional on the function.
Why is the not on, say, ?
I agree with that traits seem like the better solution here than trying to "leak" must-used-ness.
In that case, is it fine that returning an of real type will drop the must-used-ness? Maybe we should suggest to the author of the function to add the attribute to the function if the real type is
Right, there's nothing meaningfully tying such a function to , if is hidden.
The new thing being stabilized in 1.27 is specifically on functions and methods (). on types, including the iterator-adapter structs like , are .
We may need to add an arm for in this match?
So, I'd absolutely support adding for traits, which would have the same effect on a function returning as on a type T would have for a function returning . However, I also think we ought to handle this case somehow, preferably in a way that doesn't require the user to manually propagate outward on every function that returns a type.
I don't think we should. The type, including its must-use'dness, is not a part of the public API in that context. If you want the function return to be treated as must-use, the solution in that case is to tag the function as must-use.
Then in that case, would it make sense to have a lint suggesting propagation of from the type to the function that returns that concrete type?
I don't think so. The point of returning impl Trait is to hide the return type and the facts of its API, the fact that the type is must-use seems no different from other facts about the return type.
As alluded to above, I argue that this is a bug in the must-use lint due to its antedating impl-Trait; I don't see sufficient cause here to complicate the language with another lint or feature. A pull request is forthcoming.
Hm, perhaps this was too confidently worded: see description of the new pull request .
So let me summarize to see if I understand correctly what you're planning for must_use for traits:
I think expanding the applicability of mustuse should probably be introduced using an RFC. It seems to me that there are two different approaches proposed and an RFC could clarify why we chose a certain approach: proposes to evaluate the lint using the concrete type and provided a PR to this effect. This is incompatible with statement with which I agree with: "The type, including its must-use'dness, is not a part of the public API in that context [i.e. return impl Trait]". I also agree with that mustuse for traits is something we should investigate and pursue. This would be extremely helpful for futures because forgetting to poll needs to be obvious.
Can you provide an example of a case where it is the correct thing to return a concrete type that is tagged as through and not use the result of the function? My original premise is that this is an unintentional mistake in 95-99% of the cases, which feels like the ideal case for a lint. In the (rare) case where the author of the -returning function deliberately wants to allow forgetting to use the return value, they can allow the lint. I don't know exactly which "other facts" you mean, but I can think of two primary things: "sub" traits, which are not automagically propagated: traits, which are automagically propagated: I think that the case is different from the "sub trait" case because you will rather quickly run into "well, my code doesn't compile" errors when you forget to return the "sub trait". You then have to decide if you meant to expose that interface. I know the auto trait aspect was much discussed, so I don't wish to re-litigate it. My point here is that we : I think there's a case to be made that is already an ergonomics-based feature as it helps prevent the user from writing code they didn't mean to.
As a concrete side note, I opened this because I did it myself: I wrote some code that returned and was confused for a minute because the compiler didn't have any warnings. I'm used to those warnings and they are part of my development flow. Having them "suddenly go missing" just because I wanted to use felt like trying to step on the last stair that isn't there. For me, it's right up there with in that my "normal" flow of programming that I've established since ~Rust 0.12 doesn't quite work the same with .
IMO the more conservative approach would be to not leak mustuse on the concrete type. If that turns out to be the wrong call, it can always be later. I think defining mustuse on traits (e.g. on and ) will already be enough to catch all the bugs we're trying to prevent. The big advantage of defining mustuse on the trait is that this system can also work for unnameable types like the return type of an async function. Additionally it also avoids all the boilerplate code that defines each concrete iterator or future type as muchuse.
I think the current approach of "stick on the dozens of types implementing and " just doesn't scale and this is an example where it goes wrong. Also consider type parameters or associated types that are known implement those traits. IMO they should get the same treatment by , without knowing the concrete type.
To be clear, I'm totally happy with implementing for traits, but that particular option has been available "forever" but doesn't seem to be implemented for whichever reason. On the flip side, fairly quickly. I really just don't want to see this particular feature held up by a months (years?) long discussion of the ideal Platonic implementation of for traits. Isn't that what the current implementation does? Am I missing something? I believe that's what I'm proposing... Yes, I believe that that's a better option, and I'll add one more: presumably it will also work for trait objects. I just don't want to lose what existing ergonomics we have until someone implements for traits. These don't even have to be mutually exclusive options! The lint can catch cases that a trait wouldn't — such as when a given instance of a trait should be must use but not the trait itself. The lint could even be removed once the better solution is created, if we felt it didn't carry its weight anymore.
I also want to suggest a more aggressive approach: existential is always no matter of its underlying type. If a function is returning an thing, you were probably meant to use it in some way.
I wonder how hard it would be to turn such a thing on to see the impact.
Thanks for the compelling argument! I agree with what I think is the implication of your post: this question boils down to "Is more like an auto trait, or a regular API fact?" I'm not sure of the answer. What is the distinction with vs any other return type? Isn't it plausible that something that returns also has a useful side effect, and the return is not relevant all the time?

<ins> error: unused implementer of `Critical` that must be used --> $DIR/must_use-trait.rs:21:5 | LL |     get_critical(); //~ ERROR unused implementer of `Critical` that must be used |     ^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/must_use-trait.rs:1:9 | LL | #![deny(unused_must_use)] |         ^^^^^^^^^^^^^^^ error: aborting due to previous error </ins>


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

let crate_types = if options.proc_macro_crate { vec![config::CrateType::ProcMacro] } else { <del> vec![config::CrateType::Dylib] </del> <ins> vec![config::CrateType::Rlib] </ins> }; let sessopts = config::Options {


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

intravisit::walk_crate(this, krate); }); }); <ins> compiler.session().abort_if_errors(); </ins> let ret: Result<_, ErrorReported> = Ok(collector.tests); ret }) <del> }) .expect("compiler aborted in rustdoc!"); </del> <ins> }); let tests = match tests { Ok(tests) => tests, Err(ErrorReported) => return 1, }; </ins> test_args.insert(0, "rustdoctest".to_string());


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

<ins> // compile-flags:--test /// ``` /// assert!(true) /// ``` pub fn f() {} pub fn f() {} </ins>


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

<ins> error[E0428]: the name `f` is defined multiple times --> $DIR/test-compile-fail1.rs:8:1 | 6 | pub fn f() {} | ---------- previous definition of the value `f` here 7 | 8 | pub fn f() {} | ^^^^^^^^^^ `f` redefined here | = note: `f` must be defined only once in the value namespace of this module error: aborting due to previous error For more information about this error, try `rustc --explain E0428`. </ins>


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

<ins> error: expected one of `!` or `::`, found `<eof>` --> $DIR/test-compile-fail2.rs:3:1 | 3 | fail | ^^^^ expected one of `!` or `::` error: aborting due to previous error </ins>


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

<ins> error: unterminated double quote string --> $DIR/test-compile-fail3.rs:3:1 | 3 | "fail | ^^^^^^ error: aborting due to previous error </ins>


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

<ins> // compile-flags:--test // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" // build-pass #![no_std] extern crate alloc; /// ``` /// assert!(true) /// ``` pub fn f() {} </ins>


Question:
I noticed this in the output running locally: and that didn't make tests fail. Cc:
Same with panic_unwind:
This error message is printed when running , but before running any test. The code printing it is in . It looks like rustdoc is using that code in order to load the crate and find doctests in it. But since it’s not actually compiling this crate, not having an allocator is not a problem. So I think there are two issues: rustdoc keeps doing its thing even though there are errors. It probably should call something like on its instance at some point. This error should not occur in the first place. One way to inhibit it would be to tell that we’re "compiling" an rlib () rather than some other crate type. rlibs do not need (yet) to have an allocator defined. This is possibly this line: The first issue could in some other situation hide a real problem, but in this case it makes the second one mostly harmless. The only bad consequence is some noise in the output of a test run.
Related:
modify labels: +T-rustdoc
Error: Parsing label command in failed: labels +T-rustdo... Please let know if you're having trouble with this bot.

<ins> running 1 test test $DIR/test-no_std.rs - f (line 9) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out </ins>


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); <del> // command specific path, we call clear_if_dirty with this let mut my_out = match cmd { "build" => self.cargo_out(compiler, mode, target), // This is the intended out directory for crate documentation. "doc" | "rustdoc" =>  self.crate_doc_out(target), _ => self.stage_out(compiler, mode), }; // This is for the original compiler, but if we're forced to use stage 1, then // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since // we copy the libs forward. let cmp = self.compiler_for(compiler.stage, compiler.host, target); let libstd_stamp = match cmd { "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target), _ => compile::libstd_stamp(self, cmp, target), }; let libtest_stamp = match cmd { "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target), _ => compile::libtest_stamp(self, cmp, target), }; let librustc_stamp = match cmd { "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target), _ => compile::librustc_stamp(self, cmp, target), }; </del> <ins> // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, // so we need to explicitly clear out if they've been updated. for backend in self.codegen_backends(compiler) { self.clear_if_dirty(&out_dir, &backend); } </ins> if cmd == "doc" || cmd == "rustdoc" { <del> if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { </del> <ins> let my_out = match mode { </ins> // This is the intended out directory for compiler documentation. <del> my_out = self.compiler_doc_out(target); } </del> <ins> Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target), _ => self.crate_doc_out(target), }; </ins> let rustdoc = self.rustdoc(compiler); self.clear_if_dirty(&my_out, &rustdoc); <del> } else if cmd != "test" { match mode { Mode::Std => { self.clear_if_dirty(&my_out, &self.rustc(compiler)); for backend in self.codegen_backends(compiler) { self.clear_if_dirty(&my_out, &backend); } }, Mode::Test => { self.clear_if_dirty(&my_out, &libstd_stamp); }, Mode::Rustc => { self.clear_if_dirty(&my_out, &self.rustc(compiler)); self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); }, Mode::Codegen => { self.clear_if_dirty(&my_out, &librustc_stamp); }, Mode::ToolBootstrap => { }, Mode::ToolStd => { self.clear_if_dirty(&my_out, &libstd_stamp); }, Mode::ToolTest => { self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); }, Mode::ToolRustc => { self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); self.clear_if_dirty(&my_out, &librustc_stamp); }, } </del> } cargo


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

}, } <ins> // This tells Cargo (and in turn, rustc) to output more complete // dependency information.  Most importantly for rustbuild, this // includes sysroot artifacts, like libstd, which means that we don't // need to track those in rustbuild (an error prone process!). This // feature is currently unstable as there may be some bugs and such, but // it represents a big improvement in rustbuild's reliability on // rebuilds, so we're using it here. // // For some additional context, see #63470 (the PR originally adding // this), as well as #63012 which is the tracking issue for this // feature on the rustc side. cargo.arg("-Zbinary-dep-depinfo"); </ins> cargo.arg("-j").arg(self.jobs().to_string()); // Remove make-related flags to ensure Cargo can correctly set things up cargo.env_remove("MAKEFLAGS");


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target)); <del> builder.cargo(compiler, Mode::ToolRustc, target, "clean"); </del> } }


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

use std::process::{Command, Stdio, exit}; use std::str; <del> use build_helper::{output, mtime, t, up_to_date}; </del> <ins> use build_helper::{output, t, up_to_date}; </ins> use filetime::FileTime; use serde::Deserialize; use serde_json;


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

// for reason why the sanitizers are not built in stage0. copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } <del> builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); </del> } }


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

&builder.sysroot_libdir(target_compiler, compiler.host), &libtest_stamp(builder, compiler, target) ); <del> builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); </del> } }


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

&builder.sysroot_libdir(target_compiler, compiler.host), &librustc_stamp(builder, compiler, target) ); <del> builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); </del> } }


Question: I was in the middle of bisecting on system llvm and running when I noticed that, in fact, while each step was rebuilding the compiler with the changed llvm correctly, the test that was being run was never recompiled, such that the same one was always running, and my bisect was guided by wrong results. STR: Run once Touch anything that is part of e.g. , e.g. Run again Expected result: Both and the test are rebuilt, and the rebuilt test executed. Actual result: is rebuilt, the test is not, and the test built before the codegen changes is executed.

deps.push((path_to_add.into(), false)); } <del> // Now we want to update the contents of the stamp file, if necessary. First // we read off the previous contents along with its mtime. If our new // contents (the list of files to copy) is different or if any dep's mtime // is newer then we rewrite the stamp file. </del> deps.sort(); <del> let stamp_contents = fs::read(stamp); let stamp_mtime = mtime(&stamp); </del> let mut new_contents = Vec::new(); <del> let mut max = None; let mut max_path = None; </del> for (dep, proc_macro) in deps.iter() { <del> let mtime = mtime(dep); if Some(mtime) > max { max = Some(mtime); max_path = Some(dep.clone()); } </del> new_contents.extend(if *proc_macro { b"h" } else { b"t" }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"0"); } <del> let max = max.unwrap(); let max_path = max_path.unwrap(); let contents_equal = stamp_contents .map(|contents| contents == new_contents) .unwrap_or_default(); if contents_equal && max <= stamp_mtime { builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); return deps.into_iter().map(|(d, _)| d).collect() } if max > stamp_mtime { builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path)); } else { builder.verbose(&format!("updating {:?} as deps changed", stamp)); } </del> t!(fs::write(&stamp, &new_contents)); deps.into_iter().map(|(d, _)| d).collect() }


Question:
Playing with the nighly's existential types, I stumbled upon a compiler stack overflow: Error message:
A better example might be this: removing the from the existential type decleration just compiles fine
Can you try running the compiler inside gdb and produce a backtrace?
<details<summaryBacktrace:</summary</details
It's recursing in Ideally this should cause cycle errors. But I'm assuming Manually computes this without a query. Maybe we should just make a query? This would solve both the FIXME and this issue.
Both examples now produce a cycle error. So we just need to add the two examples to (if there aren't already tests for these situations)

<ins> #![feature(existential_type)] existential type Foo: Fn() -> Foo; //~^ ERROR: cycle detected when processing `Foo` fn crash(x: Foo) -> Foo { x } fn main() { } </ins>


Question:
Playing with the nighly's existential types, I stumbled upon a compiler stack overflow: Error message:
A better example might be this: removing the from the existential type decleration just compiles fine
Can you try running the compiler inside gdb and produce a backtrace?
<details<summaryBacktrace:</summary</details
It's recursing in Ideally this should cause cycle errors. But I'm assuming Manually computes this without a query. Maybe we should just make a query? This would solve both the FIXME and this issue.
Both examples now produce a cycle error. So we just need to add the two examples to (if there aren't already tests for these situations)

<ins> error[E0391]: cycle detected when processing `Foo` --> $DIR/existential-types-with-cycle-error.rs:3:1 | LL | existential type Foo: Fn() -> Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires processing `crash`... --> $DIR/existential-types-with-cycle-error.rs:6:25 | LL |   fn crash(x: Foo) -> Foo { |  _________________________^ LL | |     x LL | | } | |_^ = note: ...which again requires processing `Foo`, completing the cycle note: cycle used when collecting item types in top-level module --> $DIR/existential-types-with-cycle-error.rs:1:1 | LL | / #![feature(existential_type)] LL | | LL | | existential type Foo: Fn() -> Foo; LL | | ...  | LL | | LL | | } | |_^ error: aborting due to previous error For more information about this error, try `rustc --explain E0391`. </ins>


Question:
Playing with the nighly's existential types, I stumbled upon a compiler stack overflow: Error message:
A better example might be this: removing the from the existential type decleration just compiles fine
Can you try running the compiler inside gdb and produce a backtrace?
<details<summaryBacktrace:</summary</details
It's recursing in Ideally this should cause cycle errors. But I'm assuming Manually computes this without a query. Maybe we should just make a query? This would solve both the FIXME and this issue.
Both examples now produce a cycle error. So we just need to add the two examples to (if there aren't already tests for these situations)

<ins> #![feature(existential_type)] pub trait Bar<T> { type Item; } existential type Foo: Bar<Foo, Item = Foo>; //~^ ERROR: cycle detected when processing `Foo` fn crash(x: Foo) -> Foo { x } fn main() { } </ins>


Question:
Playing with the nighly's existential types, I stumbled upon a compiler stack overflow: Error message:
A better example might be this: removing the from the existential type decleration just compiles fine
Can you try running the compiler inside gdb and produce a backtrace?
<details<summaryBacktrace:</summary</details
It's recursing in Ideally this should cause cycle errors. But I'm assuming Manually computes this without a query. Maybe we should just make a query? This would solve both the FIXME and this issue.
Both examples now produce a cycle error. So we just need to add the two examples to (if there aren't already tests for these situations)

<ins> error[E0391]: cycle detected when processing `Foo` --> $DIR/existential-types-with-cycle-error2.rs:7:1 | LL | existential type Foo: Bar<Foo, Item = Foo>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires processing `crash`... --> $DIR/existential-types-with-cycle-error2.rs:10:25 | LL |   fn crash(x: Foo) -> Foo { |  _________________________^ LL | |     x LL | | } | |_^ = note: ...which again requires processing `Foo`, completing the cycle note: cycle used when collecting item types in top-level module --> $DIR/existential-types-with-cycle-error2.rs:1:1 | LL | / #![feature(existential_type)] LL | | LL | | pub trait Bar<T> { LL | |     type Item; ...  | LL | | LL | | } | |_^ error: aborting due to previous error For more information about this error, try `rustc --explain E0391`. </ins>


Question:
These are the most common tools for concurrency in Rust. They should always be at hand.
Also
If we add we should also add and .
Agreed
Fixed by brson's commit.

pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; pub use vec::{OwnedVector, OwnedCopyableVector}; <ins> /* Reexported runtime types */ pub use comm::{stream, Port, Chan, GenericChan, GenericSmartChan, GenericPort, Peekable}; pub use task::spawn; </ins> /* Reexported modules */ pub use at_vec;


Question:
As of we'll be updating to a version of the RLS which depends on racer which depends on . Unfortunately we're bringing in two different versions of , 209 and 211, right now. These should be deduplicated as they take a good deal of time to build on CI, and then we should also add a check which ensures that there's only one version of in our workspace. cc
I've sent a PR to update racer as part of
This is fixed by

// versions of them accidentally sneak into our dependency graph to // ensure we keep our CI times under control // "cargo", // FIXME(#53005) <del> // "rustc-ap-syntax", // FIXME(#53006) </del> <ins> "rustc-ap-syntax", </ins> ]; let mut name_to_id = HashMap::new(); for node in resolve.nodes.iter() {


Question:
(edit: much simpler reproducer at second post) (see edit history for the initial issue text) Potential duplicate of and cc
(edit: updated to nightly from 2018-08-14, as the error message changed) Another simpler reproducer: Backtrace: The backtrace looks quite different though, so I guess a fix for this one should also be checked to fix the first example.
Latest nightly appears to have fixed the ICE, however it's still making unbounded recursion :)
Async-await traige: Marking as blocking pending investigation to understand what is happening.
Alright, so here's what I've worked out so far: I was able to reproduce the ICE from the original code snippet using the compiler version and library versions from when the issue was reported ( was the closest version I could find and I had to use patch to make Cargo download versions of libraries that worked). I was then able to confirm that the reproduction supplied in the next comment also triggered the ICE. I was then able to get rid of the external dependencies (mostly by copying in parts of that version of futures) and still get the ICE - . After that, I upgraded to as mentioned in the next comment and confirmed that the ICE had been fixed and the unbounded recursion was happening with that same test case. Then, I took that test case that was confirmed to have the problem and tried to run it on the latest nightly - I had to make some minor adjustments as the pin module had changed since August, but I couldn't get the recursion error to happen. I'm inclined to say that this has been fixed at some point - .
I've submitted with a regression test for this issue. if you are able to reproduce this failure on a more recent nightly then feel free to re-open or file a new issue.
Sounds good to me, thanks!

<ins> // compile-pass // edition:2018 #![feature(arbitrary_self_types, async_await, await_macro)] use std::task::{self, Poll}; use std::future::Future; use std::marker::Unpin; use std::pin::Pin; // This is a regression test for a ICE/unbounded recursion issue relating to async-await. #[derive(Debug)] #[must_use = "futures do nothing unless polled"] pub struct Lazy<F> { f: Option<F> } impl<F> Unpin for Lazy<F> {} pub fn lazy<F, R>(f: F) -> Lazy<F> where F: FnOnce(&mut task::Context) -> R, { Lazy { f: Some(f) } } impl<R, F> Future for Lazy<F> where F: FnOnce(&mut task::Context) -> R, { type Output = R; fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<R> { Poll::Ready((self.f.take().unwrap())(cx)) } } async fn __receive<WantFn, Fut>(want: WantFn) -> () where Fut: Future<Output = ()>, WantFn: Fn(&Box<Send + 'static>) -> Fut, { await!(lazy(|_| ())); } pub fn basic_spawn_receive() { async { await!(__receive(|_| async { () })) }; } fn main() {} </ins>


Question: The following code: Produces the following error message: This error message tells you that the types are mismatched, but doesn't fully explain why. To fix it, you need to use a floating point literal instead of an integer literal. This isn't clear from the error message. If you're new to programming or if you come from a language that doesn't draw the same distinction between integer and floating point literals, it may not be clear why the literal is not the same as . It would be great if we could add something in our error message that would suggest one or more of the valid ways to fix this: - - type could be in another context

use std::fmt; use rustc_target::spec::abi; use syntax::ast; <del> use errors::DiagnosticBuilder; </del> <ins> use errors::{Applicability, DiagnosticBuilder}; </ins> use syntax_pos::Span; use hir;


Question: The following code: Produces the following error message: This error message tells you that the types are mismatched, but doesn't fully explain why. To fix it, you need to use a floating point literal instead of an integer literal. This isn't clear from the error message. If you're new to programming or if you come from a language that doesn't draw the same distinction between integer and floating point literals, it may not be clear why the literal is not the same as . It would be great if we could add something in our error message that would suggest one or more of the valid ways to fix this: - - type could be in another context

db.note("no two closures, even if identical, have the same type"); db.help("consider boxing your closure and/or using it as a trait object"); } <ins> match (&values.found.sty, &values.expected.sty) { // Issue #53280 (ty::TyInfer(ty::IntVar(_)), ty::TyFloat(_)) => { if let Ok(snippet) = self.sess.codemap().span_to_snippet(sp) { if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') { db.span_suggestion_with_applicability( sp, "use a float literal", format!("{}.0", snippet), Applicability::MachineApplicable ); } } }, _ => {} } </ins> }, OldStyleLUB(err) => { db.note("this was previously accepted by the compiler but has been phased out");


Question: The following code: Produces the following error message: This error message tells you that the types are mismatched, but doesn't fully explain why. To fix it, you need to use a floating point literal instead of an integer literal. This isn't clear from the error message. If you're new to programming or if you come from a language that doesn't draw the same distinction between integer and floating point literals, it may not be clear why the literal is not the same as . It would be great if we could add something in our error message that would suggest one or more of the valid ways to fix this: - - type could be in another context

--> $DIR/catch-block-type-error.rs:18:9 | LL |         42 <del> |         ^^ expected f32, found integral variable </del> <ins> |         ^^ |         | |         expected f32, found integral variable |         help: use a float literal: `42.0` </ins> | = note: expected type `f32` found type `{integer}`


Question: The following code: Produces the following error message: This error message tells you that the types are mismatched, but doesn't fully explain why. To fix it, you need to use a floating point literal instead of an integer literal. This isn't clear from the error message. If you're new to programming or if you come from a language that doesn't draw the same distinction between integer and floating point literals, it may not be clear why the literal is not the same as . It would be great if we could add something in our error message that would suggest one or more of the valid ways to fix this: - - type could be in another context

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { let sixteen: f32 = 16; //~^ ERROR mismatched types //~| HELP use a float literal let a_million_and_seventy: f64 = 1_000_070; //~^ ERROR mismatched types //~| HELP use a float literal let negative_nine: f32 = -9; //~^ ERROR mismatched types //~| HELP use a float literal // only base-10 literals get the suggestion let sixteen_again: f64 = 0x10; //~^ ERROR mismatched types let and_once_more: f32 = 0o20; //~^ ERROR mismatched types } </ins>


Question: The following code: Produces the following error message: This error message tells you that the types are mismatched, but doesn't fully explain why. To fix it, you need to use a floating point literal instead of an integer literal. This isn't clear from the error message. If you're new to programming or if you come from a language that doesn't draw the same distinction between integer and floating point literals, it may not be clear why the literal is not the same as . It would be great if we could add something in our error message that would suggest one or more of the valid ways to fix this: - - type could be in another context

<ins> error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:12:24 | LL |     let sixteen: f32 = 16; |                        ^^ |                        | |                        expected f32, found integral variable |                        help: use a float literal: `16.0` | = note: expected type `f32` found type `{integer}` error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:15:38 | LL |     let a_million_and_seventy: f64 = 1_000_070; |                                      ^^^^^^^^^ |                                      | |                                      expected f64, found integral variable |                                      help: use a float literal: `1_000_070.0` | = note: expected type `f64` found type `{integer}` error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:18:30 | LL |     let negative_nine: f32 = -9; |                              ^^ |                              | |                              expected f32, found integral variable |                              help: use a float literal: `-9.0` | = note: expected type `f32` found type `{integer}` error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:25:30 | LL |     let sixteen_again: f64 = 0x10; |                              ^^^^ expected f64, found integral variable | = note: expected type `f64` found type `{integer}` error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:27:30 | LL |     let and_once_more: f32 = 0o20; |                              ^^^^ expected f32, found integral variable | = note: expected type `f32` found type `{integer}` error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. </ins>


Question: We should only pass stage0 in general, should be sufficient for all use cases. cc for awareness and in case there's any concerns

let mut cmd = Command::new(rustc); cmd.args(&args) <del> .arg("--cfg") .arg(format!("stage{}", stage)) </del> .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); let mut maybe_crate = None; <ins> // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift // compiler libraries and such from stage 1 to 2. if stage == "0" { cmd.arg("--cfg").arg("bootstrap"); } </ins> // Print backtrace in case of ICE if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() { cmd.env("RUST_BACKTRACE", "1");


Question: We should only pass stage0 in general, should be sufficient for all use cases. cc for awareness and in case there's any concerns

if !up_to_date(src_file, dst_file) { let mut cmd = Command::new(&builder.initial_rustc); builder.run(cmd.env("RUSTC_BOOTSTRAP", "1") <del> .arg("--cfg").arg("stage0") </del> <ins> .arg("--cfg").arg("bootstrap") </ins> .arg("--target").arg(target) .arg("--emit=obj") .arg("-o").arg(dst_file)


Question: We should only pass stage0 in general, should be sufficient for all use cases. cc for awareness and in case there's any concerns

/// Returns the result of an unchecked addition, resulting in /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`. <del> #[cfg(not(stage0))] </del> <ins> #[cfg(not(bootstrap))] </ins> pub fn unchecked_add<T>(x: T, y: T) -> T; /// Returns the result of an unchecked substraction, resulting in /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`. <del> #[cfg(not(stage0))] </del> <ins> #[cfg(not(bootstrap))] </ins> pub fn unchecked_sub<T>(x: T, y: T) -> T; /// Returns the result of an unchecked multiplication, resulting in /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`. <del> #[cfg(not(stage0))] </del> <ins> #[cfg(not(bootstrap))] </ins> pub fn unchecked_mul<T>(x: T, y: T) -> T; /// Performs rotate left.


Question: We should only pass stage0 in general, should be sufficient for all use cases. cc for awareness and in case there's any concerns

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] <del> #[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)] </del> <ins> #[cfg_attr(not(bootstrap), rustc_nonnull_optimization_guaranteed)] </ins> pub struct $Ty($Int); }


Question: We should only pass stage0 in general, should be sufficient for all use cases. cc for awareness and in case there's any concerns

#[stable(feature = "nonnull", since = "1.25.0")] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] <del> #[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)] </del> <ins> #[cfg_attr(not(bootstrap), rustc_nonnull_optimization_guaranteed)] </ins> pub struct NonNull<T: ?Sized> { pointer: *const T, }


Question:
Let's say you have the following (simplified) code: () This results in the following error: The suggested fix will work, but already copies the data so the extra is wasteful. The error message should instead suggest . This is an error you can run into if was previously of type and you changed it to a slice after writing the rest of the code.
Note: this kind of improvement applies to too: Err:

if receiver.ends_with(&method_call) { None  // do not suggest code that is already there (#53348) } else { <del> Some(format!("{}{}", receiver, method_call)) </del> <ins> /* methods defined in `method_call_list` will overwrite `.clone()` in copy of `receiver` */ let method_call_list = [".to_vec()", ".to_string()"]; if receiver.ends_with(".clone()") && method_call_list.contains(&method_call.as_str()){ // created copy of `receiver` because we don't want other // suggestion to get affected let mut new_receiver = receiver.clone(); let max_len = new_receiver.rfind(".").unwrap(); new_receiver.truncate(max_len); Some(format!("{}{}", new_receiver, method_call)) } else { Some(format!("{}{}", receiver, method_call)) } </ins> } }) .collect::<Vec<_>>(); if !suggestions.is_empty() {


Question:
Let's say you have the following (simplified) code: () This results in the following error: The suggested fix will work, but already copies the data so the extra is wasteful. The error message should instead suggest . This is an error you can run into if was previously of type and you changed it to a slice after writing the rest of the code.
Note: this kind of improvement applies to too: Err:

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { let items = vec![1, 2, 3]; let ref_items: &[i32] = &items; let items_clone: Vec<i32> = ref_items.clone(); // in that case no suggestion will be triggered let items_clone_2:Vec<i32> = items.clone(); let s = "hi"; let string: String = s.clone(); // in that case no suggestion will be triggered let s2 = "hi"; let string_2: String = s2.to_string(); } </ins>


Question:
Let's say you have the following (simplified) code: () This results in the following error: The suggested fix will work, but already copies the data so the extra is wasteful. The error message should instead suggest . This is an error you can run into if was previously of type and you changed it to a slice after writing the rest of the code.
Note: this kind of improvement applies to too: Err:

<ins> error[E0308]: mismatched types --> $DIR/issue-53692.rs:13:37 | LL |         let items_clone: Vec<i32> = ref_items.clone(); |                                     ^^^^^^^^^^^^^^^^^ |                                     | |                                     expected struct `std::vec::Vec`, found &[i32] |                                     help: try using a conversion method: `ref_items.to_vec()` | = note: expected type `std::vec::Vec<i32>` found type `&[i32]` error[E0308]: mismatched types --> $DIR/issue-53692.rs:19:30 | LL |         let string: String = s.clone(); |                              ^^^^^^^^^ |                              | |                              expected struct `std::string::String`, found &str |                              help: try using a conversion method: `s.to_string()` | = note: expected type `std::string::String` found type `&str` error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. </ins>


Question:
This example (reduced from ) either crashes LLVM or makes it emit an assertion: I suspect the loops aren't needed, but the control-flow there affects the bug in finicky ways. The name of the module appears to be important and tied to the fact that we end up emitting in a symbol name (because of the ), which gets mangled as (note the two dots). Among other things, changing the we use to mangle , to makes the bug go away. Assertion message (if LLVM assertions are enabled): Stack backtrace for SIGSEGV (if LLVM assertions are disabled): cc
Found the culprit in : LLVM implicitly assumes that cannot show up randomly in symbol names, and rustc breaks that assumption - but LLVM never checks it, so it shares part of the blame here, IMO. Probably the correct thing to do for LLVM is to split the string at the last , instead of the first.
Why are computers
The work around I introduced with the above commit is a proposition of and fixes this issue with the segfault.
Sanitizing to and adding a debug assertion would also be a good idea.

// for ':' and '-' '-' | ':' => self.path.temp_buf.push('.'), <ins> // Avoid segmentation fault on some platforms, see #60925. 'm' if self.path.temp_buf.ends_with(".llv") => self.path.temp_buf.push_str("$6d$"), </ins> // These are legal symbols 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.path.temp_buf.push(c),


Question:
This example (reduced from ) either crashes LLVM or makes it emit an assertion: I suspect the loops aren't needed, but the control-flow there affects the bug in finicky ways. The name of the module appears to be important and tied to the fact that we end up emitting in a symbol name (because of the ), which gets mangled as (note the two dots). Among other things, changing the we use to mangle , to makes the bug go away. Assertion message (if LLVM assertions are enabled): Stack backtrace for SIGSEGV (if LLVM assertions are disabled): cc
Found the culprit in : LLVM implicitly assumes that cannot show up randomly in symbol names, and rustc breaks that assumption - but LLVM never checks it, so it shares part of the blame here, IMO. Probably the correct thing to do for LLVM is to split the string at the last , instead of the first.
Why are computers
The work around I introduced with the above commit is a proposition of and fixes this issue with the segfault.
Sanitizing to and adding a debug assertion would also be a good idea.

<ins> // compile-pass // This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the // reproduction compiles successfully and doesn't segfault, whereas that test just checks that the // symbol mangling fix produces the correct result. fn dummy() {} mod llvm { pub(crate) struct Foo; } mod foo { pub(crate) struct Foo<T>(T); impl Foo<::llvm::Foo> { pub(crate) fn foo() { for _ in 0..0 { for _ in &[::dummy()] { ::dummy(); ::dummy(); ::dummy(); } } } } pub(crate) fn foo() { Foo::foo(); Foo::foo(); } } pub fn foo() { foo::foo(); } fn main() {} </ins>


Question:
This example (reduced from ) either crashes LLVM or makes it emit an assertion: I suspect the loops aren't needed, but the control-flow there affects the bug in finicky ways. The name of the module appears to be important and tied to the fact that we end up emitting in a symbol name (because of the ), which gets mangled as (note the two dots). Among other things, changing the we use to mangle , to makes the bug go away. Assertion message (if LLVM assertions are enabled): Stack backtrace for SIGSEGV (if LLVM assertions are disabled): cc
Found the culprit in : LLVM implicitly assumes that cannot show up randomly in symbol names, and rustc breaks that assumption - but LLVM never checks it, so it shares part of the blame here, IMO. Probably the correct thing to do for LLVM is to split the string at the last , instead of the first.
Why are computers
The work around I introduced with the above commit is a proposition of and fixes this issue with the segfault.
Sanitizing to and adding a debug assertion would also be a good idea.

<ins> #![feature(rustc_attrs)] // This test is the same code as in ui/issue-53912.rs but this test checks that the symbol mangling // fix produces the correct result, whereas that test just checks that the reproduction compiles // successfully and doesn't segfault fn dummy() {} mod llvm { pub(crate) struct Foo; } mod foo { pub(crate) struct Foo<T>(T); impl Foo<::llvm::Foo> { #[rustc_symbol_name] //~^ ERROR _ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE pub(crate) fn foo() { for _ in 0..0 { for _ in &[::dummy()] { ::dummy(); ::dummy(); ::dummy(); } } } } pub(crate) fn foo() { Foo::foo(); Foo::foo(); } } pub fn foo() { foo::foo(); } fn main() {} </ins>


Question:
This example (reduced from ) either crashes LLVM or makes it emit an assertion: I suspect the loops aren't needed, but the control-flow there affects the bug in finicky ways. The name of the module appears to be important and tied to the fact that we end up emitting in a symbol name (because of the ), which gets mangled as (note the two dots). Among other things, changing the we use to mangle , to makes the bug go away. Assertion message (if LLVM assertions are enabled): Stack backtrace for SIGSEGV (if LLVM assertions are disabled): cc
Found the culprit in : LLVM implicitly assumes that cannot show up randomly in symbol names, and rustc breaks that assumption - but LLVM never checks it, so it shares part of the blame here, IMO. Probably the correct thing to do for LLVM is to split the string at the last , instead of the first.
Why are computers
The work around I introduced with the above commit is a proposition of and fixes this issue with the segfault.
Sanitizing to and adding a debug assertion would also be a good idea.

<ins> error: symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE) --> $DIR/issue-60925.rs:16:9 | LL |         #[rustc_symbol_name] |         ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> // check-pass // ignore-emscripten no llvm_asm! support #![feature(llvm_asm)] pub fn boot(addr: Option<u32>) { unsafe { llvm_asm!("mov sp, $0"::"r" (addr)); } } fn main() {} </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> // edition:2018 use std::sync::{Arc, Mutex}; pub async fn f(_: ()) {} pub async fn run() { let x: Arc<Mutex<()>> = unimplemented!(); f(*x.lock().unwrap()).await; } </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> // aux-build: issue_67893.rs // edition:2018 // dont-check-compiler-stderr // FIXME(#71222): Add above flag because of the difference of stderrs on some env. extern crate issue_67893; fn g(_: impl Send) {} fn main() { g(issue_67893::run()) //~^ ERROR: `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely } </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> #![feature(intrinsics)] extern "C" { pub static FOO: extern "rust-intrinsic" fn(); } fn main() { FOO() //~ ERROR: use of extern static is unsafe } </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-28575.rs:8:5 | LL |     FOO() |     ^^^ use of extern static | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior error: aborting due to previous error For more information about this error, try `rustc --explain E0133`. </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> pub static TEST_STR: &'static str = "Hello world"; </ins>


Question:
Take the following code: Attempting to compile this results in the following: I think the compiler should fail with something along the lines of "you attempted to use a complex type () where I expected an immediate".
edit: not sure if these symptoms are the same, but here's what I stumbled across. The following code generates a similar result for me: The and struct seem to be required, else the ICE is not triggered. Output
No longer reproduces:

<ins> // aux-build: issue_24843.rs // check-pass extern crate issue_24843; static _TEST_STR_2: &'static str = &issue_24843::TEST_STR; fn main() {} </ins>


Question:
This page: It's not obvious that reference equality is accomplished via implicit reference-pointer coercion plus . The docs mention this, but I would not look there to find reference equality. The reference primitive page is someplace I would look for info about reference equality. Update this page to discuss reference equality, and link to .
Can I help with this issue?
Still waiting for your reply
Sorry, it looks like got to this now, in

/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and /// references with longer lifetimes can be freely coerced into references with shorter ones. /// <ins> /// Reference equality by address, instead of comparing the values pointed to, is accomplished via /// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while /// [`PartialEq`] compares values. /// /// [`ptr::eq`]: ptr/fn.eq.html /// [`PartialEq`]: cmp/trait.PartialEq.html /// /// ``` /// use std::ptr; /// /// let five = 5; /// let other_five = 5; /// let five_ref = &five; /// let same_five_ref = &five; /// let other_five_ref = &other_five; /// /// assert!(five_ref == same_five_ref); /// assert!(five_ref == other_five_ref); /// /// assert!(ptr::eq(five_ref, same_five_ref)); /// assert!(!ptr::eq(five_ref, other_five_ref)); /// ``` /// </ins> /// For more information on how to use references, see [the book's section on "References and /// Borrowing"][book-refs]. /// /// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html /// <ins> /// # Trait implementations /// </ins> /// The following traits are implemented for all `&T`, regardless of the type of its referent: /// /// * [`Copy`]


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

}; if self.can_coerce(ref_ty, expected) { if let Ok(src) = cm.span_to_snippet(sp) { <del> let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756) </del> <ins> let needs_parens = match expr.node { // parenthesize if needed (Issue #46756) </ins> hir::ExprKind::Cast(_, _) | <del> hir::ExprKind::Binary(_, _, _) => format!("({})", src), _ => src, </del> <ins> hir::ExprKind::Binary(_, _, _) => true, // parenthesize borrows of range literals (Issue #54505) _ if self.is_range_literal(expr) => true, _ => false, </ins> }; <ins> let sugg_expr = if needs_parens { format!("({})", src) } else { src }; </ins> if let Some(sugg) = self.can_use_as_ref(expr) { return Some(sugg); }