Question: participle: &'tcx str, name_list: DiagSymbolList, #[subdiagnostic] <del> change_fields_suggestion: ChangeFieldsToBeOfUnitType, </del> <ins> change_fields_suggestion: ChangeFields, </ins> #[subdiagnostic] parent_info: Option<ParentInfo<'tcx>>, #[subdiagnostic]

The idea of changing a field to unit type to preserve field numbering makes sense for fields in the middle of a tuple. However, if the unused field is at the end, or it's the only field, then deleting it won't affect field numbering of any other field. No response No response <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: [78429]: https://github.com/rust-lang/rust/pull/78429 [82733]: https://github.com/rust-lang/rust/pull/82733 [82594]: https://github.com/rust-lang/rust/pull/82594 <ins> [79078]: https://github.com/rust-lang/rust/pull/79078 </ins> [cargo/9181]: https://github.com/rust-lang/cargo/pull/9181 [`char::MAX`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.MAX [`char::REPLACEMENT_CHARACTER`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.REPLACEMENT_CHARACTER

<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --Input to is able to see underlying derive attributes. This is not supposed to happen as per the change in . A to remove this effect. But onwards, underlying attributes are visible again to derive and this is not mentioned in . Example code is available here: In the following code below, generates a function named which prints all derive attributes visible to it. is defined as: Ouputs a blank line: : :
cc - I believe the new behavior is the one we want, since it makes derived 'just another attribute'. If so, we should document it more clearly in the release notes.
This change was made by , but that PR was never tagged with for some reason.
Triage: dropping and as this isn't an actual regression.


Question: cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } <del> fn check_must_use( </del> <ins> // Returns whether an error has been emitted (and thus another does not need to be later). fn check_must_use_ty<'tcx>( cx: &LateContext<'_, 'tcx>, ty: Ty<'tcx>, expr: &hir::Expr, span: Span, descr_post_path: &str, ) -> bool { if ty.is_unit() || cx.tcx.is_ty_uninhabited_from( cx.tcx.hir().get_module_parent_by_hir_id(expr.hir_id), ty) { return true; } match ty.sty { ty::Adt(def, _) => check_must_use_def(cx, def.did, span, "", descr_post_path), ty::Opaque(def, _) => { let mut has_emitted = false; for (predicate, _) in &cx.tcx.predicates_of(def).predicates { if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate { let trait_ref = poly_trait_predicate.skip_binder().trait_ref; let def_id = trait_ref.def_id; if check_must_use_def(cx, def_id, span, "implementer of ", "") { has_emitted = true; break; } } } has_emitted } ty::Dynamic(binder, _) => { let mut has_emitted = false; for predicate in binder.skip_binder().iter() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate { let def_id = trait_ref.def_id; if check_must_use_def(cx, def_id, span, "", " trait object") { has_emitted = true; break; } } } has_emitted } ty::Tuple(ref tys) => { let mut has_emitted = false; let spans = if let hir::ExprKind::Tup(comps) = &expr.node { debug_assert_eq!(comps.len(), tys.len()); comps.iter().map(|e| e.span).collect() } else { vec![] }; for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { let descr_post_path = &format!(" in tuple element {}", i); let span = *spans.get(i).unwrap_or(&span); if check_must_use_ty(cx, ty, expr, span, descr_post_path) { has_emitted = true; } } has_emitted } _ => false, } } // Returns whether an error has been emitted (and thus another does not need to be later). fn check_must_use_def( </ins> cx: &LateContext<'_, '_>, def_id: DefId, <del> sp: Span, </del> <ins> span: Span, </ins> descr_pre_path: &str, descr_post_path: &str, ) -> bool {

gives a warning, but does not.
suggested that we test this out with crater to see if this would generate much substantial noise and how common it would be.
I'd expect it'd be a pretty substantial source of warnings, but that's exactly why I think we should introduce it. People compiling with are asking for these sorts of bugs to be caught, and we should serve them appropriately ;) In any case, running crater would require having an implementation to do a crater run on, so let's do it!
Let's do it. (I'd personally even like an attribute to allow people to opt-in to this for , for example, when T is itself . That way if I make a , I'll get a warning on that I normally wouldn't want but plausibly do now that I'm getting s in the s.)
I've opened a pull request to try this out:
We discussed this on the language team meeting; folks felt generally positive, but we'd like to do a crater run to see what the impact would be like and if there would be many false positives.
I tried this using but it does not seemed to complain when the part of is not used, is the the correct behavior? I hit this when doing where I didn't use part of the tuple which cause it to not work, which I did not know is required to be used.
putting it into a binding, even an unused one, is considered a use, like how doesn't lint. With just calling it lints:


Question: // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. if let ExprKind::Struct(_, eps, _) = &parent_expr.node { <del> debug_assert_eq!(eps.len(), 2); </del> <ins> if eps.len() != 2 { return false; } </ins> // We can suggest using an inclusive range // (`..=`) instead only if it is the `end` that is // overflowing and only by 1.

An ICE is observable with this code: Changing to take a rather than makes the ICE go away.
Investigation shows that will trigger the ICE, while will not
Introduced in cc We can probably get away with doing an early return if and no other changes.


Question: fn resolve( &self, path_str: &str, <ins> disambiguator: Option<&str>, </ins> ns: Namespace, current_item: &Option<String>, parent_id: Option<hir::HirId>,

I tried to document this code: I expected to see this happen: charstd::char` points to module page of char type points to char primitive page Instead, this happened: type points to module page of char :
I think the problem is that modules are in the type namespace, so is doing exactly what you are asking it for (the module, since it has higher priority). Since the built-in types scope is the lowest precedence, perhaps there needs to be a way to access it directly? Maybe something like or ? Or maybe should skip over modules, and keep looking deeper in the scope hierarchy? (cc )
Oh hmm I see what you mean. There are : Types, values, and macros. Since modules and types are in the same namespace, it uses the first one it finds. Maybe we could work around this by first resolving in an empty module (so it has nothing in scope), then only falling back to the current scope if we don't find something there?
I'm surprised this hasn't caused trouble before now. Does the root of never use the primitive?
I don't know how it works, but the resolver is smart enough to know that in a type context won't match a module (like , the won't match a module named "char". Maybe it has something to do with late-resolution  which has a to give it some context?
Adding that would be more of area ... I can give it a shot though.
It looks like doesn't even return a resolution and only records it for later use ... I'm going to go with the empty module workaround and we can fix it later if it turns out to cause issues.
The double resolve seems hacky. We could probably make type@ specifically not resolve to a module, perhaps? Also, note that modules are in all namespaces
How would that work? We could skip any module resolutions, but since modules have precedence over types I don't know how we'd get the primitive type to resolve afterwards.
Oh hold on we have a function already. We can look at directly.
This doesn't have anything to do with primitives, this has to do with glob imports vs non-glob imports. You can get the same issue with the following:
This also doesn't have to do with modules being "resolved first" or anything. Things that are non-glob in-scope are resolved first.


Question: fn resolve( &self, path_str: &str, <ins> disambiguator: Option<&str>, </ins> ns: Namespace, current_item: &Option<String>, parent_id: Option<hir::HirId>,

Actually, my bad: This does have to do with primitives in the sense that primitives are the only thing that still work when shadowed because of some special code in checking the primitive tables. I think when the string matches one of the primitive table entries for TypeNS lookups that were explicitly annotated with type@ and resolve to a module we can hack this in. In the future we might want to tighten up this code so that e.g. can't resolve to an enum, etc.
do you mind if I fix at the same time and resolve primitives even before modules? That seems like the less surprising behavior to me, the module can still be disambiguated with .
I'm a bit wary of doing this because having the char module in scope is not a common situation, and it will get weirder for people who have a different char module. I think we should resolve to whatever is in scope, but if is explicitly mentioned we can then force resolve to the primitive.


Question: <ins> // issue: rust-lang/rust#127868 fn main() { let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,; } //~ ERROR mismatched closing delimiter: `}` //~ ERROR this file contains an unclosed delimiter </ins>

In my Fedora installation ended up being a corrupted file. It took me hours to realize, given that the output does not bring any clarity to it. rustc should really have ratelimit detection or something to detect corrupted file instead and inform about this to the user. !
This indeed seems quite confusing; and counter-productive to try to show this blob of errors. Would you be able to provide us with a reproducible example of the issue? Or if you still have it the corrupted file. labels +T-compiler +A-diagnostics +D-verbose +D-confusing +S-needs-repro -needs-triage
So this a problem because I unfortunately deleted the trashed file before someone told me that I should report this as a bug. I regret that I did not store it :-/ BUT I recalled that it was probably for reason a long string of ANSI escape codes. So I did a test string: This creates somewhat similar output as I got, except probably the string was a bit longer in my case.
OK doubling that starts to be almost perfect match:
! ... I'm considering T-shirt design ;-) Made by me and rustc. EDIT: and rendered by excellent terminal emulator foot
Somehow rustc should be able to detect corrupted file in cargo's source repository (or whatever it is called). It was pretty bizarre sight when I encountered this by accident.
Thanks for the repro. label -S-needs-repro
Yeah I mean it is really a huge corner case but it can happen in the case of data corruption (e.g. power outage in middle of write operation). I'd detect frequency of errors and maybe a threshold parameter when it is interpreted as corruption with a sane default value.
yeah, I believe this error comes out from the phase of lexing, which rustc are trying to find all the mismatched delimiters, maybe a threshold is ok for resolve it.


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

Implemented in rust impl<T: PartialEqVec<T{ pub fn remove_item(&mut self, item: &T) -Option<T{ /…/ } }
PR moved to due to reasons
Comments from original thread: think that we should add this method to too. desired?
for you can simply do
I meant specifically a method that searches for the item from the end of the vec instead of the beginning
What do you think about adding ? Just as reduces the runtime complexity from O(n) to O(1) compared to , would reduce it from O(n + (n-m)) to O(n).
I like .
It would be nice if this was more generic. let v: Vec<String= Vec::new(); v.removeitem("s"); <-- fails because &str is not a &String we really want the removeitem "item: &T" to be "something that we can compare equality with the type in the container". This would let remove_item() walk the T items, compare equality, and remove if equal.
Seems reasonable to change the signature to
Reviewing the naming used in method names and the docs, it would seem that iterators yield items while vecs contain elements. Considering that we then we should also remove elements and the method should be called . That name is a bit long so I'd propose simply . However I wonder if we should favor a more general , or have both.
Any plan to stabilize this?
This has been in nightly for a year with no issue reported on the method itself. There are proposals for additional methods, but that shouldn’t block this one. Please submit separate PRs or RFCs. fcp merge
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [x] [x] [ ] [x] [x] [x] [x] Concerns: resolved by Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Are we switching to a bound?
Oops, sorry I missed that. Yes, let’s.


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

Again here, as a maintainer of collections that offer the Vec and VecDeque APIs I'd like at least a summary comment explaining what this method does, why this design was followed, alternatives, and addressing the issues mentioned here that have received zero replies: should this method be to ? : naming issue: why s instead of elements? why instead of , etc.
concern rationale-and-vecdeque Just gonna formally register concern above
Not an issue with the method per se, but it may need to be very clearly documented that the reference is not supposed to be to an item that is in the already, as it creates impossible borrow-checker conundrum. Users coming from the C world of pointers but no proper equality comparison, may be confused by this method, e.g. The name mentioned previously would help.
as the proposer for FCP, do you have thoughts on concern?
My thinking is that the suggested by would sidestep most of the issues here.
cc re.
I don’t have a strong desire for this particular feature myself, I proposed FCP as an effort to reduce the number of features in "unstable limbo". That said: Regarding , sure, I don’t see a reason not to add it there as well. as proposed in sounds good to me. It is more general, and goes with precedent of also taking a boolean callable predicate rather than relying on . (Even further, the precedent of not having a method like that would rely on .)
I notice two things: are a lot of methods similar to this we could add, and its not obvious to me which set of those methods is the ideal set. has sat in FCP concern limbo for 8 months without anyone complaining. I think we should not stabilize this just because it exists, but instead someone should come up with a well justified explanation of exactly what the best "find and remove" set of methods of vec-likes would be.
Good points. (which is stable) and also fit the "find and remove" description, and we had a similar concern about the combinations of filtering v.s. non-filtering and self-exhausting on drop () v.s. not.
resolve rationale-and-vecdeque I don't want to personally be on the hook for blocking this any more
:bell: This is now entering its final comment period, as per the .


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

:bell:
The final comment period, with a disposition to merge, as per the , is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon.
I still think this should be called instead of .
My problem with that name is that it only removes the first matching item, not all that are (though I haven't read the relevant RFC to know whether the name has been hashed out already; I assume it has been).
I don't think the naming issue has been resolved. The implementation is still using the name. then?
Can someone clarify what the status of this is wrt. the conversation above?
An example: I'm writing a proc macro attribute, and amongst the tokens, I expect other attribute to be there. This would be useful to add:
Until we sort this out, you can use
Ping. What's the status of this? Could we stabilize something?
? Given we already have drainfilter for accepting a predicate, it would be nice to have a method that removed a single object from the vector (if there). Removing something from a vec is exceedingly common code. Getting the position and then removing that position is longwinded for such a common operation. (Btw, I think bit of naming is excellent as it highlights that there may be others still in the vec - a method name that prompts one to think is a good thing.)
I use for this, and haven't found it too cumbersome. It differs in that it removes all copies of a given item, but is very easy for many purposes.
Retain everything but the object? As work-arounds go that's shorter, but it's not ideal for expressing intent. Still keen on and .
Just to bring up a different opinion: how about removing this method instead of stabilizing it? While yes, it would be convenient to have, it might not be worth it. For one, is not a good name, as many already said. The name doesn't imply that the first item from the start is removed. is better in that regard, but still doesn't feel completely right. More importantly, if we have , we should certainly also have . Having one but not the other feels arbitrary to me and makes for a surprising API (that's bad).


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

Similarly, we would also want to add the variant of both of those methods. Potentially, we also want to add a variant that removes all items equal to the given . And as also already mentioned, we can also add all those methods to . And why not (without the versions)? Consequently, we would have to add 10 or 15 new methods. Adding fewer would make the API inconsistent IMO. All the functionality can be implemented with very little extra code with iterators.
How do you propose this be implemented with iterators? How about this signature: This uses to make it clear exactly what is removed. The argument and the return type makes it clear that we remove many items. The user has the option of how many to remove ( means all). The returned iterator can be implemented efficiently by shifting the items and then pulling a similar trick (using ) to to yield the removed items.
already mentioned this : I think that one is too complex. Especially when considering the call site, I think it's fairly hard to understand. And the name still does not imply that the search begins at the beginning, which is a big nono for me.
Removing an item from a vec is a very common codepath. Somehow it needs to be a one liner. Having swapremovefirst() and not having removefirst() would be nudging people in the direction of great performance. That seems quite rustic to me. swapremovelast is interesting as there maybe no swap needed if it happens to be the last item - cute. Just have those two functions. That’s the 80% case covered. People who wish to maintain order will just have to have slightly more code. On Fri, 15 Nov 2019 at 19:20, Lukas Kalbertodt <:
I don't understand the focus on removing here. Vec has a lot more members taking an index than and , and only a few to get hold of an index value ( variants and , sort of). Most of the complication in the "workaround" for this remove_item is finding the first index of something: v.iter().position( n == 2) Not too bad, the reminds you it's a linear search, but could be easier.


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

<delWorse for the last index: ().rev().position( v.len() - i - 1) Contrast to the and in that famous vector called string that (ugly names but at least they convey that a search is involved). I've vary rarely needed this, I don't advocate making linear searches easy, it just seems more useful to try to make searching easier, before making search-and-removing easier.
(so does ). And even if it didn't exist, that has no relevance to whether should exist or not, they're separate features, so they can both exist, it isn't either/or. (I personally have had many cases where would have been useful, it's a common operation in any language.)
Waaait! It's getting stabilized without fixing the confusing name! Please please don't call it , as this is the same name as in other languages that can remove item from an array by presenting an item from the same array. Rust's version can't do that due to borrow checker and it's a trap for users.
I absolutely wouldn't call it a trap.
It seems like many people agree that the name should at least be up for debate again. Really unfortunate how the name discussion was somehow forgotten during FCP. So I guess we should revert stabilization as soon as possible so it won't end up in beta?
Sounds reasonable. Maybe someone wants to volunteer to lead the process about settling on a name for this ?
The next release is scheduled for Jan 30th. So we have about 3 weeks to figure out a new name.
I went through the thread again and it seems like the following names are suggestions for the method as it currently exists: (iterators have "items", Vec has "elements") - Personally, I would absolutely include , as that's an important information and . I have no preference between and . However, from reading the thread again it seems there are plenty of other concerns and suggestions that haven't been resolved yet: Adding similar methods: ? ? Replace the method with:  (although I don't understand that one. Is it just a with flipped predicate? In that case I don't think it's useful. If it just removes the first element, then absolutely needs to be in the name IMO.) Do not stabilize this method at all: ,
mentioned : also raised some more concerns , and I raised some concerns .


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

I don't see where these concerns have been resolved. From re-reading this whole discussion, it isn't clear to me what the goal of adding this method is nor what problem does this method solve or whether this is a problem worth solving. What's more or less clear to me is that there is at least some design work to be done to at least ensure that libstd exposes a consistent API, and that sounds like this would warrant an RFC to me. The current discussion about using a method hints that these APIs might not only want to be consistent for the ordered collections (Vec, VecDeque, List) for which a notion of a "first" element makes sense, but might also want to be consistent with the e.g. and methods of slices. The main arguments for FCPing this appear to be that this has sit on nightly for too long without anybody complaining, and the main argument for stabilizing this has been that this has been in FCP for too long. I think it would be better to just encourage and support those that want to land this feature to write a small RFC for it. If somebody is interested in doing that, I would be able to help and give feedback.
Unless a concern is made with by a relevant team member, then it won't stop FCP. And it won't go into FCP unless the majority of team members have voted for it (and there aren't any formal concerns listed). So the fact it passed FCP means that all relevant team members that they were okay with the current design and did not have any outstanding concerns at the time. Things do not go into FCP simply because it's been "sitting around too long". Of course if any team members do have any concerns, now would be the best time to make them.
Mistakes happen. And to me this thread clearly looks like many concerns were overlooked accidentally and no one explicitly marked them as concerns for rfcbot. Luckily those mistakes were caught.
Reopening because
The current signature is missing a ?Sized bound. Could I ask for a PR to fix the bound and add a test that covers remove_item("...") on a Vec<String? This use case was requested in and
Separately: I am leaning toward removing removeitem.


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

I agree with and The currently design involves: start with a reference to a value not in the vec, use its PartialEq impl to do a linear scan, remove the first found, shift everything after the removed element. To generalize almost all of the discussion above, people are questioning whether the conjunction of all 5 of these decisions is really as common as a name like removeitem would suggest, whether a different permutation of choices might be more widely applicable, and how to adjust naming to leave room for all the other equally or more common permutations: ones where the ref we want to remove is a ref to a vec element, or we want to remove by FnMut instead of PartialEq, or we want a binary search, or we want to remove the last, or all matches, or we want the more efficient swapremove behavior. Fortunately Vec already supports all permutations of these use cases equally well, with nice independent APIs for searching and removing. Many people have voiced opinions equivalent to "removing an item from a vec is so common that there absolutely must be a function for it". I think what they mean is that the union of all permutations of the above 5 choices is common, which is true; they don't necessarily mean the specific choices that go into removeitem as it exists would justify a method specific to those choices. points out that satisfying the set of use cases which all together are common would take a much larger number of new methods.
Per , I think we should go ahead and remove . fcp close
That is not what I meant. When I said that I need in my code, I meant exactly that: that I could take my existing code and replace it with and it would have exactly the same behavior, because I really do need specifically, not the other fancier methods. I'm perfectly fine with changing the name so that we can accommodate other fancier methods in the future, but why would that mean that we shouldn't have at all?
fcp cancel
proposal cancelled.
Per , I think we should go ahead and remove . fcp close
Team member has proposed to close this. The next step is review by the rest of the tagged team members: [x] [x] [x] [x] [ ] [x] No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period.


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Checking KodrAus’ checkbox per
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to close, as per the , is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
Since we've merged the deprecation would we like to close this tracking issue now? Or keep it open until the unstable deprecated method is removed entirely?
I think keeping this open until we removed the method is a good idea. How long do we want to wait with that by the way? I guess a couple of cycles is sufficient?
Before closing, it would be great if someone could suggest a "one clean and obvious" way to remove the first/last occurance of an item from a Vector. Irrespective of the arguments made here, a method removing the first/last occurance of an item is provided across all major programming languages, and is to be "expected" Anyone new to rust is bound to google "remove from vec rust" and end up on this discussion which would only leave them more confused.
should answer those questions. But here is a copy of my answer for convenience: You can of course handle the case however you like (panic and ignoring are not the only possibilities). Like the first element, but replace with . Remember that has a runtime of O(n) as all elements after the index need to be shifted. has a runtime of O(1) as it swaps the to-be-removed element with the last one. If the order of elements is not important in your case, use instead of !
It might be worth adding more examples (maybe all of the ones above) to the docs.
I'd like to add those to the docs, should they go along the example that we currently have?
What examples are you referring to? I could imagine those "remove examples" either going on the type (as a new section "Removing elements" or something like that) or directly on the method (below the existing docs). And by the way, feel free to add (parts of) my text/examples verbatim.
Thank you.


Question: #![feature(thread_local)] #![feature(trace_macros)] #![feature(trusted_len)] <del> #![feature(vec_remove_item)] </del> #![feature(stmt_expr_attributes)] #![feature(integer_atomics)] #![feature(test)]

I was referring to those "remove examples" as to whether I should append them to what we currently have in docs for , put them somewhere else or perhaps modify examples for to include removal of specific element
That sounds fine to me. Feel free to just open a PR and we can still see about the specifics then :)


Question: item_name ) }).unwrap(); <del> let impl_span = fcx.tcx().map.def_id_span(impl_did, span); let item_span = fcx.tcx().map.def_id_span(item.def_id(), impl_span); </del> <ins> let note_span = fcx.tcx().map.span_if_local(item.def_id()).or_else(|| { fcx.tcx().map.span_if_local(impl_did) }); </ins> let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty;

I wrote and got this output: The hint in particular was confusing, since it is targeted at developers who created the impl and forgot to provide a argument, rather than consumers of an impl that is specifically designed to be static.
We should probably structure this so that both suggestions are shown. Alternatively, suggest changing the method only when the method is defined in the local crate.
Current compiler message is slightly different: The snippet given for the "candidate " seems wrong, shouldn't it present the definition of (or, if that is not available since it's from , nothing)?
Fixed by .


Question: return (level, src) } <del> fn get_lint_id_level(&self, id: LintId, mut idx: u32) </del> <ins> fn get_lint_id_level(&self, id: LintId, mut idx: u32, aux: Option<&FxHashMap<LintId, (Level, LintSource)>>) </ins> -> (Option<Level>, LintSource) { <ins> if let Some(specs) = aux { if let Some(&(level, src)) = specs.get(&id) { return (Some(level), src) } } </ins> loop { match self.list[idx as usize] { LintSet::CommandLine { ref specs } => {

The following snippet works fine before but now it reports a warning: Steps to reproduce: clone rustup override set nightly-2017-08-11 cargo test Is this an expected behavior, or a bug? Thank you!
cc -- probably related to the new lint implementation
Yes this was caused by The bug is on . The check for whether is in scope is not checking the current set of attributes being linted. For example this does not warn: but this warns: (as you've noticed) The fix is to just take the local variable into account which has the up-to-that-point set of lint attributes collected.
I've opened a PR for this at


Question: libc::execvp(self.get_argv()[0], self.get_argv().as_ptr()); io::Error::last_os_error() } <ins> #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>) -> io::Result<Option<Process>> { Ok(None) } #[cfg(any(target_os = "macos", target_os = "freebsd"))] fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) -> io::Result<Option<Process>> { use mem; use sys; if self.get_cwd().is_some() || self.get_gid().is_some() || self.get_uid().is_some() || self.get_closures().len() != 0 { return Ok(None) } let mut p = Process { pid: 0, status: None }; struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t); impl Drop for PosixSpawnFileActions { fn drop(&mut self) { unsafe { libc::posix_spawn_file_actions_destroy(&mut self.0); } } } struct PosixSpawnattr(libc::posix_spawnattr_t); impl Drop for PosixSpawnattr { fn drop(&mut self) { unsafe { libc::posix_spawnattr_destroy(&mut self.0); } } } unsafe { let mut file_actions = PosixSpawnFileActions(mem::uninitialized()); let mut attrs = PosixSpawnattr(mem::uninitialized()); libc::posix_spawnattr_init(&mut attrs.0); libc::posix_spawn_file_actions_init(&mut file_actions.0); if let Some(fd) = stdio.stdin.fd() { cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, fd, libc::STDIN_FILENO))?; } if let Some(fd) = stdio.stdout.fd() { cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, fd, libc::STDOUT_FILENO))?; } if let Some(fd) = stdio.stderr.fd() { cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, fd, libc::STDERR_FILENO))?; } let mut set: libc::sigset_t = mem::uninitialized(); cvt(libc::sigemptyset(&mut set))?; cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0, &set))?; cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?; cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0, &set))?; let flags = libc::POSIX_SPAWN_SETSIGDEF | libc::POSIX_SPAWN_SETSIGMASK; cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?; let envp = envp.map(|c| c.as_ptr()) .unwrap_or(*sys::os::environ() as *const _); let ret = libc::posix_spawnp( &mut p.pid, self.get_argv()[0], &file_actions.0, &attrs.0, self.get_argv().as_ptr() as *const _, envp as *const _, ); if ret == 0 { Ok(Some(p)) } else { Err(io::Error::from_raw_os_error(ret)) } } } </ins> } ////////////////////////////////////////////////////////////////////////////////

When confusing a Fn-like struct with a regular struct in an pattern, the output leaves a lot to be desired: <details<summary<a href=""Current output</a</summary</detailsWe should probably collect all these errors into a single diagnostic error: Even better if there was only one diagnostic.


Question: span: name_binding.span, segments: path_segments, }; <del> result = Some((module, ImportSuggestion { path })); </del> <ins> let did = module.def().and_then(|def| def.opt_def_id()); result = Some((module, ImportSuggestion { did, path })); </ins> } else { // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) {

For this code: You get the following error message: The suggestion may be excused to be not 100% perfect, but here it suggests to add an use statement despite that same item being imported already. What I want is this exactly: that it removes stuff from the suggestion list that is already being imported. Note that changing the glob import to a non glob one doesn't change anything.
cc
Why is that even an error?
tuple structs have private fields by default, you can't construct instances of B outside of the foo module.
oh ^^ maybe we should simply modify this error message then to say that the "function" is private?
It already says "constructor is not visible here due to private fields". That's okay, but maybe you might have meant another B from another module or something. However, the candidate offered is not any better as its the same one you are attempting to use.
Reopening to track "removal of suggestion" work for pub tuple structs with private fields.


Question: expr.id, method_call, r.datum.to_string(ccx)); return r; <del> /// We microoptimize derefs of owned pointers a bit here. Basically, the idea is to make the /// deref of an rvalue result in an rvalue. This helps to avoid intermediate stack slots in the /// resulting LLVM. The idea here is that, if the `Box<T>` pointer is an rvalue, then we can /// schedule a *shallow* free of the `Box<T>` pointer, and then return a ByRef rvalue into the /// pointer. Because the free is shallow, it is legit to return an rvalue, because we know that /// the contents are not yet scheduled to be freed. The language rules ensure that the contents /// will be used (or moved) before the free occurs. fn deref_owned_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, content_ty: Ty<'tcx>) -> DatumBlock<'blk, 'tcx, Expr> { match datum.kind { RvalueExpr(Rvalue { mode: ByRef }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); let ptr = Load(bcx, datum.val); if !type_is_zero_size(bcx.ccx(), content_ty) { bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange, content_ty); } } RvalueExpr(Rvalue { mode: ByValue }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); if !type_is_zero_size(bcx.ccx(), content_ty) { bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange, content_ty); } } LvalueExpr => { } } // If we had an rvalue in, we produce an rvalue out. let (llptr, kind) = match datum.kind { LvalueExpr => { (Load(bcx, datum.val), LvalueExpr) } RvalueExpr(Rvalue { mode: ByRef }) => { (Load(bcx, datum.val), RvalueExpr(Rvalue::new(ByRef))) } RvalueExpr(Rvalue { mode: ByValue }) => { (datum.val, RvalueExpr(Rvalue::new(ByRef))) } }; let datum = Datum { ty: content_ty, val: llptr, kind: kind }; DatumBlock { bcx: bcx, datum: datum } } </del> } #[derive(Debug)]

Rust compiler (rustc 1.1.0-nightly ( 2015-05-14) (built 2015-05-14) fails to compile this source: With the error: I can reproduce this ICE also on
Reduced it a bit:
The broken IR:
Looking through it quickly, it seems like the order of the cleanups is messed up? If is then from the switch we go to the label which just jumps to where we memcpy the value for into the alloca and then continue to the label. This is where the problem is since it tries to call on the value returned from . But that's the thing, we wouldn't have called in that arm of the branch and hence shouldn't need to call free either.
Adding a block around suppresses the error. I feel like we had a similar problem not too long ago.
This is "caused" by the micro optimization for dereferencing owned pointer rvalues in . Since is the "trailing" expression for the arm its cleanup will be scheduled in the same scope as the match expression. cc
Either way, this is a dupe of I believe had an idea for a fix.
it's simple, we remove the micro-optimization and always return an datum from . The possibility of returning datum also caused issues with field accesses - see for that fix. We have a static type system and the / marker types are there for a reason. If there is no answer to "how is an rvalue dereference or field meaningful?", then the return type for both of those should be .


Question: expr.id, method_call, r.datum.to_string(ccx)); return r; <del> /// We microoptimize derefs of owned pointers a bit here. Basically, the idea is to make the /// deref of an rvalue result in an rvalue. This helps to avoid intermediate stack slots in the /// resulting LLVM. The idea here is that, if the `Box<T>` pointer is an rvalue, then we can /// schedule a *shallow* free of the `Box<T>` pointer, and then return a ByRef rvalue into the /// pointer. Because the free is shallow, it is legit to return an rvalue, because we know that /// the contents are not yet scheduled to be freed. The language rules ensure that the contents /// will be used (or moved) before the free occurs. fn deref_owned_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, content_ty: Ty<'tcx>) -> DatumBlock<'blk, 'tcx, Expr> { match datum.kind { RvalueExpr(Rvalue { mode: ByRef }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); let ptr = Load(bcx, datum.val); if !type_is_zero_size(bcx.ccx(), content_ty) { bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange, content_ty); } } RvalueExpr(Rvalue { mode: ByValue }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); if !type_is_zero_size(bcx.ccx(), content_ty) { bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange, content_ty); } } LvalueExpr => { } } // If we had an rvalue in, we produce an rvalue out. let (llptr, kind) = match datum.kind { LvalueExpr => { (Load(bcx, datum.val), LvalueExpr) } RvalueExpr(Rvalue { mode: ByRef }) => { (Load(bcx, datum.val), RvalueExpr(Rvalue::new(ByRef))) } RvalueExpr(Rvalue { mode: ByValue }) => { (datum.val, RvalueExpr(Rvalue::new(ByRef))) } }; let datum = Datum { ty: content_ty, val: llptr, kind: kind }; DatumBlock { bcx: bcx, datum: datum } } </del> } #[derive(Debug)]

Original testcase by (reduced from ): The debug log reveals that a (shallow free) cleanup of the rvalue is scheduled in the scope of AST node , while the dereference expression itself has id : reveals that id refers to the entire function's block: This means the cleanup of a value valid only within a match arm is scheduled outside the arm. cc
Dupe of Leaving open for now but we can close either.
This is caused by a micro-optimization specific to dereferences of rvalues. Is this used oftenly enough to justify its existence in the first place? Even if it is, I guess we can disable it in problematic cases like this, where the temporary scope of the match arm's RHS is outside the arm.
I think we can probably remove it, in general removing special treatment of seems like a Good Thing
Triage: this still ICEs.
can you point me/us at the micro-optimization that you mentioned above, so that I (we) can try removing it ourselves and measure the impact?
I only vaguely recall this issue, but I'm pretty sure I was talking about .
triage: still ICEs.
Indeed, it doesn't even need : Does this at least continue to ICE even if LLVM is compiled without assertions? If not, we may want to up the priority on this ticket.


Question: HashSet, Hasher, Implied, <ins> IndexOutput, </ins> Input, Into, IntoDiagnostic,

I tried this code (): I expected to see this happen: rustc outputs an error saying that I need to add the and traits on . Instead, this happened: which is jarring to see, and unhelpful, because HashMap does support Index, but only with particular trait bounds on . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
The reduced case: works as expected, perhaps it is caused when the implementer is not from the local crate?
claim


Question: let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::TestHarness, <del> &[sym::test, sym::rustc_attrs], </del> <ins> &[sym::test, sym::rustc_attrs, sym::no_coverage], </ins> None, ); let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --Take this simple crate: If I try to gather code coverage for , I end up with the first line mysteriously duplicated as a covered region: (I'm using for convenience, but the same thing happens when I use and process the coverage data manually with and .) Note that in the report produced by , the first line of the file appears twice. It is marked as having executed once, even though it is a comment. Instead, the line should only appear once, and its execution count (if any) should be the execution count of the actual code on that line. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<!-- <details<summaryBacktrace</summary<p</p</details--
I did some initial investigation, and discovered a few things: The coverage mapping that embeds in the test binary contains entries for two different functions named . One is the actual that appears in the file, and the other is the that is injected by the test harness. The mapping for the injected function spans from (1,0) to (1,1). Coverage mapping regions use 1-based line numbers and column numbers, so a column number of 0 should be impossible. This unexpected column number confuses the processing code in , and results in line 1 being duplicated in the output. : There are special circumstances where it's legal for a region to have 0 for its start column and its end column, but that isn't what's happening here.
The origin of the bogus (1,0) to (1,1) region seems to be: The test harness entry point is created with a dummy span: When that dummy span is converted into a region, its 0-based start is decremented in an attempt to make the region non-empty. This decrement overflows to , and a subsequent increment (to make it 1-based) overflows back to 0.
My first thought was to sidestep the whole issue by adding to the test harness's injected .


Question: let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::TestHarness, <del> &[sym::test, sym::rustc_attrs], </del> <ins> &[sym::test, sym::rustc_attrs, sym::no_coverage], </ins> None, ); let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());

However, I couldn’t get that to work, because is unstable and can't necessarily be used by the crate it is being injected into. So I think the fix will involve having the instrumentor detect and skip code with dummy spans.
label +A-code-coverage
fixes the overflow, which gets rid of the duplicate line. However, the instrumentor still ends up emitting an empty region from (1,1) to (1,1) for the test harness's , so I'd still like to find a way to avoid instrumenting that function.
I think the empty region now confusing the reporter in more subtle ways, because now I see weird stuff like this: It makes sense that line 1 is “covered” (via the injected ), but it's strange that lines 2 and 3 also have non-zero counts.
It looks like does have special handling for empty regions, but it doesn't properly anticipate the first region being empty, and ends up in a slightly confused state.


Question: ///     Ok(()) /// } /// ``` <del> #[unstable(feature = "buffered_io_capacity", issue = "68833")] </del> <ins> #[stable(feature = "buffered_io_capacity", since = "1.46.0")] </ins> pub fn capacity(&self) -> usize { self.buf.len() }

adds methods to and . Unresolved questions:
Can I nominate this for stabilization? It's a straightforward API with no real alternatives possible, and I had a real-world use case for it recently.
CC --^?
fcp merge
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [x] [ ] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon.


Question: <ins> warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/issue-70167.rs:3:12 | LL | #![feature(const_generics)] |            ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default </ins>

results in an ICE (): <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: <ins> // #125634 struct Thing; // Invariant in 'a, Covariant in 'b struct TwoThings<'a, 'b>(*mut &'a (), &'b mut ()); impl Thing { fn enter_scope<'a>(self, _scope: impl for<'b> FnOnce(TwoThings<'a, 'b>)) {} } fn foo() { Thing.enter_scope(|ctx| { SameLifetime(ctx); //~ ERROR lifetime may not live long enough }); } struct SameLifetime<'a>(TwoThings<'a, 'a>); fn main() {} </ins>

<!-- ICE: Rustc '' 'thread 'rustc' panicked at 'expected region for ('a//0) but found Type(&'{erased} mut FooImpl<'{erased}, '{erased}, T/) when instantiating args=[&'{erased} mut FooImpl<'{erased}, '{erased}, T/, '?27, ?2t, Closure(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), ['{erased}, '{erased}, T/, i32, Binder(fn((&ReLateParam(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), BrAnon) mut FooImpl<'{erased}, '{erased}, T/,)), []), ()])]'', 'thread 'rustc' panicked at 'expected region for ('a//0) but found Type(&'{erased} mut FooImpl<'{erased}, '{erased}, T/) when instantiating args=[&'{erased} mut FooImpl<'{erased}, '{erased}, T/, '?27, ?2t, Closure(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), ['{erased}, '{erased}, T/, i32, Binder(fn((&ReLateParam(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), BrAnon) mut FooImpl<'{erased}, '{erased}, T/,)), []), ()])]'' File: --auto-reduced (treereduce-rust): original: Version information ` Command: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongProgram output</strong</summary<p</p</details<!-- query stack: [mirborrowck] borrow-checking [mirborrowck] borrow-checking --
ICEs on nightly and beta, but not on stable. Minimized further: <details<summaryProgram output</summary</details
The ICE is another one from , cc
Still reproduces on 1.81.0-nightly (2024-06-13 ) -E-needs-test
I'll look into it later today.


Question: <ins> // #125634 struct Thing; // Invariant in 'a, Covariant in 'b struct TwoThings<'a, 'b>(*mut &'a (), &'b mut ()); impl Thing { fn enter_scope<'a>(self, _scope: impl for<'b> FnOnce(TwoThings<'a, 'b>)) {} } fn foo() { Thing.enter_scope(|ctx| { SameLifetime(ctx); //~ ERROR lifetime may not live long enough }); } struct SameLifetime<'a>(TwoThings<'a, 'a>); fn main() {} </ins>

: <details<summary<strongBacktrace</strong</summary<p</p</details
This looks to be a recent regression from cc and is on beta 1.79, but is just in diagnostics.


Question: <ins> // compile-flags:-C panic=abort // only-x86_64 #![feature(target_feature_11)] #![no_std] #![no_main] use core::panic::PanicInfo; #[panic_handler] #[target_feature(enable = "avx2")] //~^ ERROR `panic_impl` language item function is not allowed to have `#[target_feature]` fn panic(info: &PanicInfo) -> ! { unimplemented!(); } </ins>

This works (but it shouldn't): similar to , cc (tracking issue) label T-lang T-compiler C-bug I-unsound F-targetfeature11
cc , author of Note that this is about the nostd panic handler, not about the function. This fails as it should: gives
ugh we really need a way to make sure that every single "this is called by rust" function gets a check... I assume that these functions can't be unsafe, so I guess those checks are a food way to start looking and make sure to deduplicate the logic there?
Yeah sadly we do need to make sure, not just for the constructs that we have now but also it needs to be kept in mind for the future constructs we add or stabilize. A lot thankfully goes through either the trait system (operators or the GlobalAlloc trait used by ) or function pointers (alloc error hook, std panic hook). Functions that you can make callable solely by setting an attribute, those are rare. The best list of lang items I could find was in the , so that would be a great start for such an exhaustive search. Thankfully most of them are unstable, but still it needs to be addressed for each of them before stabilization (if that is a target).
WG-prioritization assigning priority (). label -I-prioritize +P-medium
label +requires-nightly
There is also another table of lang items in the source code, .


Question: last } <ins> /// True if a fragment of type `frag` can be followed by any sort of /// token.  We use this (among other things) as a useful approximation /// for when `frag` can be followed by a repetition like `$(...)*` or /// `$(...)+`. In general, these can be a bit tricky to reason about, /// so we adopt a conservative position that says that any fragment /// specifier which consumes at most one token tree can be followed by /// a fragment specifier (indeed, these fragments can be followed by /// ANYTHING without fear of future compatibility hazards). fn can_be_followed_by_any(frag: &str) -> bool { match frag { "item" |  // always terminated by `}` or `;` "block" | // exactly one token tree "ident" | // exactly one token tree "meta" |  // exactly one token tree "tt" =>    // exactly one token tree true, _ => false, } } /// True if `frag` can legally be followed by the token `tok`. For /// fragments that can consume an unbounded numbe of tokens, `tok` /// must be within a well-defined follow set. This is intended to /// guarantee future compatibility: for example, without this rule, if /// we expanded `expr` to include a new binary operator, we might /// break macros that were relying on that binary operator as a /// separator. </ins> fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> { if let &CloseDelim(_) = tok { <ins> // closing a token tree can never be matched by any fragment; // iow, we always require that `(` and `)` match, etc. </ins> Ok(true) } else { match frag {

In an example like we report the following error: This is part of the macro future-proofing code but it is an unnecessary limitation. For fragments that represent at most one token tree (, , , possibly others) there is no concern at all about being following by sequence repetition. This turns out to be a really big limitation in practice, since making macros that work over a generic sequence of token trees effectively allows for arbitrary parsing. cc
triage: P-medium
I'd be happy to mentor this, if I don't fix it first.
triage: P-medium
cc
I-ICE?
Curious why this was closed, looks like it's blocking lispy-rust.
It was fixed by ; do you still see this issue present in nightly?


Question: "before", ":51] { foo += 1; eprintln!("before"); 7331 } = 7331", <ins> ":59] ("Yeah",) = (", "    "Yeah",", ")", ":62] 1 = 1", ":62] 2 = 2", ":66] 1u8 = 1", ":66] 2u32 = 2", ":66] "Yeah" = "Yeah"", </ins> ]); }

It would be nice if the compiler suggested the intended form: as this seems like a reasonable mistake. This is specific to a particular macro, though, so I'm not sure how flexible we can be with diagnostics here.
Or we could just make the macro accept ...


Question: <ins> // Copyright 2016 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 tup = (0, 1, 2); // the case where we show a suggestion let _ = tup[0]; //~^ ERROR cannot index a value of type //~| HELP to access tuple elements, use tuple indexing syntax as shown //~| SUGGESTION let _ = tup.0 // the case where we show just a general hint let i = 0_usize; let _ = tup[i]; //~^ ERROR cannot index a value of type //~| HELP to access tuple elements, use tuple indexing syntax (e.g. `tuple.0`) } </ins>

When trying to (erroneously) access members of a tuple using square brackets, rather than a period, the compiler gives the message " error: cannot index a value of type .... ". Particularly as a new user, it would be nice if the compiler could suggest something like "try using the syntax rather than <tuple[idx]." This isn't by any means a big issue, but it would help eliminate yet another search through the documentation.


Question: let trait_ref = projection.to_poly_trait_ref(tcx); let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); <del> let gen_trait = tcx.lang_items().gen_trait().unwrap(); </del> <ins> let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem); </ins> let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { debug!("deduce_sig_from_projection: not fn or generator");

This somehow doesn't occur when putting the function in a non crate, yet I can't find any difference between the version of and this one. () Errors:
Seems like it panic when the trait is not found: Maybe it can use  instead.


Question: #[inline] pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { self.bytes.extend_from_slice(other); <del> self.is_known_utf8 = self.is_known_utf8 || self.next_surrogate(0).is_none(); </del> <ins> self.is_known_utf8 = false; </ins> } }

Reviewing PR had some oversight regarding valid utf8 checks. This was graciously brought to our (meaning myself and attention by in . Fix should really just be changing to setting to , unless we decide there may be some merit to iterating again through the buffer.
label T-libs C-cleanup O-windows
label -needs-triage


Question: _ => &[], }; let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { <del> hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()), </del> <ins> hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()), </ins> _ => None, }); self.in_scope_lifetimes.extend(lt_def_names);

The diagnostics ("use of undeclared lifetime name") are bad, but this indeed must be an error because the inner is an illegal use of the outer rather than an implicitly defined fresh lifetime.
Hm, I don't think that's quite what I'd expect: previously using in that context would be fine because there is no shadowing so to speak, that is, this compiles:
From Similarly, if a fn definition is nested inside another fn definition, it is an error to mention lifetimes from that outer definition (without binding them explicitly). This is again intended for future-proofing and clarity, and is an edge case. (In the second example there's an explicit definition that shadows the previous definition for following uses, in the first example there's no second definition, only use)
I see that this is in the RFC, but I think I more or less disagree with the reasoning given. Disallowing the use of inband lifetimes when nesting function seems arbitrary and not entirely helpful; it also makes a mechanical change from "old" to "new" more difficult because shadowing is visible only based on indent levels.
IMO it should be an error, with a helpful note like the one you get when writing . Let's not make in-band lifetimes any more confusing than they already are.
The distinction is that inband lifetime's selling point is that you don't need to declare lifetimes. If we say that, and then clarify it with "except" then I think the feature feels incomplete. Inband lifetimes confusion does not increase with permitting this, IMO.
The problem is if it's allowed, then has a different meaning than This seems unfortunate and confusing. Even unergonomic if I may say so. There's no way that the distinction between and won't be missed in a quick scan of the second one. But, like, the RFC process did decide that isn't important, so whatever.
Well, somewhat, but not really. Nothing outside of imports/definitions inherits into the inner function, unlike the impl where there is a history and multiple things which inherit (, lifetimes, generics).


Question: <ins> // run-pass #![feature(bench_black_box)] use std::hint; struct U16(u16); impl Drop for U16 { fn drop(&mut self) { // Prevent LLVM from optimizing away our alignment check. assert!(hint::black_box(self as *mut U16 as usize) % 2 == 0); } } struct HasDrop; impl Drop for HasDrop { fn drop(&mut self) {} } struct Wrapper { _a: U16, b: HasDrop, } #[repr(packed)] struct Misalign(u8, Wrapper); fn main() { let m = Misalign( 0, Wrapper { _a: U16(10), b: HasDrop, }, ); // Put it somewhere definitely even (so the `a` field is definitely at an odd address). let m: ([u16; 0], Misalign) = ([], m); // Move out one field, so we run custom per-field drop logic below. let _x = m.1.1.b; } </ins>

I tried this code: I expected to see this happen: The reference is aligned Instead, this happened: : label I-unsound A-mir
We have a pass to add moves for drops in packed structs, but it doesn't fire in this case. That's because there's a bug - this computation cannot just take into account the innermost field, it needs to compute a minimum of some sort.
is this a regression? What did you exactly expected the output to be? (I'd like to run a bisection). thanks.
This was right in . Getting a consistent reproduction of this is slightly difficult because the reference might happen to align correctly by accident. In other words, the fact that the example above prints a pointer that is not 2-aligned means that something is certainly wrong. However, if the address were to be 2-aligned that could either be because the bug is fixed or because we happened to get lucky. The consistent way to check this is by looking at . In 1.52.0 the MIR contains which is correct (the move ensures that the resulting place is aligned) while 1.53.0 contains Note that there is no move.
WG-prioritization assigning priority (). label -I-prioritize +P-high E-needs-bisection
I have run a bisection with on your . The bisection could not pinpoint a single commit, maybe it sinked into a rollup merge. But if it helps, the regression should be in and coming from one of these PRs do you see in any of those a possible culprit? (I don't have the context to)
Yeah, it's , cc
Not sure how would have an effect here, it should be a NOP for with . Looks like something else is amiss as well and that PR surfaced the bug? Where is the logic that moves packed structs to a new place before dropping implemented? That's odd, I would have expected this to be inside ... after all calling on a packed struct also has to do this move. Why does MIR building adjust the caller to satisfy a requirement that the callee should be responsible for?
the pass is called or something like that.


Question: <ins> // run-pass #![feature(bench_black_box)] use std::hint; struct U16(u16); impl Drop for U16 { fn drop(&mut self) { // Prevent LLVM from optimizing away our alignment check. assert!(hint::black_box(self as *mut U16 as usize) % 2 == 0); } } struct HasDrop; impl Drop for HasDrop { fn drop(&mut self) {} } struct Wrapper { _a: U16, b: HasDrop, } #[repr(packed)] struct Misalign(u8, Wrapper); fn main() { let m = Misalign( 0, Wrapper { _a: U16(10), b: HasDrop, }, ); // Put it somewhere definitely even (so the `a` field is definitely at an odd address). let m: ([u16; 0], Misalign) = ([], m); // Move out one field, so we run custom per-field drop logic below. let _x = m.1.1.b; } </ins>

And this can't take place inside the callee because the callee receives a , and if that reference is unaligned then UB has already occurred and there's nothing the callee can do to fix things anymore
takes a raw pointer, so it could very well be the place where the packed struct alignment trouble is handled. And IMO it'd be a much more natural place than doing this by transforming caller MIR.
I don't understand the suggestion. The example above never calls for a packed struct. The offending drop in the MIR in the example above is . The type of that place is - but if were to be responsible for moving, then we would need to emit a move in literally every drop shim for a non-trivial alignment type.
Oh I see, I didn't quite read the example correctly. The problematic drop is the one that happens on field assignment, and we know it's a packed field because of the path we are accessing it with. EDIT: no wait this makes no sense. Now I am confused by your comment.
No what I just said makes no sense. What happens is that this is a partial drop -- one field has been moved out () and then the logic for dropping the remaining fields seems to be wrong. So is relevant because it changed . And it looks like somehow the change is wrong; here is also despite the reference being unaligned.
should fix this.


Question: <ins> error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:13:5 | LL |     panic!(&1); |     ^^^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:6:15 | LL | const _: () = panic!(1); |               ^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:9:19 | LL | static _FOO: () = panic!(true); |                   ^^^^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors </ins>

The panic payload of the macro (as passed on to ) is generic, but the CTFE panic support assumes it will always be an . This leads to ICEs: Cc
I guess we could support this, but we'd have to find some way to render the errors. Maybe we need to wait for const traits so we can require const Debug?
Alternatively constck could require the argument to have type .
also requires a
Yeah, the libcore panic machinery does not support non-format-string panics.
Aye, left out the latter of my message. is likely the most common argument to , and it's not unusual with e.g. ; so I agree that waiting for const traits before supporting any other arguments is reasonable.
Im hitting this ICE on stable without feature flag:
Hm indeed, that is interesting: any idea why we go on here after seeing an error? Does this kind of behavior mean any part of CTFE is reachable on stable somehow?
yes. We're not gating CTFE on whether there were stability (or any other static checks) failing. I've been abusing this since 1.0 to demo things on the stable compiler and never got around to fixing it. I don't even know if we have a tracking issue for it.
:rofl: So what would be a possible approach here? Replace such consts by early enough that their MIR never actually gets evaluated? We might as well use this issue, IMO...
That would require us to mutate all MIR and potentially even HIR. Other possible solutions: poison the mir Body if const checks fail (by adding a field like or by just nuking the body by replacing it with ) and thus make allow const evaluation to check if the mir Body failed the checks and bail out before doing anything make the have an field similar to
On second thought, let's leave this issue for the ICE, and make a new one for "we can trigger nightly-only const code on stable because we don't abort compilation early enough":
Given that this ICE is pre-existing, as shown by , can we un-block ? I'd really like to see const_panic stabilized, and this seems like a minor issue to be blocking on.
That comment is an example of accidentally partially exposing an unstable feature on stable -- a separate bug tracked in I don't see how that's an argument for shipping that feature on stable when it is broken.


Question: <ins> error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:13:5 | LL |     panic!(&1); |     ^^^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:6:15 | LL | const _: () = panic!(1); |               ^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:9:19 | LL | static _FOO: () = panic!(true); |                   ^^^^^^^^^^^^ | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors </ins>

In particular, applies to all unstable const features. Fixing this bug here is not even that hard I think: somewhere around here there needs to be a check that the argument has type . Re: , AFAIK that one is also blocked on figuring out how the diagnostics should look like, and a further concern (though maybe not blocking) is .
I guess that might make this a non-issue, where it is proposed also would require as first argument.
For reference: , which was recently merged. The plan is to fix the behaviour of in the Rust 2021 edition. Given that this ICE is listed as a blocker for , does this mean that stabilizing that will have to wait for the next edition?
No, because breaking changes are allowed to be made to unstable features without moving to a new edition; that's kinda the whole idea. The 2021 edition will effectively just extend the same restriction to all invocations, const context or not.
I'd like to tackle this but I'm not very experienced with the CTFE code. I get that we need to check from the that we've matched on in this branch and we need to match on the enum, but: For the first question, I see and that we probably want to check that the type of the tuple and that there's variants of that are , but do we stop the iteration when we get one that is a type? Is the projection list always guaranteed to terminate in a variant of that has a ? And once we have an instance of , do we just check that there's any_ projection in the list that has a ?
you can use to get the type of the . Then you can test its to be .


Question: //! [rust-discord]: https://discord.gg/rust-lang //! [array]: prim@array //! [slice]: prim@slice // To run std tests without x.py without ending up with two copies of std, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no effect there.

All existing standard library documentation implicitly assumes that the APIs are being used between the start of a Rust and end of . For example  does not document any indication that the function would panic. It does not need to document that, because the function cannot panic, as long as the call occurs within the duration of . However it's possible to observe a panic like this: (Related PR and discussion: ) In general using the standard library from an callback, or before through a static constructor, is UB: according to "we can't really guarantee anything specific happens [...]; at least not in a cross-platform way." Is this worth calling out centrally as a caveat to all other documentation of the standard library? At the top level of the whole crate (it would perhaps be more prominent than it deserves), at the module level, or in the Reference? Certainly for , , , the expectation users need to have is that nothing in there will work outside of . Are there APIs it makes sense to carve out as being permissible outside of ? Stuff like , , , , etc. We'd maybe need to do research into how constructors and atexit are being used in the wild. For example the crate relies on , , and to be usable before : It seems obvious that those things should work but there isn't documentation which guarantees it. I assume that makes the crate technically unsound as written.
IMHO, core types should work in whatever context but libstd is more dicey. It more explicitly has a runtime or three (e.g. Rust's, libc's and the OS's). So at a minimum anything in the modules , , , , , , , etc should be regarded with suspicion unless documented otherwise. In summary, my thoughts are: is fine depends on the allocator used assumes code is running in main (except for the and possibly stuff)
Core types can still panic and panics do IO.
Hm... how much of an issue is that? Panics don't have to do I/O (e.g. if stderr is closed) so if platforms don't support that before or after main then it can be silently skipped, no?
But do we do that properly today? And it's not just IO but also panic hooks which in turn can rely on various other parts of std.
I think it would be fine to document that e.g.


Question: //! [rust-discord]: https://discord.gg/rust-lang //! [array]: prim@array //! [slice]: prim@slice // To run std tests without x.py without ending up with two copies of std, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no effect there.

after main they may want to set an empty (or aborting) panic hook if panicking is possible. I really don't want to be in a situation where the user is in a worse place than if they'd just used .
Could we turn panics into immediate aborts after main? That would also avoid the backtrace printing and symbolication.
I looked through the standard library, and is the only function that has limitation on usage before/after main (in this case, this is only a problem during TLS destruction). This function is also called from , and , which can therefore panic when called during TLS destruction. and might be able to be reworked to avoid this, but this is fundamentally a limitation of since it requires a reference to the current to work. The stack guard used by the stack overflow handler also accesses the same TLS slot as , but since the stack bounds don't have a this could be moved to a separate to properly support stack overflow handling during TLS destruction.
If we're going to make a statement at all then imo we should start out with something more cautious than making solid guarantees since this would be a pretty wide-ranging promise. before/after main behavior is not tested. It is best-effort and if someone relies on it they should have their own tests core and alloc are expected to work because they don't touch OS APIs or global state caveat: user code in any hookable API like panic handlers, global allocators, OOM handler or any future hooks. Especially panics affect a lot of code. we might replace hooks after main? most existing parts of std, backtrace and other things interacting with the OS are expected to work but there may be platform-specific edge-cases and the behavior may change in the future due to changing implementation details or new features that depend more runtime state (e.g. a std threadpool or async runtime) then finally a list of known limitations
Proposed documentation based on my previous comment:


Question: <ins> // Regression test: if we suggest replacing an `impl Trait` argument to an async // fn with a named type parameter in order to add bounds, the suggested function // signature should be well-formed. // // edition:2018 trait Foo { type Bar; fn bar(&self) -> Self::Bar; } async fn run(_: &(), foo: impl Foo) -> std::io::Result<()> { let bar = foo.bar(); assert_is_send(&bar); //~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely Ok(()) } // Test our handling of cases where there is a generic parameter list in the // source, but only synthetic generic parameters async fn run2< >(_: &(), foo: impl Foo) -> std::io::Result<()> { let bar = foo.bar(); assert_is_send(&bar); //~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely Ok(()) } fn assert_is_send<T: Send>(_: &T) {} fn main() {} </ins>

(Edit: Actually, being an inherent fn doesn't matter. It happens with top-level fns too.) This prints the diagnostic: The suggestion in the last line is not valid syntax (). It also emits malformed syntax if the first parameter is a or parameter. The diagnostic becomes well-formed if any of the following is done: The first parameter is changed to instead ofThe fn is not an async fn. In either case, the diagnostic correctly says: Happens on both nightly: ... and stable:
This should hopefully be a fairly straightforward patch to the diagnostics code that generates the suggestion.


Question: } fn check_overalign_requests<T: Alloc>(mut allocator: T) { <del> let size = 8; let align = 16; // greater than size let iterations = 100; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </del> <ins> for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align/2, align-1] { // size less than alignment let iterations = 128; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </ins> <del> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) </del> <ins> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) } } </ins> } } }

The man page for says And yet Miri found libstd calling this function with an alignment of 4 on a 64bit-platform. This happens when size=2, align=4. The fact that size<align makes it enter the code path for .
The only reason I can imagine for to exist there is a buggy implementation of . This check is only meaningful if a buggy implementation returns not an allocation suitably aligned for any built-in type (on x86_4 – 16-bytes) but rather an allocation aligned for the particular request?
A lack of comment is disturbing here. If git history does not reveal any such issue, then we should just remove that check entirely.
That extra check was introduced by to fix
I have opened in jemalloc to get clarification from them about their alignment guarantees. It would be nice if someone with more knowledge could chime in, in particular knowledge about where exactly that value of 16 for on x86-64 comes from. Cc
Possibly from here:
C has types with an alignment smaller than are supported in all contexts. AFAICT this includes the memory returned by any memory allocation function - not only , but also . The largest scalar type of C implementations needs to be supported in all contexts. On most platforms, this type is often which the requires it to have an alignment of 16, so on these particular platforms, will have an alignment requirement of 16 bytes. On these platforms, all memory allocation functions need to return memory aligned to a 16 byte boundary when called with a to be able to support the largest scalar type provided by the C implementation. Otherwise would return memory not suitable for storing a scalar type. However, if the memory allocation is smaller than the size of the largest scalar type, then it would be illegal to store it there, so the memory returned needs to only be properly aligned to be able to store the largest scalar type that would fit in that particular size. In practice, this means that for sizes up to , the alignment of the returned memory equals the size of the allocation rounded to the previous power of two (e.g. in a 5 byte allocation, you can at most fit a 32-bit scalar, so the allocation only needs 4 byte of alignment). And for sizes larger than , the alignment is at least (this allows storing, e.g., an array of s).


Question: } fn check_overalign_requests<T: Alloc>(mut allocator: T) { <del> let size = 8; let align = 16; // greater than size let iterations = 100; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </del> <ins> for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align/2, align-1] { // size less than alignment let iterations = 128; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </ins> <del> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) </del> <ins> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) } } </ins> } } }

In practice, the fastest thing you can do, is calling malloc if , because if malloc will return an alignment of at least rounded to the previous power of two, which is always satisfied (remember that must be a power of two, so if its smaller than size, it is at least the previous one). will do this without having to branch on any user provided alignment argument. That's precisely what that code is doing. The else branch is calling a "generic" which should be able to handle any user-specified alignment. The implementation of based on : appears to have the bug you mention, and should probably call or similar. I suspect that the implementation of provided by jemalloc, which we use here: doesn't have this issue, because it probably just forwards the call to , which supports alignment smaller than .
So basically on the C side, one assumes that is not used with types that use the C equivalent of ? With that assumption, I agree it is enough for to guarantee an alignment of rounded down to the next power of two. (I think your post originally said "up", but now it says "down" so I guess we agree.) That's what I and our implementation indeed handles that case just fine. The bug in the way we call is fixed by Still, it would be nice not to be able to reason about "in practice", but get some commitment from jemalloc -- see And finally, this only concerns on Unixes. Does anyone know what the situation looks like with on Windows? libstd currently assumes even small allocations to be aligned there, and agrees with that (Ctrl-F "on 64-bit platforms").
EDIT: C11 to C, but yes, malloc doesn't know anything about the alignment of a type. It still can be used, but the user needs to check whether the allocation is properly aligned. The docs are quite clear IMO: Anything more concrete than that will be target specific, and those details are outside jemalloc's control - if jemalloc wants to replace the system allocator in a target, it needs to comply with the ABI there. If it were to guarantee more, e.g., all allocations are 16byte aligned, it wouldn't work on platforms using the SysV i386 ABI.
Well, with that statement from the jemalloc docs is wrong, isn't it?


Question: } fn check_overalign_requests<T: Alloc>(mut allocator: T) { <del> let size = 8; let align = 16; // greater than size let iterations = 100; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </del> <ins> for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align/2, align-1] { // size less than alignment let iterations = 128; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </ins> <del> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) </del> <ins> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) } } </ins> } } }

And for users to manually do the alignment, getting something more concrete would be useful. And also for Rust! Currently you are deducing a whole lot of things from a few words in the spec. I have zero confidence that this is the only way to read the spec. So something like: "for we guarantee an alignment of ; for smaller sizes we guarantee an alignment of the size rounded down to the next power of two." would IMO be prudent to ask from the jemalloc devs. Or else we'll find ourselves with more bugs when someone interprets all this slightly differently.
I don't know how useful would that be: malloc only needs to comply with the C standard. Parts of it are implementation-defined, and what those are defined to is often specified by the system ABI. That's the only thing the global allocator can rely on. On most platforms, the system allocator - which is the default global allocator for Rust programs - is not jemalloc - it is the one from glibc, musl, microsoft, apple, google, mozilla, etc. In some platforms, like FreeBSD, the system allocator is jemalloc, but even there we can't exploit that knowledge because users can just and now the global allocator is a different one. That's an use case we support. So even if jemalloc were to offer extra guarantees here, Rust's system allocator cannot make use of them. The only places were we can can exploit jemalloc's specific guarantees, is when using crates like jemallocator, to explicitly hardcode the allocator to a particular one. As in, if that allocator is not linked, you get a linker error or similar. But even there, it makes sense to stick to what C and the platform ABI guarantees, because jemalloc is free to break anything else in the next version.
Well it would save us this entire discussion. If that doesn't demonstrate its usefulness I don't know what does.^^ I don't know what the "system allocator" is for Linux, but the one in glibc actually guarantees a 16-byte alignment on 64bit systems for all allocations. So by that standard jemalloc would just be incorrect.
The platform ABI guarantees that. What the malloc implementations guarantee is irrelevant.


Question: } fn check_overalign_requests<T: Alloc>(mut allocator: T) { <del> let size = 8; let align = 16; // greater than size let iterations = 100; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </del> <ins> for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align/2, align-1] { // size less than alignment let iterations = 128; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </ins> <del> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) </del> <ins> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) } } </ins> } } }

If glibc were to guarantee that all addresses are 32-byte aligned, there is no way in which we could exploit that information in the implementation of the system allocator, because the platform only requires 16-byte alignment, and it is valid to pick any allocator at run-time that satisfies that.
So there a document somewhere saying "for x86-64 bit, 16-byte alignment is guaranteed"? But that document contains an exception for small sizes, making s behavior legal?
Yes, there are documents containing the rules of what's legal, at least for Linux x8664. Those document allow an exception for small sizes. One API that uses those is , which requires the alignment to be at least , which is 8 on x86_64, and which allows you to allocate bytes, with a smaller alignment. I still have no idea what jemalloc has to do with any of this - your original question is about , and that has nothing to do with jemalloc. But yes, jemalloc exploits this behavior, to be able to satisfy 1 byte request, and return addresses that are 1 byte aligned. Otherwise each 1 byte request would consume 16 bytes of memory within a memory page.
A document that could be relevant is the C standard. Unfortunately, as mentioned in the commit message for , it is rather tautological on this topic: The standard does not give any numeric value. Like many other aspects of C, it looks like the actual value of is implementation-defined.
When using jemalloc, becomes jemalloc. That's how happened. Do you have a reference for something that concretely calls out an exception for small types? The C standard only does this very indirectly, as you showed.
That was a bug in our implementation of system that applies to pretty much all allocators, not only jemalloc. says (emphasis mine): Since the alignment of an object is a power of two that is always smaller than or equal to the object size, rounding down the alignment of an allocation to the previous power of two always produces an allocation properly aligned for every type that can fit it. That holds for all allocations, so there is no exception for that. That's the rule. Since that would mean that large allocations must be unreasonably aligned, the standard does provide an exception for allocations of size larger than than .


Question: } fn check_overalign_requests<T: Alloc>(mut allocator: T) { <del> let size = 8; let align = 16; // greater than size let iterations = 100; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </del> <ins> for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align/2, align-1] { // size less than alignment let iterations = 128; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </ins> <del> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) </del> <ins> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) } } </ins> } } }

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


Question: } fn check_overalign_requests<T: Alloc>(mut allocator: T) { <del> let size = 8; let align = 16; // greater than size let iterations = 100; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </del> <ins> for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align/2, align-1] { // size less than alignment let iterations = 128; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, "Got a pointer less aligned than requested") } </ins> <del> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) </del> <ins> // Clean up for &ptr in &pointers { allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) } } </ins> } } }

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


Question: }, x => { <del> bug!("unexpected sort of node in type_of_def_id(): {:?}", x); </del> <ins> bug!("unexpected sort of node in type_of(): {:?}", x); </ins> } } }

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --%5D%0D%0Apub%20trait%20IceIce%3CT%3E%0D%0Awhere%0D%0A%20%20%20%20for%3C'a%3E%20T%3A%20'a%2C%0D%0A%7B%0D%0A%20%20%20%20type%20Ice%3C'v%3E%3A%20IntoIterator%3CItem%20%3D%20%26'v%20T%3E%3B%0D%0A%7D%0D%0A%0D%0Afn%20main()%20%7B%7D%0D%0A) <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --The ICE happens on , and : : <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Maybe related to
Bisection: bash cargo bisect-rustc --regress ice --test-dir=foo `
Looks like
ICE happens on stable and also even without the line so no requires-nightly. label regression-from-stable-to-stable, A-traits
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-low


Question: RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin SRC=. os: osx <ins> before_script: &osx_before_script > ulimit -c unlimited </ins> install: &osx_install_sccache > curl -L https://api.pub.build.mozilla.org/tooltool/sha512/d0025b286468cc5ada83b23d3fafbc936b9f190eaa7d4a981715b18e8e3bf720a7bcee7bfe758cfdeb8268857f6098fd52dcdd8818232692a30ce91039936596 | tar xJf - -C /usr/local/bin --strip-components=1 <ins> after_failure: &osx_after_failure > echo 'bt all' > cmds; for file in $(ls /cores); do echo core file $file; lldb -c $file `which ld` -b -s cmds; done </ins> - env: > RUST_CHECK_TARGET=check RUST_CONFIGURE_ARGS=--build=i686-apple-darwin SRC=. os: osx <ins> before_script: *osx_before_script </ins> install: *osx_install_sccache <ins> after_failure: *osx_after_failure </ins> - env: > RUST_CHECK_TARGET=check RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin --disable-rustbuild SRC=. os: osx <ins> before_script: *osx_before_script </ins> install: *osx_install_sccache <ins> after_failure: *osx_after_failure </ins> - env: > RUST_CHECK_TARGET= RUST_CONFIGURE_ARGS=--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios SRC=. os: osx <ins> before_script: *osx_before_script </ins> install: *osx_install_sccache <ins> after_failure: *osx_after_failure </ins> env: global:

I've seen this quite a lot recently Example logs: Example Travis runs: https://travis- https://travis- https://travis- https://travis- I'm opening a tracking issue so we can collect some more logs and hopefully draw conclusions from them at some point. Until then I'm not really sure how we'd deal with this...
Is there a way to collect the coredump from the segfault so we could attempt to track down the reason behind the segfault? Perhaps we could at least pass to clang so we could try to reproduce locally?
your guess is as good as mine!
If you set , the core dump will end up in .
https://travis- is the first job where we got a stack trace: I wouldn't necessarily call that... illuminating
I wonder if there would be a way to print what the files we're linking are? Maybe that would help since maybe the linker segfaults on an improperly formatted file or something like that; knowing what the files are (names and lengths) may help. I think passing to clang would be good enough, at least as a start.
PRs are always welcome! I don't have any magical tricks up my sleeves to implement tricks like that unfortunately.
Next successful stack trace: https://travis-
another failure of this kind https://travis-
These look like assertion failures: Now the question is how we recover the assert message. Any Mac person knows of a way?
good thinking, I totally missed that before! Looks to be: (that's a disassembly of the executable on my system, which looks to be the same). I believe and sure enough there's in the source
Well the pthreads explains why it's nondeterministic at least...
Random attempt to help this:
Looks like did the trick, we haven't seen this in ~2 weeks, so closing.