Question: ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif <ins> ifdef DISABLE_RPATH # NOTE: make this CFG_RUSTC_FLAGS after stage0 snapshot RUSTFLAGS_STAGE1 += --no-rpath RUSTFLAGS_STAGE2 += --no-rpath RUSTFLAGS_STAGE3 += --no-rpath endif </ins> # The executables crated during this compilation process have no need to include # static copies of libstd and libextra. We also generate dynamic versions of all

Currently (something after 0.5) rustc (IIUIC) is using rpaths to point libs and binaries to the appropriate locations. This is problematic when rustc and the other libs/bins are package e.g. for Fedora. The rpath usage should be made optional - can be used instead - and LDLIBRARYPATH.
Why is this problematic for packaging? Is it because the rpath values end up with the wrong values? Each crate's rpath has several values, one of which is supposed to be the final installation location (controlled with ). Can we just provide more control over which locations are used during rpathing?
In general Fedora recommends to not use rpaths [0], because the paths are hardcoded in the binary. Fedora preferres to point the dynamic linker to the appropriate paths [1]. But yes, we are more flexible about internal libraries - which the case is here. So yes, it would also help us if we could controll the rpath path (which goes a bit into the direction if issue ) [0] [1]
The following rpath is used in e.g. the cargo binary: The rpath referres to rpm's buildroot, where the lib won't stay (it will be instaled to ) Maybe the problem could adressed if the rpath would respect - but this could lead to problems at build time. Maybe LDLIBRARYPATH can be used to point to the correct dir's at build time, and the rpath can be used to point to the correct dir's at runtime. Just my 2ct - but you ar ethe expert :)
Thanks for those links. We do generate rpaths with the expectation that some of them will be invalidated by moving the binaries around. It's possible we could consider removing rpath, but it sure is nice to not think about dynamic loading when running binaries out of my build directory. We could easily add a flag to the configure script, to turn off the rpath for all the rust-provided libraries, with the assumption that package managers would modify during install. If we did that I feel like we would still want the installed rustc to generate rpaths with user-built libraries - otherwise the experience would be different depending on the rust installation. We could also just remove rpath completely - it doesn't work on windows anyway.


Question: ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif <ins> ifdef DISABLE_RPATH # NOTE: make this CFG_RUSTC_FLAGS after stage0 snapshot RUSTFLAGS_STAGE1 += --no-rpath RUSTFLAGS_STAGE2 += --no-rpath RUSTFLAGS_STAGE3 += --no-rpath endif </ins> # The executables crated during this compilation process have no need to include # static copies of libstd and libextra. We also generate dynamic versions of all

Another thing to consider is that, if we just used rustpkg for all builds, and let rustpkg install all libraries at a known location, then we might be able to conveniently not use rpath while still doing the right thing at load time. Can user directories like be put into ?
Yes - I can fully understand how easy running rust in the build directory is when using rpaths :) For the build directory use case it should be possible to create wrappers for rustc and friends which use to point to the correct dirs. You mention thet some libs might reside in , could you explain the overall concept you are following with this? In general I'd expect libraries to appear in /lib, /usr/lib some and some private /usr/lib/myapp. There are also some xdg specs that specify and - but let usfirst see what you say about ~/.rustpkg. Oh, I don't think that ~/.rustpkg would be expanded correctly if put into
Just to summarize my thoughts: If rpath is used, the rpath path beeing used should only use directories below (to point to non-standard dirs containing libs relevant for a rust component). The rpath path should not point to any build-time dir. To include libraries at buildtime or when using the binaries in the build directory I'd suggest using wrappers (isn't autotools doing it like this?) which set appropriately.
Any follow up thoughts?
Our package manager will by default not be installing libraries to a system location and will instead put them in the user's directory, . This doesn't seem out of the ordinary to me; consider cabal, etc. The behavior you recommend requires some deep changes to how Rust works, so need to be considered carefully. Does the current behavior prevent packaging in Fedora, and is there a minimal change we can make to unblock packaging? You'll probably be interested in this subject.
Thanks for the rustpkg explanation. Do I understand that rustpkg will create binaries and libs with rpaths pointing to the user's specific rustpkg dir ? My feeling is that this user specific rpaths should be configurable at build time. The use case is obviously when the binary or lib is going to be installed systemwide. The only rpath exception is the rpath pointing to the system wide package specific libdir (e.g. ).


Question: ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif <ins> ifdef DISABLE_RPATH # NOTE: make this CFG_RUSTC_FLAGS after stage0 snapshot RUSTFLAGS_STAGE1 += --no-rpath RUSTFLAGS_STAGE2 += --no-rpath RUSTFLAGS_STAGE3 += --no-rpath endif </ins> # The executables crated during this compilation process have no need to include # static copies of libstd and libextra. We also generate dynamic versions of all

I think that I'll spend a bit more time with looking at and and might get a better feeling for the problem. Btw.: I noted that the libdir isn't configurabel. Fedora for example keeps x86_64 libs in (/usr)?/lib64, and i686 in (/usr)/lib. IIUIC this is currently not possible with rust as the libs will be installed to /usr/lib/arch-specific-path
The point about libdir is well taken and I updated . I am not entirely sure how rustpkg does it's build now or how and intend for it to work, but based on the current language design I would expect that, yes, binaries installed to would have rpaths pointing there. Currently there are several rpaths configured for each linked library so that they hopefully fall back to something useful when the libraries are moved around during install or during the bootstrapping process, something like: The relative path to the library The absolute path to where the library was at build time The system installation path Under this scheme I would expect that would, when linking against libraries in , create rpaths to .
Yes, there are several rpaths used (seen in and ) and I'd say - even with looking at rust itself, without the packaging glasses on - that it should be configurable what rpaths are used. Maybe it should be an option of . As said, system wide binaries are the best example for binaries where you don't want to many rpaths - including no rpaths pointing to some user dir.
Please don't tag TJC :(
Sorry, TJC! Maybe it's time to give in and start working on Rust :) Seriously though, sorry. I'm sure it's a real PITA.
mentioned that this is a security issue, which I didn't realize. Debian also says .
By the way, it's possible to strip this with but it would be much nicer to not require a third party tool.
I generally wonder why you don't add a user-specific to to point to the user specific rustpkg dir instead of using rpath. That makes it much easier to cope with - and that would also be in par with (at least) the Fedora guidelines. And I suppose with Debian's too, as it's the common way. (See 3rd party java binaries. They modify the to point to some hidden dir in the userdir.)
We used to.


Question: ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif <ins> ifdef DISABLE_RPATH # NOTE: make this CFG_RUSTC_FLAGS after stage0 snapshot RUSTFLAGS_STAGE1 += --no-rpath RUSTFLAGS_STAGE2 += --no-rpath RUSTFLAGS_STAGE3 += --no-rpath endif </ins> # The executables crated during this compilation process have no need to include # static copies of libstd and libextra. We also generate dynamic versions of all

Users kept forgetting and/or getting annoyed having to adjust it when running from a build dir. Rpaths made it possible to run foo/bar/rustc no matter which rustc you chose.
right. IIUIC - I always feel like a noob when it comes to autotools - autotools are generating wrappers for binaries which are created during a build process and moves the original binaries to hiddend irectories. The wrappers are then modifying the environment (setting env vars etc) to achieve the same goal (so e.g. that rustc can be run from the dev directory without messing with the env vars yourself). I wonder if this could help.
Okay, it's actually not autools which creates these wrappers but libtool:
Sorry, I didn't mean to imply a disinterest in fixing this better, just noting how it came to be. Also strongly disinterested in using libtool. Would prefer going back to telling users to set env vars.
How about defaulting to static linking (when it works)? Dynamic linking is valuable, but mostly for global installs handled by a package manager. Of course, if we end up with a bunch of tools using that would be wasteful. I think RPATH will just lead to confusion, and it's an easy security hole to leave open.
I would be very happy to get static linking working well enough to make it a default in many such cases. But we ought to do the right thing when linking dynamically too. Is rpath-using- considered acceptable? I.e. is it just the absolute paths that are problematic?
The absolute paths are the ones that can easily be a security issue, so isn't that bad. I would still rather avoid it for a globally installed package but it's easy enough to strip for people who don't need it and won't be an issue if you don't know about it (like the absolute path could be). Using the rpath could be a flag, but the absolute path should never be there.
Nominating for milestone 2: backwards compatible. (The choice of whether one needs to put a setting in or use some configure flag for certain systems, etc, seems like a backwards compatibility issue. Though maybe I misunderstand and these are issues only for people developing itself, not for clients of ?) It also could well be that this is more appropriately assocated with milestone 1: well-defined.


Question: ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif <ins> ifdef DISABLE_RPATH # NOTE: make this CFG_RUSTC_FLAGS after stage0 snapshot RUSTFLAGS_STAGE1 += --no-rpath RUSTFLAGS_STAGE2 += --no-rpath RUSTFLAGS_STAGE3 += --no-rpath endif </ins> # The executables crated during this compilation process have no need to include # static copies of libstd and libextra. We also generate dynamic versions of all

I suspect and have a more concrete notion about this.
I don't have anything much to add to this despite it coming up for triage today. I think it has to be fixed still, I'm still happy to do it via whatever combination of static linking by default and use of is sufficient for packagers, and I haven't seen any clear movement on it in the meantime.
accepted for backwards-compatible milestone
I'm getting worried that we won't resolve this for 1.0. I agree this is important to fix. Here's my current suggestion: Modify the build system to once again set LDLIBRARYPATH/PATH to find the appropriate dynamic libraries. Add a flag to rustc to disable rpath Add a configure flag to disable rpathing the rust build itself. Packagers can use this to do whatever they want. With this logic the rust package itself could avoid rpath where distros have their own way of dealing with library paths. The rustc installed by these distros would still be rpathing user's crates for the sake of convenience. Is this an acceptable compromise or do distros want us to completely disable rpath? I'm afraid that doing so would provide an inconsistent developer experience depending on how rustc is acquired; if we need to do that then we instead must find a way to completely eliminate rpath.
If we start to just statically link everything by default then rpath becomes much less important and we can just say it's up to users to figure it out if they opt into dynamic linking.
I think we should completely remove absolute rpaths. It's okay to have $ORIGIN-based ones but it may not be a good default. I'm not sure what the answer is to that, but agree that static linking basically resolves this.
It doesn't appear that this is fully working. There are still rpaths in the binaries when configured with even though the flag for rustc does work. /usr/bin/rustc: RPATH=$ORIGIN/../lib:/build/rust-git/src/rust/x8664-unknown-linux-gnu/stage1/lib/rustlib/x8664-unknown-linux-gnu/lib:/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib
What steps did you follow to having the rpath show up? I thought I double checked on linux that the configure flag worked, but I may have overlooked something.


Question: use ascii; use borrow::{Cow, ToOwned, Borrow}; use boxed::Box; <del> use clone::Clone; </del> use convert::{Into, From}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use error::Error;

We need to find a way to implement Clone for where . In user code, "cloning" such a box manually is simple: will do it with a short roundtrip through which should be unproblematic. In the rust distribution, we can't impl Clone easily since the tools to do so are in libcollections but the Box type lives in liballoc.
You do not need vec for the implementation. Something like the following would work: Note that because can panic it is required to keep track of the partial result so the correct stuff is dropped.
Yes, that's nice that it can be carefully solved by essentially extracting the needed parts from what Vec does. But the Box code is otherwise so clean, it doesn't feel like the right way to do it.
You're welcome to suggest an alternative but I doubt it can be done in a manner that is both correct and significantly cleaner :)
Your fundamental analysis is great: just isn't an exception safe representation while filling it with elements. It needs to keep track of the fill level, so a representation like Vec or BoxBuild is needed...
Clone is also wanted for , but that can be much simpler: There is no panic issue, and it can use a simple memcpy of the data.


Question: #![feature(rustc_attrs)] fn main() { <del> #![rustc_dummy("hi" , 1 , 2 , 1.012 , pi = 3.14 , bye , name ("John"))] </del> <ins> #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))] </ins> #[rustc_dummy = 8] fn f() { } <del> #[rustc_dummy(1 , 2 , 3)] </del> <ins> #[rustc_dummy(1, 2, 3)] </ins> fn g() { } }

proc-macro derive panicked All of the 62 regressions are due to old versions of having an assert expecting instead of . So this is again a consequence of whitespace changes in pretty-printing (). I think we should be able to fix this by special casing the comma token during token stream pretty-printing and not printing the space before it.
Fixed in
Just FYI, we discussed this in the meeting. We felt like the action here was appropriate -- while in general we do not guarantee stability of pretty printing, it makes sense to be judicious, and in this particular case not having a leading space before just looks better anyway.


Question: !msg.contains("if and else have incompatible types") && !msg.contains("if may be missing an else clause") && !msg.contains("match arms have incompatible types") && <del> !msg.contains("structure constructor specifies a structure of type") { </del> <ins> !msg.contains("structure constructor specifies a structure of type") && !msg.contains("has an incompatible type for trait") { </ins> return None } let first = msg.match_indices("expected").filter(|s| {

The multi-line errors should be extended to include this testcase. missed this because the didn't go through . I tried but that didn't work either. If someone can point me to to where to catch it, I can probably fix this too. cc Code: Error: Change to:


Question: match ty.normalized.ty_adt_def() { Some(adt_def) if adt_def.has_ctor() => { let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap(); <ins> // Check the visibility of the ctor. let vis = tcx.visibility(ctor_def_id); if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) { tcx.sess .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) }); } </ins> let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); let user_substs = Self::user_substs_for_adt(ty); user_self_ty = user_substs.user_self_ty;

I tried this code: I expected to see this happen: compilation should fail because the trait impl is defined outside of the module for the type but refers to its private field. Instead, this happened: this compiled successfully This reproduces on the playground for stable Rust, version 1.69.0:
Adding a main function and attempting to call the (playground link: ) raises the compilation error: !
This can be reproduced with cross-crate (e.i., any other crate can access the private field). This means that all encapsulations that take advantage of the field being private can be bypassed. (For example, if we change Vec to a tuple struct, the same thing as setlen could be done in safe code by abusing this bug.) label +I-unsound Also, this can be reproduced in all versions where is stable (e.i., 1.32+). It's a matter of how you initialize Foo. If you provide a constructor for Foo, you won't get a compile error:
Just for completeness, turning this into a segfault without external crates/just std:
label A-visibility
this has been unsound ever since in version 1.32
WG-prioritization assigning priority (). label -I-prioritize +P-high


Question: FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option<String> }, } <del> fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind { ty::FnPtr(_) => true, ty::Ref(..) => true, ty::Adt(field_def, substs) if field_def.repr.transparent() && !field_def.is_union() => { for field in field_def.all_fields() { let field_ty = tcx.normalize_erasing_regions(ParamEnv::reveal_all(), field.ty(tcx, substs)); if field_ty.is_zst(tcx, field.did) { continue; } </del> <ins> impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Is type known to be non-null? fn ty_is_known_nonnull(&self, ty: Ty<'tcx>) -> bool { match ty.kind { ty::FnPtr(_) => true, ty::Ref(..) => true, ty::Adt(field_def, substs) if field_def.repr.transparent() && !field_def.is_union() => { for field in field_def.all_fields() { let field_ty = self.cx.tcx.normalize_erasing_regions( self.cx.param_env, field.ty(self.cx.tcx, substs), ); if field_ty.is_zst(self.cx.tcx, field.did) { continue; } </ins> <del> let attrs = tcx.get_attrs(field_def.did); if attrs.iter().any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed)) || ty_is_known_nonnull(tcx, field_ty) { return true; </del> <ins> let attrs = self.cx.tcx.get_attrs(field_def.did); if attrs .iter() .any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed)) || self.ty_is_known_nonnull(field_ty) { return true; } </ins> } <del> } false </del> <ins> false } _ => false, </ins> } <del> _ => false, </del> } <del> } /// Check if this enum can be safely exported based on the /// "nullable pointer optimization". Currently restricted /// to function pointers, references, core::num::NonZero*, /// core::ptr::NonNull, and #[repr(transparent)] newtypes. /// FIXME: This duplicates code in codegen. fn is_repr_nullable_ptr<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ty_def: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>, ) -> bool { if ty_def.variants.len() != 2 { return false; } </del> <ins> /// Check if this enum can be safely exported based on the "nullable pointer optimization". /// Currently restricted to function pointers, references, `core::num::NonZero*`, /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes. fn is_repr_nullable_ptr( &self, ty: Ty<'tcx>, ty_def: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>, ) -> bool { if ty_def.variants.len() != 2 { return false; } </ins> <del> let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields; let variant_fields = [get_variant_fields(0), get_variant_fields(1)]; let fields = if variant_fields[0].is_empty() { &variant_fields[1] } else if variant_fields[1].is_empty() { &variant_fields[0] } else { return false; }; </del> <ins> let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields; let variant_fields = [get_variant_fields(0), get_variant_fields(1)]; let fields = if variant_fields[0].is_empty() { &variant_fields[1] } else if variant_fields[1].is_empty() { &variant_fields[0] } else { return false; }; </ins> <del> if fields.len() != 1 { return false; } </del> <ins> if fields.len() != 1 { return false; } </ins> <del> let field_ty = fields[0].ty(tcx, substs); if !ty_is_known_nonnull(tcx, field_ty) { return false; } </del> <ins> let field_ty = fields[0].ty(self.cx.tcx, substs); if !self.ty_is_known_nonnull(field_ty) { return false; } </ins> <del> // At this point, the field's type is known to be nonnull and the parent enum is Option-like. // If the computed size for the field and the enum are different, the nonnull optimization isn't // being applied (and we've got a problem somewhere). let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, ParamEnv::reveal_all()).unwrap(); if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) { bug!("improper_ctypes: Option nonnull optimization not applied?"); } </del> <ins> // At this point, the field's type is known to be nonnull and the parent enum is // Option-like. If the computed size for the field and the enum are different, the non-null // optimization isn't being applied (and we've got a problem somewhere). let compute_size_skeleton = |t| SizeSkeleton::compute(t, self.cx.tcx, self.cx.param_env).unwrap(); if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) { bug!("improper_ctypes: Option nonnull optimization not applied?"); } </ins> <del> true } </del> <ins> true } </ins> <del> impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { </del> /// Check if the type is array and emit an unsafe type lint. fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { if let ty::Array(..) = ty.kind {

While reviewing I noticed for the first time that the improperctypes lint normalizes with the "revealall" mode. I don't have a nuanced understanding of what that means exactly but based on the general description in the rustc docs and experimentation (see below) I think that's probably the wrong choice for this lint, because it exposes details to the user that are normally hidden during type checking. For example, using existential types, the lint pierces through otherwise-opaque existentials to look at the underlying (hidden) type, thus it both accepts code that is only FFI-safe because of the particular type underlying the existential, which users of that type shouldn't know or rely on leaks the underlying type to the user in error messages when (correctly) rejecting uses of an existential type as FFI-unsafe I can't quickly find an equivalent using only stable , because we don't have , but if there's a way to write "Option of the return type of this function" in stable Rust, then that would presumably have the same issue. cc for fact-checking my understanding that this is because of reveal_all
User-facing diagnostics should avoid the mode, yeah. In fact, the other variant of is literally - also the doc comments are pretty explicit about this: cc
I've been using 's over in recent PRs that modify the lint (see , , and ). In each recent PR, I've ensured that opaque types are prohibited (in the spirit of "FFI-safety of a type not relying on particular type behind an opaque type being FFI-safe") - with the exception of when a opaque type is used in a projection (). Unless there are specific examples of behavior that still need to be changed as a result of this issue - should this issue be closed?
My litmus test for closing this would be "all the normalizing done in improper_ctypes uses ", which is hard to audit for while there's multiple PRs in flight that address parts of the problem. After those PRs are all merged, we can see if there's any remaining and if so, their location should tell us how to exercise any remaining questionable behavior.
I've opened to fix the remaining two places that is used now that the other PRs have landed.


Question: <ins> error[E0224]: at least one trait is required for an object type --> $DIR/issue-79467.rs:4:5 | LL |     dyn 'static: 'static + Copy, |     ^^^^^^^^^^^ error: aborting due to previous error For more information about this error, try `rustc --explain E0224`. </ins>

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --code from <!-- 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</details
I think this is the code crashing: Assigning P-low by the same rationale as , but I expect this to be much easier to fix than , , or
No longer crashing: `


Question: expr.span); } Err(..) => { <del> rcx.fcx.tcx().sess.span_note(expr.span, "cat_expr_unadjusted Errd during dtor check"); </del> <ins> let tcx = rcx.fcx.tcx(); if tcx.sess.has_errors() { // cannot run dropck; okay b/c in error state anyway. } else { tcx.sess.span_bug(expr.span, "cat_expr_unadjusted Errd"); } </ins> } } }

I tried to get a minimal example, now i just ended up with completely senseless code, that still gives the error. playpen says: if you remove the for loop, only the last two cat_expr notes are left. adding more code just ends up with more of the notes.
this is pretty much my fault. :) In all the cases that I have seen where it arises, it is due to a type error (or a type inference failure at at least) somewhere in the code. Of course the notes are incredibly annoying. I will try to fix.
And of course the concrete example given here is one where there is no type error. At least, not one exposed by compiling this code. (I have not yet managed to show being instantiated concretely without causing some other type error to arise.)
(but there may be a mix of bugs causing the original input here to pass. In particular, the code in the description is doing , but that associated type does not exist. One needs . See also: )
cc


Question: #![crate_id="lint_stability#0.1"] #![crate_type = "lib"] <ins> #![feature(macro_rules)] #![macro_escape] </ins> #[deprecated] pub fn deprecated() {} #[deprecated="text"]

The expansion of and both currently cause code to fail the stability check because they expand to reveal unstable implementation details. A seemingly reasonable solution to this would be to just not run the analysis on any code that has been macro-expanded. cc
I definitely agree with this approach: we should be able to annotate a macro with a stability level, and that's what should count for its users. Do we have a way of telling what part of an AST was generated via macro expansion by the time we get to linting?
Mostly; there's the field of a : for normal code, for macro generated code (basically containing the backtrace of macro invocations that led to that point).
OK, that makes this sound like a pretty easy fix. I'll take a quick look at it tomorrow (unless wants to?)
Hm, this seems slightly subtle, since the contents of a macro would then never be checked for stability. This differs to a conventional function, e.g. given , won't warn, but the contents of is still checked, while where is just never checked. (Of course, macros and phasing are both feature gated so you have to opt-in to instability to use non-standard macros anyway.)
Good point. Also, it looks tricky with the current infrastructure to even lint on the macro invocation -- the backtrace of macro expansion does not appear to link to the def_id of the macro (or give any other way of getting at the macro's stability). Nevertheless, I think we should bail out of the lint when we hit the results of expansion; those should be checked, if anywhere, at the site of macro definition. One other question: do syntax extensions also produce the span information you mentioned above? I ask because original problematic cases are written syntax extensions. If not, is there some other way of telling that an expansion happened?
I have a patch ready that bails of out the lint on expanded code. This also seems to mask uses of . If y'all are ok with this strategy for now, I'll file a PR.
Sounds good to me. Thanks!
cc


Question: let receiver_ty = sig.inputs()[0]; let receiver_ty = wfcx.normalize(span, None, receiver_ty); <ins> // If the receiver already has errors reported, consider it valid to avoid // unnecessary errors (#58712). if receiver_ty.references_error() { return Ok(()); } </ins> if tcx.features().arbitrary_self_types { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled.

<!-- 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: let filename = "tests/parser/unclosed-delims/issue_4466.rs"; assert_parser_error(filename); } <ins> #[test] fn crate_parsing_stashed_diag() { // See also https://github.com/rust-lang/rust/issues/121450 let filename = "tests/parser/stashed-diag.rs"; assert_parser_error(filename); } </ins>

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- 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</details
I suspect this is related to cc
tests/ui/suggestions/unnamable-
Very likely. I'll take a look soon.
For the record: it was that caused this.


Question: <ins> #![feature(external_doc)] #![crate_name = "foo"] // @has foo/struct.Example.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n    .first()n    .second()n    .build();Z' /// ```rust /// let example = Example::new() ///     .first() #[cfg_attr(not(feature = "one"), doc = "    .second()")] ///     .build(); /// ``` pub struct Example; // @has foo/struct.F.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n    .first()n    .another()n    .build();Z' ///```rust ///let example = Example::new() ///    .first() #[cfg_attr(not(feature = "one"), doc = "    .another()")] ///    .build(); /// ``` pub struct F; // @has foo/struct.G.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n.first()n    .another()n.build();Z' ///```rust ///let example = Example::new() ///.first() #[cfg_attr(not(feature = "one"), doc = "    .another()")] ///.build(); ///``` pub struct G; // @has foo/struct.H.html // @has - '//div[@class="docblock"]/p' 'no whitespace lol' ///no whitespace #[doc = " lol"] pub struct H; // @has foo/struct.I.html // @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!Z' ///     4 whitespaces! #[doc = "something"] pub struct I; // @has foo/struct.J.html // @matches - '//div[@class="docblock"]/p' '(?m)anno whitespacenJust some text.Z' ///a ///no whitespace #[doc(include = "unindent.md")] pub struct J; // @has foo/struct.K.html // @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!Z' ///a /// ///    4 whitespaces! /// #[doc(include = "unindent.md")] pub struct K; </ins>

<!-- 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. --I tried this code: /// let example = Example::new() /// .first("hello") #[cfgattr(not(feature = "one"), doc = " .second("hello")n")] /// .third("hello") /// .build(); /// with I expected to see this: ! Instead, this happened: ! <!-- 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. --: running over the code gives me /// let example = Example::new() /// .first("hello") /// .second("hello") /// .third("hello") /// .build(); ///
As explained on discord, <strikethe attributes aren't applied to doc comments</strike(EDIT: they are applied, the problem seems to be that it results in two doc comments for rustdoc). However, your doc comment is split in two so the second half isn't considered as being inside a code block, explaining why you have this display. Even if shows it as one doc comment, rustdoc sees two of them. <strikeMaybe we should add a warning or something that attributes aren't applied to doc comments... What do you think ?</strike
How can an attribute get applied to a doc comment? Both are, under the hood, attributes, no? I would expect that to be equivalent to expecting to only derive Debug if is passed, which is not how that works. I'm guessing what is true is that attributes directly written don't actually merge with -style comments. Potentially relevant: , ,
Simplified reproducer rust //! foo(); #![doc = " bar();"] //! Checking with 1.31.0 it still ignores it (so likely not related), but checking with 1.21.0 (and 1.0.0) it worked as expected, so somewhere within that range (but I don't have any other versions installed at the moment to check).
Compilation broke somewhere between 1.23.0 (works) 1.24.0 (does not work) I tested it with rust //! let x = r#" #![doc = " bar();"] //! "#; //! assert_eq!


Question: <ins> #![feature(external_doc)] #![crate_name = "foo"] // @has foo/struct.Example.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n    .first()n    .second()n    .build();Z' /// ```rust /// let example = Example::new() ///     .first() #[cfg_attr(not(feature = "one"), doc = "    .second()")] ///     .build(); /// ``` pub struct Example; // @has foo/struct.F.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n    .first()n    .another()n    .build();Z' ///```rust ///let example = Example::new() ///    .first() #[cfg_attr(not(feature = "one"), doc = "    .another()")] ///    .build(); /// ``` pub struct F; // @has foo/struct.G.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n.first()n    .another()n.build();Z' ///```rust ///let example = Example::new() ///.first() #[cfg_attr(not(feature = "one"), doc = "    .another()")] ///.build(); ///``` pub struct G; // @has foo/struct.H.html // @has - '//div[@class="docblock"]/p' 'no whitespace lol' ///no whitespace #[doc = " lol"] pub struct H; // @has foo/struct.I.html // @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!Z' ///     4 whitespaces! #[doc = "something"] pub struct I; // @has foo/struct.J.html // @matches - '//div[@class="docblock"]/p' '(?m)anno whitespacenJust some text.Z' ///a ///no whitespace #[doc(include = "unindent.md")] pub struct J; // @has foo/struct.K.html // @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!Z' ///a /// ///    4 whitespaces! /// #[doc(include = "unindent.md")] pub struct K; </ins>

(x, "n bar();n"); //!
They are not supposed to be applied to a doc comment I do not think that. Your example would make sense for which I also consider to be wrong, but I am talking about which should insert the attribute conditionally but that is not the point. It might help to illustrate my thought process; We have some kind of documented item: rust /// let example = Example::new() /// .first() /// .build(); /// and each of those is turned into a doc attribute rust"] #[doc = "let example = Example::new()"] #[doc = " .first()"] #[doc = " .build();"] #[doc = " In a later step those attributes would then be concatenated and parsed as markdown or whatever. I want to use this behavior to document items conditionally, depending on which features the crate user has enabled. One way to do this would be to do rust let example = Example::new() .first() .build(); rust let example = Example::new() .first() .second() .build(); but that would blow up the source code with many duplicate lines, where only some minor things were changed. So I thought that it might make more sense to conditionally include a doc comment like this: rust /// let example = Example::new() /// .first() #[cfgattr(feature = "one", doc = " .second()")] /// .build(); /// which would turn into rust"] #[doc = "let example = Example::new()"] #[doc = " .first()"] #[doc = " .second()"] #[doc = " .build();"] #[doc = " or rust"] #[doc = "let example = Example::new()"] #[doc = " .first()"] #[doc = " .build();"] #[doc = " depending on whether the feature is enabled. So the attribute should not be inserted and not applied to the following doc comment. The weird thing is that the manually expanded version is working as expected. rust"] #[doc = "let example = Example::new()"] #[doc = " .first()"] #[cfg_attr(feature = "one", doc = " .second()")] #[doc = " .build();"] #[doc = " but this is very unhandy to work with :/
I was randomly looking at passes for another reason and noticed what is likely the source of this issue.


Question: <ins> #![feature(external_doc)] #![crate_name = "foo"] // @has foo/struct.Example.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n    .first()n    .second()n    .build();Z' /// ```rust /// let example = Example::new() ///     .first() #[cfg_attr(not(feature = "one"), doc = "    .second()")] ///     .build(); /// ``` pub struct Example; // @has foo/struct.F.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n    .first()n    .another()n    .build();Z' ///```rust ///let example = Example::new() ///    .first() #[cfg_attr(not(feature = "one"), doc = "    .another()")] ///    .build(); /// ``` pub struct F; // @has foo/struct.G.html // @matches - '//pre[@class="rust rust-example-rendered"]'  //     '(?m)let example = Example::new()n.first()n    .another()n.build();Z' ///```rust ///let example = Example::new() ///.first() #[cfg_attr(not(feature = "one"), doc = "    .another()")] ///.build(); ///``` pub struct G; // @has foo/struct.H.html // @has - '//div[@class="docblock"]/p' 'no whitespace lol' ///no whitespace #[doc = " lol"] pub struct H; // @has foo/struct.I.html // @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!Z' ///     4 whitespaces! #[doc = "something"] pub struct I; // @has foo/struct.J.html // @matches - '//div[@class="docblock"]/p' '(?m)anno whitespacenJust some text.Z' ///a ///no whitespace #[doc(include = "unindent.md")] pub struct J; // @has foo/struct.K.html // @matches - '//pre[@class="rust rust-example-rendered"]' '(?m)4 whitespaces!Z' ///a /// ///    4 whitespaces! /// #[doc(include = "unindent.md")] pub struct K; </ins>

There are two relevant passes: runs second and removes leading columns of whitespace from the docs. This runs on a single "doc fragment" at a time, because of merging that normally means the entire documentation string, but since sugared and raw docs aren't merged they remain as separate fragments and use their own widths of leading whitespace to strip.
That also matches up with first released in 1.24 which introduced this distinction between doc kinds in order to fix , which IMO was user error in not matching the indent depth.


Question: #![crate_name = "foo"] // @has foo/fn.f.html <del> // @has - '//*[@class="rust fn"]' 'pub fn f(0u8 ...255: u8)' </del> <ins> // @has - '//*[@class="rust fn"]' 'pub fn f(_: u8)' </ins> pub fn f(0u8...255: u8) {}

Rustdoc on [nightly documents][1] methods have signature of as while it only has to document it as . ! On [rustdoc stable][2], things are normal: ! : Version 1.49.0 ( 2020-12-29) [1]: [2]:
I'd like to investigate this :)
searched nightlies: from nightly-2020-12-29 to nightly-2021-01-22 regressed nightly: nightly-2021-01-09 searched commits: from to regressed commit: This regressed in , so this is probably caused by
This also affects Where will generate:
So a few observations: which displays mutability in patterns, causing to be displayed the mechanism for detecting and eliding works by , but as returns instead of , the comparison fails and displays the type.
I see two path to solving this bug: an option for to not display the mutability in patterns revert cc what do you think?
I would prefer to go for 1, there's no reason to have two completely different functions for pretty-printing.
Assigning and removing as in the prioritization working group.
(now a beta regression)


Question: } // Empty groups `a::b::{}` are turned into synthetic `self` imports <del> // `a::b::c::{self as _}`, so that their prefixes are correctly </del> <ins> // `a::b::c::{self as __dummy}`, so that their prefixes are correctly </ins> // resolved and checked for privacy/stability/etc. if items.is_empty() && !empty_for_self(&prefix) { let new_span = prefix[prefix.len() - 1].ident.span;

The error happens on latest stable and nightly. Steps to reproduce: ; : : returns error: The error only happens if the module is named (for instance, and work without error). The error is not produced if doesn't use in any way. If doesn't contain imports but uses the library directly (e.g. ), the error is produced. always succeeds. I don't know if this is supposed to be forbidden but the error message seems to be misleading.
The second instance is injected implicitly. The error could be better, yes.
Where exactly is injected - in the library or in the test? Why does the library work on its own? Why does conflict with in the test?
Ok, it turns out this is a legitimate bug, I misinterpreted it as a more commonly reported diagnostic issue. is injected into both the library and the test, but only the first one causes the error. If you set in , then you'll see the error immediately while compiling - conflicts with . On 2018 edition, however, is injected in more subtle way, as where is some unique symbol that still has the string representation , but doesn't clash with anything in the same crate. Unfortunately, turns into "just " after encoding into metadata in the compiled library (this is the bug). So, when we load that library from the test it looks like the library defines two conflicting items.
The solution is to either encode gensyms/hygiene into metadata properly (this is a large task and a long standing issue), or come up with some hack preventing the injected specifically from being encoded (it doesn't really need to be encoded).
Fixed in


Question: <ins> // error-pattern: requires `generator` lang_item #![feature(no_core, lang_items, unboxed_closures)] #![no_core] #[lang = "sized"] pub trait Sized { } #[lang = "fn_once"] #[rustc_paren_sugar] pub trait FnOnce<Args> { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } pub fn abc() -> impl FnOnce(f32) { |_| {} } fn main() {} </ins>

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


Question: "num_cpus", "ordslice", "racer", <del> "rand 0.7.3", </del> <ins> "rand 0.8.4", </ins> "rayon", "regex", "rls-analysis",

Hello, this is your friendly neighborhood mergebot. After merging PR rust-lang/rust, I observed that the tool rls no longer builds. A follow-up PR to the repository is needed to fix the fallout. cc do you think you would have time to do the follow-up work? If so, that would be great!
This might be due to no longer builds: ` We need a new version I think. The last published version of is 5 months old already :thinking: Can you please check why there are no new versions being published?
TIL scheduled GitHub Action Workflows apparently require regular activity in the repository to keep going :eyes:
I didn't realize anyone was still using those crates so I disabled the action, I believe it was broken anyway. Does rustfmt and/or other crates still use those packages? If so I can try to find time to restart the action.
Racer those crates. And RLS . So without those crates compiling racer with the latest nightly isn't possible, which makes compiling RLS impossible and therefore blocks the sync of RLS back to rust-lang/rust.
Would it maybe be an option to make racer depend on to compile instead of publishing AP crates?
We stopped using them in rustfmt a while ago and I can't imagine a scenario where we'd switch back. Agreed on racer, which AIUI is the last true direct consumer of those crates. However, it's also in and those crates only get bumped in racer when a racer consumer needs them to be bumped.
Ah ok. In that case if this is purely for something in maintenance mode I think my own personal tenure in maintaining these crates is over with, so I would prefer to hand over the reins to someone else. Would someone be willing to volunteer to take over these crates?
let's sync up on #t-infra on Zulip -- I think it makes sense to move these crates into infra control/publication.
Let's wait if Racer can move over to rustc-dev racer-rust/racer. If so, there shouldn't be a need to keep maintaining rustc-ap crates at all. Looking at the dependents on , there really is only , the crates themselves and (which by now uses ).
has some relevant considerations as well.


Question: "num_cpus", "ordslice", "racer", <del> "rand 0.7.3", </del> <ins> "rand 0.8.4", </ins> "rayon", "regex", "rls-analysis",

One way or another I think the AP crates need to be accounted for as per the accepted RFC, though it certainly would be a simpler story if they no longer need to be updated/published
Happy to coordinate as necessary, just let me know!
Over a month now. Is this gonna be fixed?
it's blocked on


Question: pub mod c_str; pub mod os; pub mod path; <ins> pub mod path2; </ins> pub mod rand; pub mod run; pub mod sys;

and all interfaces directly with the file-system should probably use rather than trying to coerce to handle these cases. (Similar issue to .)
nominating feature-complete
Accepted for backwards-compatible
My last referenced commit is a month old, but I'm still working on this issue (currently finishing up the support for Windows paths).
The issues here of dealing with filesystems that are not utf8 seem related to , at least tangentially.


Question: <ins> error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-93647.rs:2:5 | LL |     (||1usize)() |     ^^^^^^^^^^^^ error: aborting due to previous error For more information about this error, try `rustc --explain E0015`. </ins>

Const generic defaults are being stabilized, <!-- 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</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Seems to also happen with closures:
I got a fix for this one I think. claim
even worse, this compiles on beta but shouldn't
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-critical
I think this needs to remain open until the fix is beta-backported :thinking: not 100% sure on procedure here
You might be correct. At least that's what happened last time one of my PRs was backport nominated (), though I'm not sure if that was due to that being a regression on stable. Regardless, thanks for reopening this.
that's my understading, too. I /think/ issues that are pending a beta/stable backport (like this one) will stay open until the corresponding backport PR has landed. The {stable,beta}-backport procedure is detailed but this detail is not explicited (I'll see if I can fix that to be more clear). For completeness, backports are discussed every Thursday during the compiler team weekly meeting (). Anyway, thanks a lot for fixing this issue and also to + for reporting and debugging :)
Copied from Zulip: Question/thought: Is this a case where tracking bound vars got in the way? Or did it actually help uncover a potential bug?
Not sure what you mean. The bug was that we were just not doing lifetime name resolution at all on const generic defaults. Like this code compiles on beta: edit: ohhh, you mean ?


Question: <ins> error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-93647.rs:2:5 | LL |     (||1usize)() |     ^^^^^^^^^^^^ error: aborting due to previous error For more information about this error, try `rustc --explain E0015`. </ins>

Yeah I think in this case it helped uncover the bug, because of the fact it ICEd and showed us we weren't resolving the closure default.
I guess this example shows that this did help us uncover a bug, but kind of indirectly: This just didn't uncover a case where "lost" bound vars.
this is now fixed on beta


Question: match self.find_library_crate() { Some(t) => t, None => { <ins> self.sess.abort_if_errors(); </ins> let message = match root_ident { None => format!("can't find crate for `{}`", self.ident), Some(c) => format!("can't find crate for `{}` which `{}` depends on",

Built glfw-rs using rust 0.10-pre. When referencing this crate in another source file and building, I get error: internal compiler error: unexpected failure This message reflects a bug in the Rust compiler. We would appreciate a bug report: note: the compiler hit an unexpected failure path. this is a bug Ok(task 'rustc' failed at 'assertion failed: ()', ) This is on OSX 10.9: rustc 0.10-pre ( 2014-02-18 10:16:48 -0800) host: x8664-apple-darwin
This means that you've got two versions of the same lying around, and doesn't like having two versions. This will be fixed by , I just need to land it :(
I have just build the library for the first time, and I can only find one dylib for it on my system (next to the rlib, but I gues that shouldn't cause any problems). Is there another possibility for this error? Gesendet: Mittwoch, 19. Februar 2014 um 01:09 UhrVon: "Alex Crichton" : mozilla/rust hhildebr : Re: [rust] Compiler error when referencing crate "glfw-rs" () This means that you've got two versions of the same libglfw- lying around, and rustc doesn't like having two versions. This will be fixed by , I just need to land it :( — Reply to this email directly or view it on GitHub.
my reading of is that having a dylib and an rlib simultaneously is a problem.
Having a dylib and an rlib simultaneously should not be a problem, it is in fact quite common. Having 2 dylibs and 1 rlib or 2 rlibs and 1 dylib however is a problem.
sorry, my mistake in parsing the title of .
Yes, indeed, I had several identical dylibs, but it wasn't the glfw-rs.. there were rust libs in /usr/local/lib and /usr/local/lib/rustlib/... Thanks! Gesendet: Mittwoch, 19.


Question: match self.find_library_crate() { Some(t) => t, None => { <ins> self.sess.abort_if_errors(); </ins> let message = match root_ident { None => format!("can't find crate for `{}`", self.ident), Some(c) => format!("can't find crate for `{}` which `{}` depends on",

Februar 2014 um 17:15 UhrVon: "Alex Crichton" : mozilla/rust hhildebr : Re: [rust] Compiler error when referencing crate "glfw-rs" () Having a dylib and an rlib simultaneously should not be a problem, it is in fact quite common. Having 2 dylibs and 1 rlib or 2 rlibs and 1 dylib however is a problem. — Reply to this email directly or view it on GitHub.
so can we close this ticket now, in that case? Or do you want to wait for alexcrichton's patches to land, and see what things look like for you then?
Nono, the ticket can be closed for now. Thanks for your help! Gesendet: Mittwoch, 19. Februar 2014 um 21:30 UhrVon: "Felix S Klock II" : mozilla/rust hhildebr : Re: [rust] Compiler error when referencing crate "glfw-rs" () so can we close this ticket now, in that case? Or do you want to wait for alexcrichton's patches to land, and see what things look like for you then? — Reply to this email directly or view it on GitHub.


Question: #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn modified(&self) -> io::Result<SystemTime> { <del> Ok(SystemTime::from(self.stat.st_mtim)) </del> <ins> SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64) </ins> } #[cfg(not(any(

Compiling project with causes the following compilation error: See this .
cc target maintainer
I guess has the same issue? This got broken by ("unix time module now return result") which dropped I guess the way forward is to make use instead. I'm wondering if there is a way to make sure that this kind of breakage doesn't happen before a rustc release?
Our platform support policy is to avoid blocking PRs on whether tier 3 platforms build, because tier 3 platforms are not required to build.
Sure, I'm not saying to block PRs, but I'm wondering about somehow getting notified quickly enough to be able to react before a rustc release.
(as in: getting the break notice from a getrandom CI build a dozen days after the merge does not look that robust)
Hm. Does the Rust compiler for hurd get built from a stable or beta branch of rustc? My understanding was that tier 3 targets generally used the nightly compiler in any case.
In Debian we will use the stable releases to compile all rust-needing Debian packages, as the Debian policy requires.
The breaking commit is not in the current 1.77 release but is in the 1.78 beta. It will not be in a stable release for another 5 weeks-ish. Would you like your PR that fixes it to be beta-nominated, so that it gets backported and is in the stable release of 1.78?
Yes, please.
I recommend you set up a daily/weekly job on your side building master to check for regressions. ( may fix this)


Question: let result = match e.node { hir::ExprUnary(hir::UnNeg, ref inner) => { // unary neg literals already got their sign during creation <del> match inner.node { hir::ExprLit(ref lit) => { use syntax::ast::*; use syntax::ast::LitIntType::*; const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; match (&lit.node, ety.map(|t| &t.sty)) { (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { return Ok(Integral(I8(::std::i8::MIN))) }, (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { return Ok(Integral(I16(::std::i16::MIN))) }, (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { return Ok(Integral(I32(::std::i32::MIN))) }, (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { return Ok(Integral(I64(::std::i64::MIN))) }, (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | (&LitKind::Int(n, Signed(IntTy::Is)), _) => { match tcx.sess.target.int_type { IntTy::I16 => if n == I16_OVERFLOW { return Ok(Integral(Isize(Is16(::std::i16::MIN)))); }, IntTy::I32 => if n == I32_OVERFLOW { return Ok(Integral(Isize(Is32(::std::i32::MIN)))); }, IntTy::I64 => if n == I64_OVERFLOW { return Ok(Integral(Isize(Is64(::std::i64::MIN)))); }, _ => bug!(), } }, _ => {}, } }, hir::ExprUnary(hir::UnNeg, ref inner) => { // skip `--$expr` return eval_const_expr_partial(tcx, inner, ty_hint, fn_args); }, _ => {}, </del> <ins> if let hir::ExprLit(ref lit) = inner.node { use syntax::ast::*; use syntax::ast::LitIntType::*; const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; match (&lit.node, ety.map(|t| &t.sty)) { (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { return Ok(Integral(I8(::std::i8::MIN))) }, (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { return Ok(Integral(I16(::std::i16::MIN))) }, (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { return Ok(Integral(I32(::std::i32::MIN))) }, (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { return Ok(Integral(I64(::std::i64::MIN))) }, (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | (&LitKind::Int(n, Signed(IntTy::Is)), _) => { match tcx.sess.target.int_type { IntTy::I16 => if n == I16_OVERFLOW { return Ok(Integral(Isize(Is16(::std::i16::MIN)))); }, IntTy::I32 => if n == I32_OVERFLOW { return Ok(Integral(Isize(Is32(::std::i32::MIN)))); }, IntTy::I64 => if n == I64_OVERFLOW { return Ok(Integral(Isize(Is64(::std::i64::MIN)))); }, _ => bug!(), } }, _ => {}, } </ins> } match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { Float(f) => Float(-f),

This is clearly ridiculous, but rustc is perfectly happy with it. Regression from 1.9.
prints . Using the constant in any other way, e.g. errors out:
cc is that fallout from your new const eval?
I haven't removed anything, not that I can think of, to cause this.
Then it's very likely fallout from (skipping double negations)
The remaining error in that testcase feels wrong. should, IMO, be - the literal is in range, but the negation overflows.
Actually I think it should be valid code, but yield , at least that's what the original literal out of range lints do
But overflows when negating, which is an error. Why should it be different than ?
I have no particular opinion on this. But the lint has code handling double negations: (it's treating double negations as if they weren't there at all)
The double negation is not the issue here. The value of evaluates to , as expected. But consider the following code: This will also compile just fine and print . It goes wrong in the cast . Rust doesn't check if cast overflows, so the value becomes .  can be changed to disallow casts that fail. (I'd be happy to implement this myself.) Or we can accept that these casts are can overflow silently.
I believe the issue is that --128 (aka 128) is an intermediate result of the computation that is out of bounds for the i8. EDIT: The issue is about the fact that the compiler doesn't complain.
jup, that was a misunderstanding of some code on my part + the issue that processing HIR works the wrong way around (you start with the outer most expression). Reverting should do the job
I thought that it was intended that would succesfully evaluate to . (That rustc knows that it's overflowing, but is smart to know that double negation will fix it in the end.) Pretend I said nothing.


Question: fn poll_write_vectored( self, cx: &mut Option<String>,  bufs: &[usize]   bufs: &[usize],  ) -> Option<Result<usize, Error>> { ... } }  No newline at end of file

Take a look at the docs for : Rustdoc is making good choices for whether to wrap the declarations ! But when it wraps, it doesn't include a trailing comma on the last parameter. I think it should, because the default style guide wants a comma there. (And rustdoc should continue not putting a trailing comma when the declaration is shown as a single line.) <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

The following code fails on stable: When compiled in release mode, the assert is optimized out by LLVM even though it checks the exact same condition as the other assert, as can be verified by testing in debug mode. Note that it's theoretically possible for the stack to be aligned correctly such that the bug is suppressed, but that's not likely. The 256's can be replaced with larger alignments if that happens. The bug is caused by the impl of copying to the stack with the default alignment of 16. ()
and seem related
This is a soundness hole.
So... I guess the problem is that the that rustc emits for the unsized local doesn't use ? That's... kind of bad, because it doesn't look like even supports dynamically setting the alignment: If this is correct, the issue should be renamed to something like "unsized locals do not respect alignment".
A way to fix this would be to change the ABI for dynamic trait calls that take by value to always pass by address. When the trait object is created is where the trampoline function would be generated, so there is no additional cost for static calls.
This can also be fixed by not allowing dynamically-sized local variables with an alignment more than some maximum value and having all dynamically-sized locals use that maximum alignment unless optimizations can prove that a smaller alignment suffices.
Messing with the ABI wouldn't help with unsized locals in general (assuming is correct), since e.g. will also need an alloca with dynamic alignment in general. Given only a value, there is no static way to say anything about its alignment, so how would you distinguish whether calling a method on it is OK?
Can we call and then align the pointer for the local ourselves as a workaround until we come up with a good solution?
In clang there's a function which might or might not be useful in this case.
requires a constant alignment. Non constant alignments are . This matches semantics of LLVM instruction, so it's not helping, as alignment of value in is unknown at compile time when moving from .
I think that overallocating for unsized locals of unknown alignment may make sense. You can and then make use of to compute the offset. Sure, it increases stack requirements, but it seems acceptable for , and in most cases you end up with extra 7 bytes on stack or less. 256 alignment seems like an edge case where wasting 255 bytes doesn't matter.


Question: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

if we keep setting as the default alignment we can skip the overallocating and offset dance for types with an alignment below that.
My idea was that rustc would prohibit coercing overaligned types to a dyn trait that takes by value. So:
The alignment is dynamically determined though, not sure if saving 15 bytes of stack space is worth the conditional branch?
Oh right. Yea that's probably not helpful.
Since , this would be backwards incompatible (at latest) once trait object upcasting is finally implemented: and trait objects would have to have the same alignment restriction (because you can upcast to ), but today you can freely create such objects with any alignment.
I was under the impression that calling didn't require dynamic , is that related to missing MIR optimizations, meaning we have unnecessary moves which end up duplicating the data on the stack using a dynamic ?
Correctness shouldn't rely on optimizations to fire...
Sure, I was just hoping we weren't relying on "unsized locals", only unsized parameters (i.e. ), for what we're exposing as stable. And I was hoping an optimization wouldn't need to be involved to get there. I wonder if it would even be possible to restrict "unsized locals" to the subset where we can handle it entirely through ABI, and not actually have dynamic s anywhere, since that would make me far more comfortable with 's implementation or even stabilization. Ironically, if that works, it's also the subset we could've implemented years earlier than we did, since most of the complexity, unknowns (and apparently bugs) are around dynamic s, not calling trait object methods on a dereference of .
That should be possible. I think everything that is necessary is performing the deref of the box as argument () instead of moving the box contents to a local first () That would also make it possible to call in cg_clif. Cranelift doesn't have alloca support, so the current MIR is untranslatable.
Hmm, but that's not trivially sound because it could lead to MIR calls where argument and return places overlap, which is UB. We'd potentially have to special-case it to derefs, but even then what's to stop someone from doing ? Maybe we could introduce a temporary for the return value instead, for these kinds of virtual calls? That should remove any potential overlap while allowing the call.


Question: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

(Unrelatedly, I just realize we use a copying-out shim for vtable entries that take by value, even when would be passed as at the call ABI level. We would probably have to make computing the call ABI a query for this microopt to not be expensive)
That would result in being moved to a temp first before dropping and calling the boxed closure. If it wasn't moved first before the drop of , then borrowck would give an error. (I meant for this change to be done at mir construction level, not as an optimization pass, so borrowck should catch any soundness issues)
We can try it, I guess, but right now a lot relies on many redundant copies/moves being created by MIR building and may not catch edge cases like this. But also I don't think moving out of a moves the itself today. Me too, but I was going with the "correct by construction" approach of creating a redundant copy/move, just on the return side, instead of the argument side, of the call.
After revisiting on triage, removing nomination.
pre-triage: nominated for discussion in the next weekly meeting.
I just checked and, a function call roughly this (touched up for clarity): Some of my previous comments assumed the wasn't there and the call would use the destination directly, but given that there is a move, that simplifies my suggestion. <hr/For virtual by-value calls, we can skip one move when building the MIR, specifically the move out of the dereference of a for the argument. Given that we already move the result of the call, there should be no aliasing caused by this, but if we decide to change anything about how we build MIR calls, we'd need to be extra careful. We can also make this pattern be gated by a separate feature-gate (rather than ), and make sure the standard library only uses that feature-gate and not . This should solve any alignment issues might have, because we'd not be using dynamic unless the broader feature is used.
OK, if I understand what's being proposed here, it is to excerpt a subset of the "original unsized-locals plan" -- specifically, to permit locals with unsized types, but only in contexts where we can be guaranteed that we can point to the original storage and don't actually have to move any value (and hence we don't require variable size stack frames).


Question: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

I'm in favor of this proposal, but I do think we want to be slightly careful to ensure we're not violating soundness. The main concern would be if there is some way to access or re-use the variable that was moved. I attempted to do so with this example () but it fails to compile: The error here arises because the closure would need to capture a to do anything, which prevents a later move. But maybe there is some kind of tricky example that can arise where we re-assign the value during argument evaluation?
compiles and does before , where is the result of .
Borrowck should prevent that, right?
borrowck may rely on MIR building creating extraneous copies, so we can't just assume it helps us. IMO we should limit it to functions taking unsized parameters and function calls passing such parameters or dereferences of es (any other pointer/reference doesn't support moving out of).
Well, I think is right that borrowck would catch violations of soundness in some strict sense, but I guess what I meant is that we might be breaking backwards compatibility.
The example that feels pretty relevant. If I understood your proposal, it would no longer compile. If I recall (thinking back), I had a plan to handle this by save the to an alternate location in the actual call, we pass ownership of and then do a shallow free of the This still seems like it would work, though I'm not sure how easy/elegant it is to formulate. In a sense we'd be rewriting to .
Isn't example dependent on doing a direct virtual call? My understanding is that you can't do this on stable with because the virtual call exists in one place, in libstd, and it doesn't do anything weird, so it would work with a restricted ruleset. EDIT: if it can work on stable, it's because calling 's will move the whole before the assignment is evaluated, which is fine, because the shallow drop is actually inside that , not its caller.
I agree that this code doesn't compile on stable today, but I'm not sure if that's the point. I guess you're saying it's ok for it to stop compiling? I think what I would like is that our overall behavior is as consistent as possible between Sized and Unsized parameters. I think we could actually do a more general change that doesn't special case Sized vs Unsized or anything else.


Question: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

I think I am basically proposing the same thing as earlier, but with a twist: Today, when building the parameters, we introduce a temporary for each parameter. So if we had we might do: What I am saying is that we could say: If the argument is moved (not copied), and the "place" has outer derefs (e.g., we are passing where is some place), then we assign the place to a temporary and we make the argument to the function be : I don't believe this is observable to end-users, except potentially for when the destructor on runs. I believe that it accepts all the same code we used to accept. It also has nothing specific to or types at all. Does that make sense? I'm very curious to know if anyone sees any problems with it. (One obvious thing: if we ever add , its design would have to accommodate this requirement, but I think that's fine, in fact the complications around getting moves right for precisely this case are one of the reasons we've held off on thus far.)
Can you not reinitialize today? If you move the whole , it is indeed more conservative (and should let us skip unnecessary moves even in cases). But also, do you want to move the locals check from typeck to borrowck? I don't have an intuition for when your approach wouldn't create unsized MIR locals, from the perspective of typeck. However, this is only relevant if we want a stricter feature-gate. At the very least it seems like it would be easier to implement a change only to MIR building, and it should fix problems with for the time being, even without a separate feature-gate.
Hmm, that's a good point, I think do that. Sigh. I knew that seemed too easy. I remember we used to try and prevent that, but we never did it fully, and in the move to NLL we loosened those rules back up, so this compiles: Still, you could do my proposal for unsized types, though it would introduce an incongruity. UPDATE: Oh, wait, I remember now. For unsized types, reinitialization is not possible, because you can't do with an unsized rvalue (we wouldn't know how many bytes to move). So in fact there isn't really the same incongruity.


Question: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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: use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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: <ins> // The problem in #66357 was that the call trace: // // - parse_fn_block_decl // - expect_or // - unexpected // - expect_one_of // - expected_one_of_not_found // - recover_closing_delimiter // // ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`. fn f() { |[](* } //~^ ERROR expected one of `,` or `:`, found `(` //~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` </ins>

When compiling a personal project, I got an error that the compiler panicked and entered unreachable code. I've dumped the output: And I committed my code which caused the bug here: It might be because I had only written half of an anonymous function at at line 92. This is not that urgent as I only saw it with half-written code, but since the compiler suggested I file a bug I did. :
Good call! Reducing it to is enough to trigger the ICE. <details<summarybacktrace </summary
modify labels: I-ICE T-compiler C-bug A-frontend
I've traced the problem down to this call:
triage: P-high, removing nomination label.


Question: <ins> const QUERY = 'MyForeignType::my_method'; const EXPECTED = { 'others': [ // Test case for https://github.com/rust-lang/rust/pull/96887#pullrequestreview-967154358 // Validates that the parent path for a foreign type method is correct. { 'path': 'foreign_type_path::aaaaaaa::MyForeignType', 'name': 'my_method' }, ], }; </ins>

There are bad (404) links in search results with nightly rustdoc. E.g. go to and then click the result. This leads to which does not exist. Cc
Actually, this issue seems to exist even on stable -- somehow it went unnoticed for quite a while, it seems.
I think it's because we are badly handling a reexport/type alias.
I think this is a duplicate of


Question: Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred) })); <del> if ocx.select_all_or_error().is_empty() { </del> <ins> if ocx.select_all_or_error().is_empty() && count > 0 { </ins> diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), "dereference the return value",

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


Question: Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred) })); <del> if ocx.select_all_or_error().is_empty() { </del> <ins> if ocx.select_all_or_error().is_empty() && count > 0 { </ins> diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), "dereference the return value",

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


Question: #![forbid(dead_code)] #[derive(Debug)] <del> pub struct Whatever { //~ ERROR struct `Whatever` is never constructed </del> <ins> pub struct Whatever { </ins> pub field0: (), <del> field1: (), </del> <ins> field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read </ins> field2: (), field3: (), field4: (),

The struct is meant to not be constructible. Also the behavior is incoherent between tuple structs (correct behavior) and named structs (incorrect behavior). Also, this is a regression, this didn't use to be the case. No response No response
label +F-never_Type +D-inconsistent
We will also get such warnings for private structs with fields of never type (): The struct is never constructed although it is not constructible. This behavior is expected and is not a regression. Did you meet any cases using this way in real world? For the incoherent behavior, we also have: This because we only skip positional ZST (PhantomData and generics), this policy is also applied for never read fields:
Can you elaborate in which sense it is expected? I can understand that it is expected given the current implementation of Rust. It seems between stable and nightly a new lint was implemented. This lint is expected for inhabited types. However it has false positives on inhabited types, i.e. types that are only meant for type-level usage (for example to implement a trait). I agree we should probably categorize this issue as a false positive of a new lint rather than a regression (technically). Thanks, I can see the idea behind it. I'm not convinced about it though, but it doesn't bother me either. So let's just keep this issue focused on the false positive rather than the inconsistent behavior.
How do you think about private structs with fields of never type?
I would consider it the same as public structs, because they can still be "constructed" at the type-level. So they are dynamic dead--code but not dead-code since they are used statically. It would be dead-code though if the type is never used (both in dynamic code and static code, i.e. types).
Actually, thinking about this issue, I don't think this is a false positive only for the never type. I think the whole lint is wrong. The fact that the type is empty is just a proof that constructing it at term-level is not necessary for the type to be "alive" (aka usable). This could also be the case with non-empty types. A lot of people just use unit types for type-level usage only (instead of empty types).


Question: #![forbid(dead_code)] #[derive(Debug)] <del> pub struct Whatever { //~ ERROR struct `Whatever` is never constructed </del> <ins> pub struct Whatever { </ins> pub field0: (), <del> field1: (), </del> <ins> field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read </ins> field2: (), field3: (), field4: (),

So my conclusion would be that linting a type to be dead-code because it is never constructed is brittle as it can't be sure that the type is not meant to be constructed at term-level (and thus only used at type-level). Adding is not a solution because if the type is actually not used at all (including in types) then we actually want the warning. Here is an example: The same thing with a private struct: And now actual dead code:
I think a better way is: is usually used to do such things like just a proof. Maybe we can add a help for this case.
But I agree that we shouldn't emit warnings for pub structs with any fields of never type (and also unit type), this is an intentional behavior.
Oh yes good point. So all good to proceed with adding never type to the list of special types.
Thanks a lot for the quick fix! Once it hits nightly, I'll give it a try. I'm a bit afraid though that this won't fix the underlying problem of understanding which types are not meant to exist at runtime. For example, sometimes instead of using the never type, I also use empty enums such that I can give a name and separate identity to that type. Let's see if it's an issue. If yes, I guess ultimately there would be 2 options: Just use in those cases. Introduce a trait (or better name) for types that are not meant to exist at runtime like unit, never, and phantom types, but could be extended with user types like empty enums. I'll ping this thread again if I actually hit this issue.
I could test it (using nightly-2024-08-01) and . I just had to change a to in a crate where I didn't have already. Ultimately, is going to be a type alias for so maybe it's not worth supporting it. And thinking about empty enums, this should never be an issue for my particular usage, which is to build empty types. Because either the type takes no parameters in which case I use an empty enum directly. Or it takes parameters and I have to use a struct with fields, and to make the struct empty I also have to add a never field. So my concern in the previous message is not an issue for me.


Question: issue_url = gh_url() + '/{}/comments'.format(number) response = urllib2.urlopen(urllib2.Request( issue_url, <del> json.dumps({'body': maybe_delink(message)}), </del> <ins> json.dumps({'body': maybe_delink(message)}).encode(), </ins> { 'Authorization': 'token ' + github_token, 'Content-Type': 'application/json', } )) response.read() <del> except urllib2.HTTPError as e: print("HTTPError: %sn%s" % (e, e.read())) </del> <ins> except HTTPError as e: print("HTTPError: %sn%r" % (e, e.read())) </ins> raise

Updated the toolstate repository at https://rust-lang- currently does not seem to work, see e.g. To "tool failed to build"-issues are being created, either. remarked that the error . Cc


Question: = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) <ins> Future breakage diagnostic: error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:90:20 | LL |         let _ref = &m1.1.a; |                    ^^^^^^^ | note: the lint level is defined here --> $DIR/unaligned_references.rs:1:9 | LL | #![deny(unaligned_references)] |         ^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) Future breakage diagnostic: error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:100:20 | LL |         let _ref = &m2.1.a; |                    ^^^^^^^ | note: the lint level is defined here --> $DIR/unaligned_references.rs:1:9 | LL | #![deny(unaligned_references)] |         ^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) </ins>

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