Question: } } } <ins> fn expr_as_call_operand( &mut self, mut block: BasicBlock, scope: Option<region::Scope>, expr: Expr<'tcx>, ) -> BlockAnd<Operand<'tcx>> { debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { this.as_call_operand(block, scope, value) }); } let tcx = this.hir.tcx(); if tcx.features().unsized_locals { let ty = expr.ty; let span = expr.span; let param_env = this.hir.param_env; if !ty.is_sized(tcx.at(span), param_env) { // !sized means !copy, so this is an unsized move assert!(!ty.is_copy_modulo_regions(tcx, param_env, span)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. if let ExprKind::Deref { ref arg } = expr.kind { let arg = this.hir.mirror(arg.clone()); // Generate let tmp0 = arg0 let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); // Return the operand *tmp0 to be used as the call argument let place = Place { local: operand, projection: tcx.intern_place_elems(&[PlaceElem::Deref]), }; return block.and(Operand::Move(place)); } } } this.expr_as_operand(block, scope, expr) } </ins> }

To be clear, I wasn't proposing changing anything apart from MIR building either, I don't think. IIUC, what you proposed is that would be compiled to: whereas under my proposal (limited to apply to unsized parameters, instead of moved parameters) would yield: I think I mis-stated the problem earlier. It's not so much that your proposal will introduce compilation errors, it's that I think it changes the semantics of code like this in what I see as a surprising way: I believe that this code would compile to the following under your proposal: which means that would be invoked with the new value of , right? Under my proposal, the code would still compile, but it would behave in what I see as the expected fashion. Specifically, it would generate:
Isn't there a way to "lock" that value through the borrow-checker, so further accesses would be disallowed, until the call returns? I'd rather be stricter here. <hr/My point was that if your proposal affects sized moves, you're breaking stable reinitialization. If it doesn't affect sized moves, I don't see how this applies anymore:
Let me just chime in here and say that this is a pain in Miri. Unsized locals are pretty different from sized locals, I had to introduce a bunch of special hacks to make them work. MIR locals even needed a new state just for them: Lazily allocating locals seems odd to me, but at least we can consistently do that for all locals. Elsewhere however to make this lazy initialization actually work out and catch mistakes where an unsized local is "overwritten" with a value of different size: This all feels really unprincipled, and it would be great if at some point we could come up with a coherent semantics for unsized locals in MIR. The worst part is that the size of a local is implicitly determined on the first write to it. It would be much better to be explicit about that, e.g. at time.
I don't think we have anything like this today, but presumably we could add such a thing, but I'm not quite sure what you have in mind. When does this prohibition on further accesses take effect?


Question: } } } <ins> fn expr_as_call_operand( &mut self, mut block: BasicBlock, scope: Option<region::Scope>, expr: Expr<'tcx>, ) -> BlockAnd<Operand<'tcx>> { debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { this.as_call_operand(block, scope, value) }); } let tcx = this.hir.tcx(); if tcx.features().unsized_locals { let ty = expr.ty; let span = expr.span; let param_env = this.hir.param_env; if !ty.is_sized(tcx.at(span), param_env) { // !sized means !copy, so this is an unsized move assert!(!ty.is_copy_modulo_regions(tcx, param_env, span)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. if let ExprKind::Deref { ref arg } = expr.kind { let arg = this.hir.mirror(arg.clone()); // Generate let tmp0 = arg0 let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); // Return the operand *tmp0 to be used as the call argument let place = Place { local: operand, projection: tcx.intern_place_elems(&[PlaceElem::Deref]), }; return block.and(Operand::Move(place)); } } } this.expr_as_operand(block, scope, expr) } </ins> }

In particular, the IR for under your proposal, if I understood, would be But the access to that (I believe) we wish to prevent takes place in the "evaluate remaining arguments" part of things. So I think we'd have to add some sort of "pseudo-move" that tells borrowck that should not be assignable from that point forward, right? Well, it depends on your perspective. It's true that, given the need to permit reinitialization, the check is now specific to unsized values -- i.e., MIR construction will be different depending on whether we know the type to be sized or not. That's unfortunate. However, I think we still maintain a degree of congruence, from an end-user perspective. In particular, users could not have reinitialized a anyhow. However, under my proposal, users can write things like and the code works as expected (versus either having an unexpected result or getting an error). In any case, it seems like we're sort of "narrowing in" on a proposal here: when we see a function call with a parameter that is , and the value being passed is a deref, we want to modify the IR to not introduce a temporary and instead pass that parameter directly from its location, either we do some sort of "no more assignments" lock, or we move the pointer and introduce a temporary (and then pass in a deref of that temporary) Does that sound right so far?
If it's easier to do the more flexible approach (by moving the pointer) than the "locking" approach (which is a bit like borrowing the pointer until all arguments are evaluated, then releasing the borrow and doing a move instead), I don't mind it, I was only arguing with the "uniformity" aspect. Something important here: your approach is stabilizable, while mine is meant more for that one in the standard library, and not much else.
Yes, I was kind of shooting for something that we could conceivably stabilize.
Removing nomination, this was already discussed in triage meeting and it's under control.
So should we maybe try out the approach I proposed and see how well it works?
yes, going to try that out.
For the record, the "new plan" is this.


Question: } } } <ins> fn expr_as_call_operand( &mut self, mut block: BasicBlock, scope: Option<region::Scope>, expr: Expr<'tcx>, ) -> BlockAnd<Operand<'tcx>> { debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { this.as_call_operand(block, scope, value) }); } let tcx = this.hir.tcx(); if tcx.features().unsized_locals { let ty = expr.ty; let span = expr.span; let param_env = this.hir.param_env; if !ty.is_sized(tcx.at(span), param_env) { // !sized means !copy, so this is an unsized move assert!(!ty.is_copy_modulo_regions(tcx, param_env, span)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. if let ExprKind::Deref { ref arg } = expr.kind { let arg = this.hir.mirror(arg.clone()); // Generate let tmp0 = arg0 let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); // Return the operand *tmp0 to be used as the call argument let place = Place { local: operand, projection: tcx.intern_place_elems(&[PlaceElem::Deref]), }; return block.and(Operand::Move(place)); } } } this.expr_as_operand(block, scope, expr) } </ins> }

When generating the arguments to a call, we ordinarily will make a temporary containing the value of each argument: But we will modify this such that, for arguments that meet the following conditions: The argument is moved (not copied), and its type is not known to be , and the "place" has outer derefs (e.g., we are passing P where P is some place), then we assign the place P (instead of ) to a temporary and we make the argument to the function be (instead of ). This means that given where , we used to generate but now we generate We are now moving the box itself, which is slightly different than the semantics for values known to be sized. In particular, it does not permit of the box after having moved its contents. But that is not supported for unsized types anyway. The change does permit modifications to the callee during argument evaluation and they will work in an analogous way to how they would work with sized values. So given something like: we will find that we (a) save the old value of to a temporary and then (b) overwrite while evaluating the arguments and then (c) invoke the with the old value of .
Update: There is also
is a perfectly normal operand, I don't know what you mean. It's the same kind of as we currently have in (on the RHS)
Oh sorry, somehow I thought operands could only refer directly to locals, not also dereference them. I think I am beginning to see the pieces here -- together with function argument handling, this entirely avoids having to dynamically determine the size of a local. I have to agree that is quite elegant, even though baking "pass-by-reference" into MIR semantics still seems like a heavy hammer to me. On the other hand this places a severe restriction on now unsized locals may be used, basically taking back large parts of Is there some long-term plan to bring that back (probably requires with dynamic alignment in LLVM)? Or should we amend the RFC or at least the tracking issue with the extra restrictions?
I would keep the more general feature but use two different feature-gates (if we can). And just like with a few other feature-gates () we could warn that (the general one) is incomplete and could lead to misaligned variables (or something along those lines).


Question: } } } <ins> fn expr_as_call_operand( &mut self, mut block: BasicBlock, scope: Option<region::Scope>, expr: Expr<'tcx>, ) -> BlockAnd<Operand<'tcx>> { debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { this.as_call_operand(block, scope, value) }); } let tcx = this.hir.tcx(); if tcx.features().unsized_locals { let ty = expr.ty; let span = expr.span; let param_env = this.hir.param_env; if !ty.is_sized(tcx.at(span), param_env) { // !sized means !copy, so this is an unsized move assert!(!ty.is_copy_modulo_regions(tcx, param_env, span)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. if let ExprKind::Deref { ref arg } = expr.kind { let arg = this.hir.mirror(arg.clone()); // Generate let tmp0 = arg0 let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); // Return the operand *tmp0 to be used as the call argument let place = Place { local: operand, projection: tcx.intern_place_elems(&[PlaceElem::Deref]), }; return block.and(Operand::Move(place)); } } } this.expr_as_operand(block, scope, expr) } </ins> }

We could also add runtime asserts that the (dynamic) alignment is respected, once we know could never trigger them (e.g. from stable code).
I was wondering about that too. It seems like it'd be good to review the more general feature in any case. This is partly why I brought up the idea of wanting a guaranteed "no alloca" path -- this was something I remember us discussing long ago, and so in some sense I feel like the work we're doing here isn't just working around LLVM's lack of dynamic alignment support (though it is doing that, too) but also working to complete the feature as originally envisioned.
I two notes to the tracking issue so we don't overlook this in the future.
This is probably expected, but the fix failed to actually make sound:


Question: let pat = self.mk_pat(lo.to(self.prev_span), pat); let pat = self.maybe_recover_from_bad_qpath(pat, true)?; <ins> let pat = self.recover_intersection_pat(pat)?; </ins> if !allow_range_pat { self.ban_pat_range_if_ambiguous(&pat)?

The compiler could suggest that identifier must precede the pattern in the following code: playpen link: Current error message: It could be improved as:
modify labels: A-diagnostics C-feature-request T-compiler
So what happens after is that we've parsed a and then follows which is not a valid token after a parsed . To fix this we can, after having parsed in , check if follows and then emit appropriate suggestions. We will need to use some heuristics to figure out what the user wants based on the structure of . Some of the suggestions would be and some not. cc


Question: <ins> fn main() {} #[cfg(FALSE)] fn container() { const unsafe WhereIsFerris Now() {} //~^ ERROR expected one of `extern` or `fn` } </ins>

The following program compiles, and prints :
As pointed out by on discord , this also works on stable:
Regression introduced in 1.40.0, specifically this line:
I have a fix in


Question: use fn_ctxt::FnCtxt; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; <del> use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed}; </del> <ins> use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; </ins> use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor;

I wrote code that looked like this while not having my brain turned on 100%. Due to said brain not functioning, it took me a while to understand what rustc was trying to tell me with the message pointing to the pattern with the text . sure looked like a unit variant to me! What rustc was trying to tell me was that the definition of the variant was a struct variant ("found struct variant") and my pattern wasn't matching the definition ("this pattern you specified looks like it's trying to match a variant that is not a unit struct, unit variant or constant"). The change I needed to make was adding to my pattern, because I was trying to distinguish different variants from each other, not use pieces within the variants. Suggesting seems like a decent starting point to me, but there could definitely be cases I'm not considering here and I'm totally open to hearing that No response No response <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
WEIRD this PR looks like it implements what I wish rustc did: but the test files in that PR say they're for and I'm getting
Aha ok this test shows that for tuple variants, rustc will suggest adding : and that test also shows that rustc isn't suggesting anything for struct variants!
Aha and it looks like adding struct fields was more complex so that's why it wasn't done?
claim


Question: <del> //@ known-bug: #97501 #![feature(core_intrinsics)] use std::intrinsics::wrapping_add; #[derive(Clone, Copy)] struct WrapInt8 { value: u8 } impl std::ops::Add for WrapInt8 { type Output = WrapInt8; fn add(self, other: WrapInt8) -> WrapInt8 { wrapping_add(self, other) } } fn main() { let p = WrapInt8 { value: 123 }; let q = WrapInt8 { value: 234 }; println!("{}", (p + q).value); } </del>

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</detailsAdding an suffix fixes the issue: The error first appears with the toolchain. It works fine with .
The offset intrinsic does not support doing this, it requires isize or usize. ICEs using intrinsics wrongly are expected and not a bug. Thanks for the report anyways.
Shouldn't a occur for the argument?
There is nothing to be coerced to, since the intrinsics accept any type on the type level.
Is this specific to the intrinsic? I tried a couple of other intrinsics, and the compiler complained about mismatched types: : : Doing the same for results in an ICE, e.g.:
the intrinsic is generic, that's why it passes type checking
It's only generic in the first parameter. And has the exact same signature, but the issue doesn't occur for it.
Hi what is the motivation to keep this check as an ICE instead of a user friendly error since the error arises from misusage of the API?
Giving better errors for intrinsics and other internal-only features increases maintenance burden, so decided to not support it. Invalid usage of intrinsics may lead to ICEs (since intrinsics should not be used - I see for your case here it makes sense to use them in the tests, but I think you can live with ICEs). I guess it's not ideal that the ICE message says to report it - but fixing that is hard.


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

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: Ok(()) } <del> pub fn remove_dir_all(p: &Path) -> io::Result<()> { </del> <ins> fn remove_dir_all_modern(p: &Path) -> io::Result<()> { </ins> // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks.

The fix for CVE-2022- (, ) appears to have introduced a regression that can cause file system corruption on some UNIX systems. The new code will attempt to use in any case where it does not know what type of file a directory entry represents. Some systems do not provide that information along with the entry names returned while reading a directory, and even on systems which provide a type hint, that hint may be . In cases where we do not know the type of the entry, the code tries first to unlink it as if it were something other than a directory: The code assumes that on a directory will fail with , or on Linux with the non-standard , but this is not always the case. POSIX does suggests as a failure in some, but not all cases: (See in The Open Group Base Specifications Issue 7, 2018 edition) Implementations are not required to prohibit on directories, and indeed UFS file systems on present day illumos and presumably at least some Solaris systems allow of a directory if the user has sufficient privileges. Other platforms may as well. Unfortunately unlinking a directory on UFS causes a sort of file system corruption that requires an unmount and a trip through to correct. Any code that uses on UFS has since started causing that kind of corruption, which took a bit of work to track down. I think the fix is probably relatively simple, and has the benefit of not touching the code path where we believe we know what sort of entry we are removing: In short, we should try to first, rather than first, as that always fails in a safe way that we can detect. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
cc (as you're the one how wrote the new code)
Thanks for the ping claim
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-critical
Was this issue reported upstream? Filesystems corrupting themselves seem like a poor failure mode in any case, and in some ways is a violation of the sandboxing that the kernel ought to provide for the user-space applications.


Question: Ok(()) } <del> pub fn remove_dir_all(p: &Path) -> io::Result<()> { </del> <ins> fn remove_dir_all_modern(p: &Path) -> io::Result<()> { </ins> // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks.

It was reported upstream, and we're working on a fix -- but that fix will obviously only be in new versions of the operating system. To expand further on the corruption: the file system becomes inconsistent and requires repair, and the damage such as it is can only be caused by privileged users; i.e., by root or a user with root equivalent privileges. I am not yet aware of a way that it would cause actual data loss, just an interruption to service, but anything is possible. Allowing the linking and unlinking of directories is a regrettable, but seemingly intentional feature we are saddled with through our UNIX heritage. I'm working to disable and eventually remove the feature in the OS -- although we strongly value backwards compatibility, in this case I can't really see a legitimate use case or find a consumer that would be broken by doing so, but we won't know for sure until we try. While this specific case is unfortunate, and we can and will work on our end to try to mitigate the impact, the fact remains that POSIX explicitly documents and allows for implementations where on a directory does not return . For the code to be completely correct on all POSIX systems, it cannot make that assumption. In addition, working around the issue in new versions of the OS doesn't fix existing deployments out there already. Enterprise customers are often reluctant to promptly update their operating system, even though they may update software built and deployed on it -- software that may be written in Rust. I myself hit this issue by upgrading only the Rust compiler to a new stable version, and trying to build and use Rust-based software we have to build UFS ramdisks on illumos. We aim to fix the OS for the future, but the critical regression in Rust needs to be fixed as well for the present. We appreciate everybody who has looked at this so far -- please let me know how I can help expedite the process!
Thanks again for the report. The linked PR should fix the issue. Apparently only and guarantee that trying to a directory fails. , and allow it, at least in theory. After looking around a bit I found that it is even explicitly documented for and . So it is not a bug but a feature there... After changing that in you might want to adapt the man page as well.


Question: Ok(()) } <del> pub fn remove_dir_all(p: &Path) -> io::Result<()> { </del> <ins> fn remove_dir_all_modern(p: &Path) -> io::Result<()> { </ins> // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks.

We can try to avoid this case by default, as is switching to try unknown as a directory first, but you should note that this is still going to be racy. If there's an unprivileged adversary like the CVE supposes, then they can try to race changes between "try (and fail) as a directory" to "unlink as a file", to make it unlink a directory after all and induce corruption. IOW, it sounds like it's not safe for a privileged process to unlink paths at all if they may be changed by lesser privileges .
It should not really cause corruption according to the , just orphaned directories: Of course this can lead to resource exhaustion since the disk space and the inodes cannot be reclaimed until the next .
And that user is only root or otherwise root-like? i.e. it's not just talking about regular access privileges?
For Illumos the process must have root privileges or needs to be in the process privilege set (). Solaris has at some point abolished this privilege and apparently does not allow unlinking directories anymore ().


Question: <ins> // edition:2021 fn main() { &[1, 2, 3][1:2]; //~^ ERROR: expected one of //~| HELP: you might have meant a range expression } </ins>

Having written Python for several hours, I made this mistake and couldn't realize what was wrong for a while. No response claim <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I'm not sure whether it's worth to fix this right now. will significantly change this code, basically requiring a rewrite of this diagnostic.
Agreed, it's reasonable to wait for type ascription removal. Thanks for the info!
Now we should fix this error message: is not OK, we'd better suggest to use . I think you need to add proper logic for this part of code:


Question: #[stable] pub trait Any: 'static { /// Get the `TypeId` of `self` <del> #[stable] </del> <ins> #[experimental = "this method will likely be replaced by an associated static"] </ins> fn get_type_id(&self) -> TypeId; }

The Any trait is not in release condition at all, considering that is still uses slow virtual calls that could be replaced with an associated static in the near future but stabilizing with would mean that it could not be removed. Normally, this isn't an issue, but since Any is almost exclusively used through trait objects this blocks possible optimizations to layout that could allow to be represented as instead of containing a full vtable.
It would need to be , where the is the destructor (btw).


Question: let x = self.parse_seq_to_before_end( &token::Gt, SeqSep::trailing_allowed(token::Comma), <del> |p| p.parse_generic_arg(None), </del> <ins> |p| match p.parse_generic_arg(None)? { Some(arg) => Ok(arg), // If we didn't eat a generic arg, then we should error. None => p.unexpected_any(), }, </ins> ); match x { Ok((_, _, Recovered::No)) => {

<!-- 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. --I tried this code: on stable 1.78.0, this checks in 0.02 seconds. on beta 1.79.0-beta.3, this hangs somewhere in , I killed it after 5 minutes of no progress.
cc
Sharing the stack would be useful
:thinking: that doesn't really seem to be it
You need to switch to like thread 2 or 3 if you're doing this in gdb
it's not particularly deep, but it looks downstream of so I guess this must be it
Minimal:


Question: let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, hir_id, <del> span_of_attrs(&item.attrs), </del> <ins> span_of_attrs(&item.attrs).unwrap_or(item.source.span()), </ins> "Documentation test in private item"); diag.emit(); } } /// Returns a span encompassing all the given attributes. <del> crate fn span_of_attrs(attrs: &clean::Attributes) -> Span { </del> <ins> crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> { </ins> if attrs.doc_strings.is_empty() { <del> return DUMMY_SP; </del> <ins> return None; </ins> } let start = attrs.doc_strings[0].span(); <ins> if start == DUMMY_SP { return None; } </ins> let end = attrs.doc_strings.last().expect("No doc strings provided").span(); <del> start.to(end) </del> <ins> Some(start.to(end)) </ins> } /// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.

crashes on nightly () and also on stable () with "nightly" features turned on via . It does not trigger on stable without flag. Here is the output I'm getting: I created a small repro case + here: (it only happens when there is a certain combination of procedural macros, so I cannot make it a single file).
The source code is: with crate being a procedural macro crate with:
Couple of things that are important here: only happens with two procedural macros. macro has to do that . attribute has to be , does not reproduce with anything else.
Just a heads-up: AFAIK if a bug only occurs on stable with (I understand that it is not the case here), then it should probably be disregarded, because isn't supposed to be used when not bootstrapping the compiler.
The bug itself reminds me of
it happens on nightly as well. That detail was included to give context that evidently the ICE has been present for longer than 12 weeks, I believe.
With the following patch in the linked repo, the output is not ideal, but preferable to the ICE: I'll take a look to see if we can somehow keep the span for the entire attr doc, or at worst pointing at the correct macro.
Changing the patch to be gives us which makes more sense but is missing a primary span. Edit: I see no way to recover the original span after its has been modified. I guess we already rely on proc macro writers to be nice when it comes to spans, so this is acceptable as well.


Question: .collect(), _ => Vec::new(), }; <del> candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id)); </del> return Err(IllegalSizedBound(candidates, needs_mut, span)); }

<!-- 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. If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. --Given the following code: <!-- Please provide a link to --The current output is: <!-- The following is not always necessary. --Ideally the output should suggest -ing the out-of-scope trait, similar to E0599: <!-- If the problem is not self-explanatory, please provide a rationale for the change. --Someone tried to do dynamic dispatch between two underlying used a boxed trait object (with the type spelled , so wasn't in scope) and call the method on the boxed reader, and it was unclear from the error why the method wasn't accessible: <!-- If dramatically different output is caused by small changes, consider also adding them here. 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 output might also be different depending on the Edition. --This is reproducible on nightly (rustc 1.67.0-nightly ( 2022-12-01)).
Note: A sign there may be a problem worth fixing here is the code I wrote is a near copypaste of a top stack overflow answer for a :)
So, after some investigating, this appears to be a regression of , which essentially the same suggestion I proposed here: adding a for the trait object's trait. When generating the error when the lookup fails, the trait is initially included in the list of candidates, but it's filtered out by this (because the callee is the trait method, and so the parent of the callee is the trait, which is the candidate): This was introduced in by which also removed the corresponding suggestion from the test's expected output. It's not immediately clear to me from the PR () why this change was necessary. If the call is removed, the only UI test that fails is the one. Reverting that change would fix this issue, but I'm not sure if there are other cases I'm missing.


Question: .collect(), _ => Vec::new(), }; <del> candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id)); </del> return Err(IllegalSizedBound(candidates, needs_mut, span)); }

(cc with whom I was discussing this on Mastodon)
Haven't look at this yet, maybe I misinterpreted what was achieving, and that commit just needs a revert -- can't recall why I did that.
Yeah, lol, I totally overlooked that the would be load-bearing due to the way we treat trait methods on as inherent. I'll revert , modify the test, etc.


Question: <ins> // check-pass #![feature(c_variadic)] #![warn(function_item_references)] use std::fmt::Pointer; use std::fmt::Formatter; fn nop() { } fn foo() -> u32 { 42 } fn bar(x: u32) -> u32 { x } fn baz(x: u32, y: u32) -> u32 { x + y } unsafe fn unsafe_fn() { } extern "C" fn c_fn() { } unsafe extern "C" fn unsafe_c_fn() { } unsafe extern fn variadic(_x: u32, _args: ...) { } //function references passed to these functions should never lint fn call_fn(f: &dyn Fn(u32) -> u32, x: u32) { f(x); } fn parameterized_call_fn<F: Fn(u32) -> u32>(f: &F, x: u32) { f(x); } //function references passed to these functions should lint fn print_ptr<F: Pointer>(f: F) { println!("{:p}", f); } fn bound_by_ptr_trait<F: Pointer>(_f: F) { } fn bound_by_ptr_trait_tuple<F: Pointer, G: Pointer>(_t: (F, G)) { } fn implicit_ptr_trait<F>(f: &F) { println!("{:p}", f); } //case found in tinyvec that triggered a compiler error in an earlier version of the lint checker trait HasItem { type Item; fn assoc_item(&self) -> Self::Item; } fn _format_assoc_item<T: HasItem>(data: T, f: &mut Formatter) -> std::fmt::Result where T::Item: Pointer { //when the arg type bound by `Pointer` is an associated type, we shouldn't attempt to normalize Pointer::fmt(&data.assoc_item(), f) } //simple test to make sure that calls to `Pointer::fmt` aren't double counted fn _call_pointer_fmt(f: &mut Formatter) -> std::fmt::Result { let zst_ref = &foo; Pointer::fmt(&zst_ref, f) //~^ WARNING taking a reference to a function item does not give a function pointer } fn main() { //`let` bindings with function references shouldn't lint let _ = &foo; let _ = &mut foo; let zst_ref = &foo; let fn_item = foo; let indirect_ref = &fn_item; let _mut_zst_ref = &mut foo; let mut mut_fn_item = foo; let _mut_indirect_ref = &mut mut_fn_item; let cast_zst_ptr = &foo as *const _; let coerced_zst_ptr: *const _ = &foo; let _mut_cast_zst_ptr = &mut foo as *mut _; let _mut_coerced_zst_ptr: *mut _ = &mut foo; let _cast_zst_ref = &foo as &dyn Fn() -> u32; let _coerced_zst_ref: &dyn Fn() -> u32 = &foo; let _mut_cast_zst_ref = &mut foo as &mut dyn Fn() -> u32; let _mut_coerced_zst_ref: &mut dyn Fn() -> u32 = &mut foo; //the suggested way to cast to a function pointer let fn_ptr = foo as fn() -> u32; //correct ways to print function pointers println!("{:p}", foo as fn() -> u32); println!("{:p}", fn_ptr); //potential ways to incorrectly try printing function pointers println!("{:p}", &foo); //~^ WARNING taking a reference to a function item does not give a function pointer print!("{:p}", &foo); //~^ WARNING taking a reference to a function item does not give a function pointer format!("{:p}", &foo); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &foo as *const _); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", zst_ref); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", cast_zst_ptr); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", coerced_zst_ptr); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &fn_item); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", indirect_ref); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &nop); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &bar); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &baz); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &unsafe_fn); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &c_fn); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &unsafe_c_fn); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &variadic); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &std::env::var::<String>); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p} {:p} {:p}", &nop, &foo, &bar); //~^ WARNING taking a reference to a function item does not give a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer //~^^^ WARNING taking a reference to a function item does not give a function pointer //using a function reference to call a function shouldn't lint (&bar)(1); //passing a function reference to an arbitrary function shouldn't lint call_fn(&bar, 1); parameterized_call_fn(&bar, 1); std::mem::size_of_val(&foo); unsafe { //potential ways to incorrectly try transmuting function pointers std::mem::transmute::<_, usize>(&foo); //~^ WARNING taking a reference to a function item does not give a function pointer std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); //~^ WARNING taking a reference to a function item does not give a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer //the correct way to transmute function pointers std::mem::transmute::<_, usize>(foo as fn() -> u32); std::mem::transmute::<_, (usize, usize)>((foo as fn() -> u32, bar as fn(u32) -> u32)); } //function references as arguments required to be bound by std::fmt::Pointer should lint print_ptr(&bar); //~^ WARNING taking a reference to a function item does not give a function pointer bound_by_ptr_trait(&bar); //~^ WARNING taking a reference to a function item does not give a function pointer bound_by_ptr_trait_tuple((&foo, &bar)); //~^ WARNING taking a reference to a function item does not give a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer implicit_ptr_trait(&bar); // ignore //correct ways to pass function pointers as arguments bound by std::fmt::Pointer print_ptr(bar as fn(u32) -> u32); bound_by_ptr_trait(bar as fn(u32) -> u32); bound_by_ptr_trait_tuple((foo as fn() -> u32, bar as fn(u32) -> u32)); } </ins>

I tried this code: I expected to see this happen: The compilation succeed or guide me to (1) cast the to with . (2) borrow the : . But in this case the addresses printed are the same (what?). Instead, this happened*: Cryptic error message: There is : . It took me minutes before I found the workaround. But it still surprised me. : <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
This creates a reference-to-function-pointer (type ), a double indirection. So it is not what you want. The error could possibly be improved, and the entire situation documented better, but I think getting an error is expected here. is not a function pointer, it is an anonymous ) (of size 0) indicating exactly the function it was created from. This type coerces to a function pointer, but cannot know what type to coerce it to. Printing function pointers is easy (well, if they are not polymorphic via ), but printing these function singleton ZSTs is hard.
It might also be worth linting against .
helps with the docs. But to close this issue, it would probably make sense to write a lint against where is the name of a function. That should be a matter of adding a new in which checks all expressions for being . That path we can pass to to get a . Now we just need to check if that refers to a function: pass the to . At least I hope that makes sense, someone stop me if this is all wrong. ;)
I'd like to help write this lint. The default level for the lint should be right? claim
Yeah, feels like a reasonable start.
Nominated for lang team discussion. It seems we usually ask for lints to be approved before shipping them, so let's get that process started. sorry for this, I wasn't aware of this part of the process. You can still go ahead and implement this if you want, but depending on what the lang team decides, we should submit this lint to clippy instead of the compiler itself. That might require minor adjustments, but the main work you are putting in and the testcases will be useful either way.


Question: <ins> // check-pass #![feature(c_variadic)] #![warn(function_item_references)] use std::fmt::Pointer; use std::fmt::Formatter; fn nop() { } fn foo() -> u32 { 42 } fn bar(x: u32) -> u32 { x } fn baz(x: u32, y: u32) -> u32 { x + y } unsafe fn unsafe_fn() { } extern "C" fn c_fn() { } unsafe extern "C" fn unsafe_c_fn() { } unsafe extern fn variadic(_x: u32, _args: ...) { } //function references passed to these functions should never lint fn call_fn(f: &dyn Fn(u32) -> u32, x: u32) { f(x); } fn parameterized_call_fn<F: Fn(u32) -> u32>(f: &F, x: u32) { f(x); } //function references passed to these functions should lint fn print_ptr<F: Pointer>(f: F) { println!("{:p}", f); } fn bound_by_ptr_trait<F: Pointer>(_f: F) { } fn bound_by_ptr_trait_tuple<F: Pointer, G: Pointer>(_t: (F, G)) { } fn implicit_ptr_trait<F>(f: &F) { println!("{:p}", f); } //case found in tinyvec that triggered a compiler error in an earlier version of the lint checker trait HasItem { type Item; fn assoc_item(&self) -> Self::Item; } fn _format_assoc_item<T: HasItem>(data: T, f: &mut Formatter) -> std::fmt::Result where T::Item: Pointer { //when the arg type bound by `Pointer` is an associated type, we shouldn't attempt to normalize Pointer::fmt(&data.assoc_item(), f) } //simple test to make sure that calls to `Pointer::fmt` aren't double counted fn _call_pointer_fmt(f: &mut Formatter) -> std::fmt::Result { let zst_ref = &foo; Pointer::fmt(&zst_ref, f) //~^ WARNING taking a reference to a function item does not give a function pointer } fn main() { //`let` bindings with function references shouldn't lint let _ = &foo; let _ = &mut foo; let zst_ref = &foo; let fn_item = foo; let indirect_ref = &fn_item; let _mut_zst_ref = &mut foo; let mut mut_fn_item = foo; let _mut_indirect_ref = &mut mut_fn_item; let cast_zst_ptr = &foo as *const _; let coerced_zst_ptr: *const _ = &foo; let _mut_cast_zst_ptr = &mut foo as *mut _; let _mut_coerced_zst_ptr: *mut _ = &mut foo; let _cast_zst_ref = &foo as &dyn Fn() -> u32; let _coerced_zst_ref: &dyn Fn() -> u32 = &foo; let _mut_cast_zst_ref = &mut foo as &mut dyn Fn() -> u32; let _mut_coerced_zst_ref: &mut dyn Fn() -> u32 = &mut foo; //the suggested way to cast to a function pointer let fn_ptr = foo as fn() -> u32; //correct ways to print function pointers println!("{:p}", foo as fn() -> u32); println!("{:p}", fn_ptr); //potential ways to incorrectly try printing function pointers println!("{:p}", &foo); //~^ WARNING taking a reference to a function item does not give a function pointer print!("{:p}", &foo); //~^ WARNING taking a reference to a function item does not give a function pointer format!("{:p}", &foo); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &foo as *const _); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", zst_ref); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", cast_zst_ptr); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", coerced_zst_ptr); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &fn_item); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", indirect_ref); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &nop); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &bar); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &baz); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &unsafe_fn); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &c_fn); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &unsafe_c_fn); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &variadic); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p}", &std::env::var::<String>); //~^ WARNING taking a reference to a function item does not give a function pointer println!("{:p} {:p} {:p}", &nop, &foo, &bar); //~^ WARNING taking a reference to a function item does not give a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer //~^^^ WARNING taking a reference to a function item does not give a function pointer //using a function reference to call a function shouldn't lint (&bar)(1); //passing a function reference to an arbitrary function shouldn't lint call_fn(&bar, 1); parameterized_call_fn(&bar, 1); std::mem::size_of_val(&foo); unsafe { //potential ways to incorrectly try transmuting function pointers std::mem::transmute::<_, usize>(&foo); //~^ WARNING taking a reference to a function item does not give a function pointer std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); //~^ WARNING taking a reference to a function item does not give a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer //the correct way to transmute function pointers std::mem::transmute::<_, usize>(foo as fn() -> u32); std::mem::transmute::<_, (usize, usize)>((foo as fn() -> u32, bar as fn(u32) -> u32)); } //function references as arguments required to be bound by std::fmt::Pointer should lint print_ptr(&bar); //~^ WARNING taking a reference to a function item does not give a function pointer bound_by_ptr_trait(&bar); //~^ WARNING taking a reference to a function item does not give a function pointer bound_by_ptr_trait_tuple((&foo, &bar)); //~^ WARNING taking a reference to a function item does not give a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer implicit_ptr_trait(&bar); // ignore //correct ways to pass function pointers as arguments bound by std::fmt::Pointer print_ptr(bar as fn(u32) -> u32); bound_by_ptr_trait(bar as fn(u32) -> u32); bound_by_ptr_trait_tuple((foo as fn() -> u32, bar as fn(u32) -> u32)); } </ins>

:)
As a point of interest, this would have been extremely useful in helping debug a segfault in The original code used , not .
Without the cast, this should not compile as transmute checks that the sizes match. I assume what you describe happens when using , i.e., not just remove the but also add a .
Unfortunately I never committed the broken code so I'm not sure what I had originally ... the closest thing is which doesn't compile. Sorry for the noise.
no worries. I already have the lint implemented, but in that case I'll wait until they discuss to write the tests
I think should compile. That's no noise, it seems very relevant. :)
poll T-lang Should we add a lint for taking a reference to a fn?
Team member has asked teams: T-lang, for consensus on: [x] [x] [x] [ ] [x] [ ]
I think I agree here, but to confirm: this isn't actually about linting the taking of a reference to a place of type, but just about using on the voldemort-typed function name constants, right?
Yes.
Discussed in a (rather small) meeting today: Those present felt a lint would make sense. If somebody wanted to go ahead and try to author one, please feel free and nominate the resulting PR for discussion.
all right, so if you want to open a PR, everything is settled for that. :)


Question: "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, expr_ty={:?}", field, base, expr, expr_t ); <del> let mut err = self.no_such_field_err(field.span, field, expr_t); </del> <ins> let mut err = self.no_such_field_err(field, expr_t); </ins> match *expr_t.peel_refs().kind() { ty::Array(_, len) => {

I just encountered this output: We currently mention available fields when the field used isn't found. It would be nice if we peeked at the types for the available fields to see if any of them has any fields (including through deref) of the name we originally wanted. In this case, I would love to see the following output: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I'll work on this. claim
I was just about to open a PR when I saw that you claimed the issue. It's my fault for not claiming this issue myself obviously, so if you've already been investing time into this the issue its still yours, but if you haven't can I open a PR for this?
I've done nothing yet as I planned to work on this tomorrow morning, so this is yours :)
release-assignment
if you're still interested in contributing, it seems to me that might be similar in scope and section of the codebase you could work in.
Thank you.


Question: <ins> error: expected one of `extern` or `fn`, found `WhereIsFerris` --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs:5:18 | LL |     const unsafe WhereIsFerris Now() {} |                  ^^^^^^^^^^^^^ expected one of `extern` or `fn` error: aborting due to previous error </ins>


Question: // the MIR body will be constructed well. let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; <del> let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; </del> <ins> let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("tried to create by-move body of non-coroutine receiver"); }; </ins> let args = args.as_coroutine(); let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap();

<!-- ICE: Rustc '-Zunstable-options --edition=2024 -ooutputfile -Zdump-mir-dir=dir' 'error: internal compiler error: impossible case reached', 'error: internal compiler error: impossible case reached' 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: [coroutinebymovebodydefid] looking up the coroutine by-move body for [analysis] running analysis passes on this crate -- label +F-asyncclosure
As a step of reducing your code examples, could you please ensure that is necessary to reproduce this ICE before mentioning it in the issue? This ICE reproduces on edition 2021, which is the current stable edition.
My project fails on nightly also while using edition 2021.
Yep, a fix is already up and it's waiting for approval. I recommend downgrading to a slightly older nightly until this is fixed.


Question: <del> #define CFG_RELEASE_NUM GetEnv("CFG_RELEASE_NUM") #define CFG_RELEASE GetEnv("CFG_RELEASE") #define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME") #define CFG_BUILD GetEnv("CFG_BUILD") [Setup] SetupIconFile=rust-logo.ico AppName=Rust AppVersion={#CFG_RELEASE} AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license AppPublisher=Mozilla Foundation AppPublisherURL=http://www.rust-lang.org VersionInfoVersion={#CFG_RELEASE_NUM} LicenseFile=LICENSE.txt PrivilegesRequired=lowest DisableWelcomePage=true DisableProgramGroupPage=true DisableReadyPage=true DisableStartupPrompt=true OutputDir=. SourceDir=. OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} DefaultDirName={sd}Rust Compression=lzma2/normal InternalCompressLevel=normal SolidCompression=no ChangesEnvironment=true ChangesAssociations=no AllowUNCPath=false AllowNoIcons=true Uninstallable=yes [Tasks] Name: modifypath; Description: &Add {app}bin to your PATH (recommended) [Components] Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed #ifdef MINGW Name: gcc; Description: "Linker and platform libraries"; Types: full #endif Name: docs; Description: "HTML documentation"; Types: full Name: cargo; Description: "Cargo, the Rust package manager"; Types: full Name: std; Description: "The Rust Standard Library"; Types: full // tool-rls-start Name: rls; Description: "RLS, the Rust Language Server" // tool-rls-end [Files] Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust #ifdef MINGW Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc #endif Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std // tool-rls-start Source: "rls/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls Source: "rust-analysis/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls // tool-rls-end [Code] const ModPathName = 'modifypath'; ModPathType = 'user'; function ModPathDir(): TArrayOfString; begin setArrayLength(Result, 1) Result[0] := ExpandConstant('{app}bin'); end; #include "modpath.iss" #include "upgrade.iss" // Both modpath.iss and upgrade.iss want to overload CurStepChanged. // This version does the overload then delegates to each. procedure CurStepChanged(CurStep: TSetupStep); begin UpgradeCurStepChanged(CurStep); ModPathCurStepChanged(CurStep); end; </del>

The .exe installer tries to install to "C:Program Files (x86)Rust", even though it's the 64-bit version. It then fails to create the destination directory due to a permission error. The .msi installer correctly defaults to "C:Program FilesRust <channel<version", and has no problems with permissions, I would expect the .exe installer to have the same behaviour.
Rust should install to , just like Ant, Python, and many others. is the place for developer tools that have a known folder. is badly named (compare to ), poorly suited for command line tools, and clutters the already hideous PATH more than .
/cc
Neither Ant nor Python install to C:tools by default, and searching I can't find any reference to C:tools even being a thing? Both Python and Ant install to C:Python<Versionand C:ant, which is incredibly annoying, so please don't do that!
I might be mistaken, but installing both through stuck them in for me. I'd recommend anyone with a machine running Vista or later use chocolatey. And there's a trend in chocolatey to have packages extract to when they aren't self-contained enough for .
For an OS without much filesystem hierarchy, is a decent place for developer and command-line packages, similar to on some unices. But I'd much rather see a that actually obeyed chocolatey's conventions and extracted an archive to , with no installer/registry involvement. But Rust only and installers for windows. : And all packages that do this reduce PATH clutter, since chocolatey symlinks their executables into .
The idea was to deprecate the .exe installer once .msi is known to be working satisfactory.
Can we have a zip release too, that contains Rust and Cargo like the others? Linux and OS X have an archive release. Those are preferred in chocolatey because they don't involve the registry or any other Windows components.
We do produce tarballs for windows.
Seems like we should probably just stop producing the .exe's. That fix would go in
I don't see a cargo+rustc nightly tarball for windows, although I do see ones for linux and osx.
triage: We do not link to the .exe installer anymore, but we still produce them.


Question: <del> #define CFG_RELEASE_NUM GetEnv("CFG_RELEASE_NUM") #define CFG_RELEASE GetEnv("CFG_RELEASE") #define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME") #define CFG_BUILD GetEnv("CFG_BUILD") [Setup] SetupIconFile=rust-logo.ico AppName=Rust AppVersion={#CFG_RELEASE} AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license AppPublisher=Mozilla Foundation AppPublisherURL=http://www.rust-lang.org VersionInfoVersion={#CFG_RELEASE_NUM} LicenseFile=LICENSE.txt PrivilegesRequired=lowest DisableWelcomePage=true DisableProgramGroupPage=true DisableReadyPage=true DisableStartupPrompt=true OutputDir=. SourceDir=. OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} DefaultDirName={sd}Rust Compression=lzma2/normal InternalCompressLevel=normal SolidCompression=no ChangesEnvironment=true ChangesAssociations=no AllowUNCPath=false AllowNoIcons=true Uninstallable=yes [Tasks] Name: modifypath; Description: &Add {app}bin to your PATH (recommended) [Components] Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed #ifdef MINGW Name: gcc; Description: "Linker and platform libraries"; Types: full #endif Name: docs; Description: "HTML documentation"; Types: full Name: cargo; Description: "Cargo, the Rust package manager"; Types: full Name: std; Description: "The Rust Standard Library"; Types: full // tool-rls-start Name: rls; Description: "RLS, the Rust Language Server" // tool-rls-end [Files] Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust #ifdef MINGW Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc #endif Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std // tool-rls-start Source: "rls/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls Source: "rust-analysis/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls // tool-rls-end [Code] const ModPathName = 'modifypath'; ModPathType = 'user'; function ModPathDir(): TArrayOfString; begin setArrayLength(Result, 1) Result[0] := ExpandConstant('{app}bin'); end; #include "modpath.iss" #include "upgrade.iss" // Both modpath.iss and upgrade.iss want to overload CurStepChanged. // This version does the overload then delegates to each. procedure CurStepChanged(CurStep: TSetupStep); begin UpgradeCurStepChanged(CurStep); ModPathCurStepChanged(CurStep); end; </del>

I don't have access to windows at the moment to check if this bug has been resolved, but it's been a long time...
Grabbing the Windows download link from and swapping the for yields a functional link to the , which is nice. Testing on win7-x64, the MSI extracts with lessmsi, but the directory structure is somewhat unusual so there's no one-liner to get the Rust folder out. The best I came up with was: This yields a Rust install rooted at . However now that exists, multiple targets aren't really an issue anymore. Someone should make a Chocolatey package for
Can someone with access to Windows check what happens here today?
The latest version installs to instead, which works, but is a terrible default.
Triage: ! This seems... fine. I'm not sure if this should stay open or not; I'll let the relevant team (infra? compiler?) decide.


Question: use rustc_infer::infer::{self, InferOk}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; <del> use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable}; </del> <ins> use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitable}; </ins> use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits;


Question: use rustc_infer::infer::{self, InferOk}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; <del> use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable}; </del> <ins> use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitable}; </ins> use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits;


Question: return None; }; <del> if new_ty.references_error() { return None; } </del> self.state.steps.push((self.state.cur_ty, kind)); debug!( "autoderef stage #{:?} is {:?} from {:?}",

<!-- ICE: Rustc '' 'thread 'rustc' panicked at 'coerceborrowedpointer had no error'', 'thread 'rustc' panicked at 'coerceborrowedpointer had no error'' File: --auto-reduced (treereduce-rust): <details<summary<strongoriginal code</strong</summary<poriginal: </p</detailsVersion 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: [typeck] type-checking [analysis] running analysis passes on this crate --
Regression in there are no individual builds of the commits yet tho :sweat_smile:
I would guess cc


Question: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

: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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

<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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: /// # Examples /// /// ``` <del> /// # #![feature(vec_remove_item)] </del> /// let mut vec = vec![1, 2, 3, 1]; /// /// vec.remove_item(&1); /// /// assert_eq!(vec, vec![2, 3, 1]); /// ``` <del> #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] </del> <ins> #[stable(feature = "vec_remove_item", since = "1.42.0")] </ins> pub fn remove_item<V>(&mut self, item: &V) -> Option<T> where T: PartialEq<V>,

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: _ => None, } } <ins> fn host_dll_subdir() -> Option<&'static str> { if cfg!(target_arch = "x86_64") { Some("amd64") } else if cfg!(target_arch = "x86") { Some("") } else { None } } </ins> } // If we're not on Windows, then there's no registry to search through and MSVC // wouldn't be able to run, so we just call `link.exe` and hope for the best. #[cfg(not(windows))] <del> pub fn link_exe_cmd(_sess: &Session) -> Command { Command::new("link.exe") </del> <ins> mod platform { use std::path::PathBuf; use std::process::Command; use session::Session; pub fn link_exe_cmd(_sess: &Session) -> Command { Command::new("link.exe") } pub fn host_dll_path() -> Option<PathBuf> { None } </ins> } <ins> pub use self::platform::*; </ins>

On nightly (and beta I believe) the compiler will currently fail when cross compiling from x86_64 to x86 (after ensuring the standard library is in the right location) with the message: I believe this is a regression from and , which were backported, so I believe this is a stable regression. That being said I doubt anyone other than Cargo CI is doing this, so it may not be that big. I also believe that is working on a patch, but this should help track this issue.
I have been doing this with ring and ring-based projects for many months.


Question: let len = self.buf.len(); let mut ret = Ok(()); while written < len { <del> match self.inner.as_mut().unwrap().write(&self.buf[written..]) { </del> <ins> self.panicked = true; let r = self.inner.as_mut().unwrap().write(&self.buf[written..]); self.panicked = false; match r { </ins> Ok(0) => { ret = Err(Error::new(ErrorKind::WriteZero, "failed to write the buffered data"));

There is a panic safety issue in : after a call panics, the impl of calls again, which means the buffer contents are potentially written twice. This may cause an application to overwrite parts of a file that it did not mean to overwrite (in a DB engine written in Rust, this could cause unrecoverable data corruption!). Demonstration: The expected output of the demo program is , the actual output is: More generally, we need a story for panic safety in Rust. My takeaway from the related discussions (e.g. , , the trait) was that only code and impls should have to worry about panic safety. The demo app contains none of these, so I'd consider this a bug in . (otherwise all implementations would need to provide the strong exception safety guarantee?) Solution: could use temporarily mark the buffer as empty during the calls; so that the impl doesn't do anything after a panic. However, this doesn't help if the panic occurs during a call...
Note that Rust is normally referring to "memory safety" when talking about safety, so the issue here isn't in conflict with the related discussions. It's definitely a bug in , but I want to point out how specific it is here: the only reason you have odd behaviour is because you have a implementation that will panic after successfully writing the data it is given. I'm all for making more robust, but it's not just "if the call panics", it's "if the call panics after successfully writing data". Panicking before a successful write (or if the write fails), would not have the same issue.
If your impl is panicking in the middle of a write, it seems to me like you're in data corruption land with or without a second write. This is not quite the case - and thread locals expand that surface area. What's specifically the expected behavior here? Is the implementation specifically the thing that needs tweaking, or should the totally poison itself? For reference, Java's class has no special handling for exceptions thrown from the inner : , so adjusting alone seems like a reasonable route to take.
Without the , a panic in the middle of a write (without ) only corrupts the part of the file that the application meant to overwrite. In a DB engine context, that means the resulting corruption can be repaired when the transaction is rolled back.


Question: let len = self.buf.len(); let mut ret = Ok(()); while written < len { <del> match self.inner.as_mut().unwrap().write(&self.buf[written..]) { </del> <ins> self.panicked = true; let r = self.inner.as_mut().unwrap().write(&self.buf[written..]); self.panicked = false; match r { </ins> Ok(0) => { ret = Err(Error::new(ErrorKind::WriteZero, "failed to write the buffered data"));

But with , a panic after some data was written might corrupt parts of the file that are not saved in the rollback journal, so recovery not possible. I think we need some guideline like: If a method call panics, it's a bug to call any additional methods on the same object. Thus, the bug is in . may need something similar to a poison-flag so that the impl can detect whether a previous call panicked, but it doesn't need to protect against it's own methods being called after a panic (that would be considered a bug in the caller). The Java has the same problem, but the expectation in the Java world is different: it's trivially possible to catch an exception and continue using the potentially-invalid state; so in Java's case I would argue that all implementations should provide the strong exception safety guarantee to avoid this kind of issue. Essentially, the Rust world needs to decide between a Java/C++-style "strong exception safety guarantee" (=failing method call should not have any side effects) or a new "no-use-after-panic guarantee" (=after a failing method call, no additional method calls should occur). Some types (like BufWriter) can be compatible with at most one of the guarantees -- strong exception safety requires that a panicking call has no side effects; no-use-after-panic requires that a panicking call has the side effect of suppressing the buffer flush in the impl. The trait seems to be roughly equivalent to basic exception safety. Types that do not implement instead live in the world. Generic types implementing need to be careful not to call any functions on the type parameter from within the implementation if a previous call panicked (unless they use a bound).
triage: P-medium is fixing the data corruption in


Question: }, value_ns: match self.resolve( path_str, <ins> disambiguator, </ins> ValueNS, &current_item, base_node,

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: }, value_ns: match self.resolve( path_str, <ins> disambiguator, </ins> ValueNS, &current_item, base_node,

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> // Copyright 2017 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. // Tests the rustdoc --sort-modules-by-appearance option, that allows module declarations to appear // in the order they are declared in the source code, rather than only alphabetically. // compile-flags: -Z unstable-options --sort-modules-by-appearance pub mod module_b {} pub mod module_c {} pub mod module_a {} // @matches 'sort_modules_by_appearance/index.html' '(?s)module_b.*module_c.*module_a' // @matches 'sort_modules_by_appearance/sidebar-items.js' '"module_b".*"module_c".*"module_a"' </ins>

Instead it should use the order that appear in the crate file. Even better, it should allow adding section headers (with a description) between them. Hypothetically: And get something like this: This would make both the source code and the documentation more accessible as the modules would be presented in a comprehensible order, with some description of each related group of modules. Edit: Rename issue to reflect that this isn't an either-or. Alphabetical order is useful, but so is programmer-specified order (to make the code accessible for newcomers) and Rustdoc should support both - see the thread below.
Shouldn't related modules be nested in submodules rather than logically ordered in the source? Finding things in long non-ordered lists is a real pain.
Yeah, I'm going to vote "alphabetical".
Hmmm. I pretty sure I put a comment here, and now its gone. Strange. Anyway. Here it goes again. Alphabetical order == random order. That's great when you know what you are looking for and just want to find it. When coming to a new non-trivial code base, being presented the content in random order is just about the worst possible way to access it. Nested modules allow us to group related modules together, and that's a good thing. If you have a long list of modules, certainly, group them. But this doesn't solve the problem. You now have a TOC where each level is randomized, which is still inaccessible. Searching for a function or module by name is an important use case, sure. But being able to access a new code base is as important, if not more so. Looking up a name in a short non-alphabetized list (at each level) isn't too hard, and one can always compensate for the lack of an alphabetical index by using ^F. Trying to understand a system presented in random order is next to impossible, and one can not compensate for the lack of a comprehensible order in a large system. If there was a way to specify the order of the entries in each level, which we agree should only contain "a few" entries, then the TOC would become accessible. If one could even add a bit of annotation for each level, so much the better.


Question: <ins> // Copyright 2017 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. // Tests the rustdoc --sort-modules-by-appearance option, that allows module declarations to appear // in the order they are declared in the source code, rather than only alphabetically. // compile-flags: -Z unstable-options --sort-modules-by-appearance pub mod module_b {} pub mod module_c {} pub mod module_a {} // @matches 'sort_modules_by_appearance/index.html' '(?s)module_b.*module_c.*module_a' // @matches 'sort_modules_by_appearance/sidebar-items.js' '"module_b".*"module_c".*"module_a"' </ins>

The annotated TOC would serve as a very accessible way for a newcomer to understand the code base. And, this doesn't rule out also generating an alphabetically sorted reference index, beside the TOC. All good books do both - a TOC in reasonable order and an index for looking up data by name. We shouldn't have to choose, we should be able to get both. So, I misnamed the issue. It should be "Rustdoc shouldn't list modules only alphabetically".
Agreed. Can someone rename the title?
Rename done.
Visiting for triage. Minor, but still an issue.
Triage, still listed alphabetically. Here's a sample source file: !