profile
viewpoint
Felix S Klock II pnkfelix Paris, France

pnkfelix/boxdraw-rs 2

Library for drawing ASCII art rectangles

Manishearth/rust 1

a safe, concurrent, practical language

pnkfelix/BinFiles 1

Little scripts that my ConfigFiles and DotFiles sometimes reference. Meant to be alias of ~/bin/

pnkfelix/ack 0

A replacement for grep for programmers

pnkfelix/ack2 0

ack 2.0

pnkfelix/add3 0

A demo project for illustrating dependency handling in Cargo

pnkfelix/add6 0

Toy crate that depends on past version of add3 crate.

pnkfelix/agents 0

Agent based simulation

pnkfelix/alexa-rs 0

Rust library for building Alexa skills

pull request commentrust-lang/rust

Track devirtualized filenames

@bors p=1

this is a bugfix to a subtle incremental compilation bug that I have seen come up in my own workflow for building rustc itself (ironically, it happened while I was double-checking the intermediate commits of this PR itself were buildable). So I am upping the priority slightly, but not more than the PR's that have also had their priorities increased.

pnkfelix

comment created time in a day

pull request commentrust-lang/rust

Track devirtualized filenames

@bors rollup=never

(this change is subtle and hard to test, and I want to maximize our ability to bisect to it if necessary.)

pnkfelix

comment created time in a day

pull request commentrust-lang/rust

Track devirtualized filenames

@bors r=eddyb

pnkfelix

comment created time in a day

push eventpnkfelix/rust

Felix S Klock II

commit sha a8e4236edc1e118ccb6c3f3a8d0139e4cd90b5b8

add fixme suggested by eddyb

view details

push time in a day

Pull request review commentrust-lang/rust

Track devirtualized filenames

 impl Globals {  scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); +/// FIXME: Perhaps this should not implement Rustc{Decodable, Encodable}+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]+#[derive(HashStable_Generic)]+pub enum RealFileName {+    Named(PathBuf),+    /// For de-virtualized paths (namely paths into libstd that have been mapped+    /// to the appropriate spot on the local host's file system),+    Devirtualized {+        /// `local_path` is the (host-dependent) local path to the file.+        local_path: PathBuf,+        /// `virtual_name` is the stable path rustc will store internally within+        /// build artifacts.+        virtual_name: PathBuf,+    },

Great! I was musing about such a change in my head, so I'm glad to hear you had similar thoughts. I'll add the FIXME; there's already so many others in this PR, another won't hurt.

pnkfelix

comment created time in a day

pull request commentrust-lang/rfcs

Destructuring assignment

@pickfire I'm pretty sure it does, given the desugaring it outlines in the reference section: your code would be desugared to:

let mut a = 1;
let mut b = 2;
{ let (_a, _b) = (b, a); a = _a; b = _b; }
assert_eq!(a, 2);
assert_eq!(b, 1);
varkor

comment created time in 2 days

pull request commentrust-lang/rust

Track devirtualized filenames

I'm going to unilaterally tag this as beta-accepted, based on the conversation in today's T-compiler meeting

However, as noted in my recent chat with @Mark-Simulacrum: please do wait until after this has been reviewed before backporting it into beta and/or stable. I don't want my unilateral beta-backport approval to inadvertently sidestep the review process entirely.

pnkfelix

comment created time in 2 days

pull request commentrust-lang/rust

Track devirtualized filenames

A note on the lack of a regression test for #70924: I don't have a regression test as part of the PR, because I'm not sure how to make one. my local replication relies on either adding/removing the rust-src component in rustup , or actually renaming the rustlib/src/rust subdirectory in my build directory.

(Either of these options don't seem to lend themselves to a test in our infrastructure, no?)

pnkfelix

comment created time in 2 days

pull request commentrust-lang/rust

Track devirtualized filenames

r? @eddyb

pnkfelix

comment created time in 2 days

Pull request review commentrust-lang/rust

Track devirtualized filenames

 fn write_out_deps(             boxed_resolver.borrow().borrow_mut().access(|resolver| {                 for cnum in resolver.cstore().crates_untracked() {                     let source = resolver.cstore().crate_source_untracked(cnum);-                    if let Some((path, _)) = source.dylib {-                        files.push(escape_dep_filename(&FileName::Real(path)));-                    }-                    if let Some((path, _)) = source.rlib {-                        files.push(escape_dep_filename(&FileName::Real(path)));-                    }-                    if let Some((path, _)) = source.rmeta {-                        files.push(escape_dep_filename(&FileName::Real(path)));+                    match source {

(fixed by removing the erroneous refactoring and living with some resulting ugly code duplication.)

pnkfelix

comment created time in 2 days

push eventpnkfelix/rust

Benoît du Garreau

commit sha ef485c6fa97a562b0bc559ffbe38fee9bf1f745b

Impl Error for Infallible

view details

Kevin Per

commit sha dfbc143e65dd4dc8499f7296ddc7889854a8cc7d

Adding if to prevent borrowing suggestion in structs #71136

view details

Kevin Per

commit sha bc29f1d062feeb68207c961d254652d6bff9fd9b

Adding new test #71136

view details

Kevin Per

commit sha d232be80f82b052fd023eb2f4904ccad0aa42d7a

Fix tidy checks

view details

flip1995

commit sha 17d877cce28b22b9b345ec7ef8b14859d8b165c4

Update contributing section about syncing Clippy

view details

Steven Fackler

commit sha 2ce3f85d46edbf5105f2e93d2cbe56ad777b41e6

Tweak and stabilize AtomicN::fetch_update

view details

Philipp Krones

commit sha c1698fedeb69109f9b1aebc0bfccd9bf3112ccad

Apply suggestions from code review Co-authored-by: Phil Hansch <dev@phansch.net>

view details

Vadim Petrochenkov

commit sha 2d10babb71f6658c39279425ec5cda11a28d3af4

Stabilize fn-like proc macros in expression, pattern and statement positions

view details

Steven Fackler

commit sha 31c820552350e3f686a6f353982f0f31ecbaf4a7

Update src/libcore/sync/atomic.rs Co-authored-by: Ralf Jung <post@ralfj.de>

view details

Markus Westerlind

commit sha 1d8489c150df7d0e751f7c438541036df1a9ac5e

perf: Revert accidental inclusion of a part of #69218 This was accidentally included in #69494 after a rebase and given how much `inflate` and `keccak` stresses the obligation forest seems like a likely culprit to the regression in those benchmarks. (It is necessary in #69218 as obligation forest needs to accurately track the root variables or unifications will get lost)

view details

Guillaume Gomez

commit sha 7e855b59151f2e5c2a58fe422a273e997df14b24

Clean up rustdoc source code

view details

Guillaume Gomez

commit sha c8fb0d7ef38957cd2b8f6e5b9b7ea47eaa6cca28

End unification of exit codes in librustdoc

view details

Bastian Kauschke

commit sha a8c152dfc921e8ec2c00f65e7c731197e522a96d

add regression tests + improve method name

view details

Jubilee

commit sha 510fce10f8a22521ec861f4446a304f9a2e4c5bd

Unblock font loading in rustdoc.css rustdoc's font loading defaults to "auto", so browsers may block render. But rustdoc's case prefers a faster TTI for scrolling, this means the strictest font-display in use should be "swap". rustdoc's fonts do provide notable legibility improvements but first-time users will have little trouble reading without. This means "optional" is preferred. The one exception is Source Serif Pro: it's a big difference for body text, so "fallback" is preferred over "optional" to cause a (tiny) block.

view details

Bastian Kauschke

commit sha 3f661d25f9ce3b5ac6139c8d8bf4614b55dca5be

borrowck `DefId` -> `LocalDefId`

view details

Jeremy Fitzhardinge

commit sha ff9646c0adc149dfff194665785f4daa3aa6d9c3

Stabilize process_set_argv0 feature for Unix This stabilizes process_set_argv0 targeting 1.45.0. It has been useful in practice and seems useful as-is. The equivalent feature could be implemented for Windows, but as far as I know nobody has. That can be done separately. Tracking issue: #66510

view details

Vardan Margaryan

commit sha 94e4b5ec316993200d75276b4e7c16a059bf3a57

Add the redundant_wildcard_enum_match lint

view details

Vardan Margaryan

commit sha 0ad9f7d651b52de4be6384c9b6dc893b389fd557

Fix trivial cases of new match_wildcard_for_single_variants lint

view details

Vardan Margaryan

commit sha 494830797744c09d6de3b2b2452ab185d2204005

Fix cases of match_wildcard_for_single_variants lint when it is spanned on Option

view details

Vardan Margaryan

commit sha 749619cfe34be1ee591f3af748fbdd4d2f54d3f0

Apply suggestions from PR review

view details

push time in 2 days

Pull request review commentrust-lang/rust

Track devirtualized filenames

 fn write_out_deps(             boxed_resolver.borrow().borrow_mut().access(|resolver| {                 for cnum in resolver.cstore().crates_untracked() {                     let source = resolver.cstore().crate_source_untracked(cnum);-                    if let Some((path, _)) = source.dylib {-                        files.push(escape_dep_filename(&FileName::Real(path)));-                    }-                    if let Some((path, _)) = source.rlib {-                        files.push(escape_dep_filename(&FileName::Real(path)));-                    }-                    if let Some((path, _)) = source.rmeta {-                        files.push(escape_dep_filename(&FileName::Real(path)));+                    match source {

Oh! I just reaized tha this change was incorrect. (At least, I assume we can have scenarios where the paths here are different, and we need to make multiples calls to files.push!) Sorry!

pnkfelix

comment created time in 2 days

pull request commentrust-lang/rust

Track devirtualized filenames

cc @eddyb @Mark-Simulacrum

pnkfelix

comment created time in 2 days

PR opened rust-lang/rust

Track devirtualized filenames

Split payload of FileName::Real to track both real and virutalized paths.

(Such splits arise from metadata refs into libstd; the virtualized paths look like /rustc/1.45.0/src/libstd/io/cursor.rs rather than /Users/felixklock/Dev/Mozilla/rust.git/src/libstd/io/cursor.rs)

This way, we can emit the virtual name into things like the like the StableSourceFileId (as was done back before PR #70642) that ends up in incremental build artifacts, while still using the devirtualized file path when we want to access the file.

Fix #70924

+130 -47

0 comment

14 changed files

pr created time in 2 days

create barnchpnkfelix/rust

branch : track-devirtualized-filenames-issue-70924

created branch time in 2 days

pull request commentrust-lang/rfcs

Destructuring assignment

Now I know why I was concerned about the terminology here, as well as the proposed approach in the reference level explanation of "just extending the grammar for <place>":

Mutable places are used elsewhere in Rust's grammar, namely in &mut <place>.

So at the very least we need to give the places that occur in the LHS of an assignment some distinct grammatical category.

varkor

comment created time in 2 days

pull request commentrust-lang/rfcs

Destructuring assignment

Could you update the RFC to clarify whether nesting in general is supported on the LHS of an assignment?

Namely, I imagine the intent of this RFC is that the following should be supported:

struct S<T>(T);
fn foo(two: S<S<u32>>) -> u32 {
    let x: u32;
    S(S(x)) = two;
    return x;   
}

but the RFC has no examples where one of these "place-yielding expressions" is nested inside of another, I do not think, and the text in the reference level explanation is written with a grammar that is not recursive and cannot express the example I gave above.

(This sort of example I think may also show why neither the terminology of "pattern" nor that of "place" will actually work here... we need a new term to describe this construction with the right level of precision and accuracy, I think...)

varkor

comment created time in 2 days

issue commentrust-lang/rust

'rustc' panicked at 'failed to lookup `SourceFile` in new context'

After discussing with @eddyb , I have managed to replicate this on a local rustc build, and have a plausible fix in a prototype branch. Will be posting soon.

manio

comment created time in 2 days

issue commentrust-lang/compiler-team

Roadmap 2020-2021

To add to agenda at start:

  • "error: expected identifier when building time-macros-impl v0.1.1" #72545
    • It is also a regression.
    • Detected on day one.
    • Affects at least time, wasm-bindgen and syn.
    • It was also reported as https://github.com/rust-lang/rust/issues/72608
nikomatsakis

comment created time in 3 days

issue commentrust-lang/rust

LLVM error: "Instruction does not dominate all uses!" on Windows

self-assigning, with plan to revert injecting PR before it hits beta.

kryptan

comment created time in 3 days

issue commentrust-lang/rust

Trait object with non-static lifetime is accepted where static lifetime is expected and required

Discussed with @spastorino . This is probably a duplicate of #71550, but since it is P-critical and we have not 100% confirmed that these are exactly the same bug (in part because we do not have an MCVE for #72315).

Since @spastorino has confirmed that their PR #71896 does fix both issues, I'm going to assign this bug to them, just like #71550.

VFLashM

comment created time in 3 days

pull request commentrust-lang/rust

Translate the virtual `/rustc/$hash` prefix back to a real directory.

We may need to revert this PR if I cannot find a way to fix #70924 soonish...

eddyb

comment created time in 5 days

push eventrust-lang/cargo-bisect-rustc

Felix S. Klock II

commit sha 754278a0e663afa487dc45272673a8c5ee33005a

Revert "Include compiler crashes in ICE defintion" This reverts commit a3891cdd26d1c5d35257c351c7c86fa7e72604bb.

view details

Felix S Klock II

commit sha 82e234fb0784ad14f419aed05f33a9fa7c3ca4fe

Merge pull request #94 from chrissimpkins/revert-ice-definition Revert "Include compiler crashes in ICE defintion"

view details

push time in 5 days

PR merged rust-lang/cargo-bisect-rustc

Reviewers
Revert "Include compiler crashes in ICE defintion"

This reverts the ICE definition change at commit a3891cdd26d1c5d35257c351c7c86fa7e72604bb.

Cherry picked https://github.com/rust-lang/cargo-bisect-rustc/pull/88/commits/7bd1ec404ff28377f2bfd2652fa86edea997f7e0 from #88

r? @pnkfelix

+43 -36

1 comment

1 changed file

chrissimpkins

pr closed time in 5 days

pull request commentrust-lang/cargo-bisect-rustc

Revert "Include compiler crashes in ICE defintion"

Thanks for pulling this out!

I'll file an issue to track doing this the "right way." (According to the cargo devs, one can use verbose output from cargo which will print the underlying error codes from rustc, at least at some verbosity level...)

chrissimpkins

comment created time in 5 days

issue commentrust-lang/rust

`forbid` overwritten by later `allow` on the same "scope level"

To be clear, reclassifying as a stable-to-stable regression would reduce the pressure to resolve this in time for the release on June 4th.

(The stable-to-beta regression at hand was the CLI behavior regression, which was already addressed by PR #70918 )

It would also mean that

RalfJung

comment created time in 9 days

issue commentrust-lang/rust

`forbid` overwritten by later `allow` on the same "scope level"

One thing that I should have brought up sooner:

Should this bug be reclassified as a stable-to-stable regression rather than a stable-to-beta one, given that the underlying problem as identified by @RalfJung up above has been present since version 1.21 in 2017?

RalfJung

comment created time in 9 days

create barnchpnkfelix/rust

branch : separate-unsized-locals

created branch time in 10 days

issue commentrust-lang/compiler-team

Remove Spans from HIR

@rustbot second

cjgillot

comment created time in 10 days

issue commentrust-lang/compiler-team

Remove Spans from HIR

you can find associated zulip discussion here: https://zulip-archive.rust-lang.org/233931tcompilermajorchanges/98972RemoveSpansfromHIRcompilerteam294.html

cjgillot

comment created time in 10 days

issue commentrust-lang/compiler-team

create windows working group

@rustbot second

nikomatsakis

comment created time in 10 days

issue commentrust-lang/rust

Integer overflow on String::drain() with an inclusive range

also, I started a topic on the #t-libs zulip stream for this.

bodil

comment created time in 10 days

pull request commentrust-lang/rust

Implement Chain with Option fuses

This seems like it injected regression noted in issue #71359.

The regression in question might be fairly niche.

But I still wanted to check in about whether the benefit from this PR is significant enough to justify the risk associated with issue #71359?

cc @cuviper and @scottmcm

cuviper

comment created time in 10 days

pull request commentrust-lang/rust

Bump pulldown-cmark

beta-accepted

ehuss

comment created time in 10 days

pull request commentrust-lang/rust

Separate unsized fn param from unsized locals

(i'll see if I can help out here)

spastorino

comment created time in 11 days

issue commentrust-lang/rust

repr(packed) allows invalid unaligned loads

The topic of &raw versus &#$raw versus raw_ref! has been discussed a bunch by the lang design team, as you can see from the comments above and from issue #64490

At this point we are going to take baby steps here, namely via steps like PR #72279

So I think we can safely unnominate this from lang team's plate (and thus, as a nice side effect, stop talking about it at the T-compiler pre-triage sessions).

huonw

comment created time in 11 days

pull request commentrust-lang/rust

Aggressively check for non-`PartialEq` types in `const_to_pat`

This seems fine, as long as I'm correct in my understanding that this is just turning some ICE's from #65466 (most, to be fair) into static errors, while leaving the remaining ICEs from #65466 as ICEs.

That is, the note about "this is too permissive, obviously" -- that doesn't correspond to any case where we previously had an ICE (or static error) and would now attempt to do codegen for invalid code, right?

ecstatic-morse

comment created time in 12 days

Pull request review commentrust-lang/rust

Aggressively check for non-`PartialEq` types in `const_to_pat`

 impl<'a, 'tcx> ConstToPat<'a, 'tcx> {          Pat { span, ty: cv.ty, kind: Box::new(kind) }     }++    fn ty_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {+        let tcx = self.tcx();++        let is_partial_eq = |ty| {+            let partial_eq_trait_id = tcx.require_lang_item(EqTraitLangItem, Some(self.span));+            let obligation: PredicateObligation<'_> = predicate_for_trait_def(+                tcx,+                self.param_env,+                ObligationCause::misc(self.span, self.id),+                partial_eq_trait_id,+                0,+                ty,+                &[],+            );++            // FIXME: should this call a `predicate_must_hold` variant instead?+            self.infcx.predicate_may_hold(&obligation)+        };++        // Higher-ranked function pointers, such as `for<'r> fn(&'r i32)` are allowed in patterns+        // but do not satisfy `Self: PartialEq` due to shortcomings in the trait solver.+        // Check for bare function pointers first since it is cheap to do so.+        if let ty::FnPtr(_) = ty.kind {+            return true;+        }++        // In general, types that appear in patterns need to implement `PartialEq`.+        if is_partial_eq(ty) {+            return true;+        }++        // HACK: The check for bare function pointers will miss generic types that are instantiated+        // with a higher-ranked type (`for<'r> fn(&'r i32)`) as a parameter. To preserve backwards+        // compatibility in this case, we must continue to allow types such as `Option<fn(&i32)>`.+        //+        //+        // We accomplish this by replacing *all* late-bound lifetimes in the type with concrete+        // ones. This leverages the fact that function pointers with no late-bound lifetimes do+        // satisfy `PartialEq`. In other words, we transform `Option<for<'r> fn(&'r i32)>` to+        // `Option<fn(&'erased i32)>` and again check whether `PartialEq` is satisfied.+        // Obviously this is too permissive, but it is better than the old behavior, which

It would probably be a good idea to construct an example of something that runs into this (and presumably causes the same ICE that this is fixing most other occurrences of), and then file a bug about fixing that remaining hole, right?

@ecstatic-morse , can you provide a piece of example code that runs into that scenario?

ecstatic-morse

comment created time in 12 days

pull request commentrust-lang/rust

Querify whether a type implements `StructuralEq` and `PartialStructuralEq`

(r=me if ecstatic-morse agrees with my logic that we don't have to find the answer to their question yet to land this...)

ecstatic-morse

comment created time in 12 days

pull request commentrust-lang/rust

Querify whether a type implements `StructuralEq` and `PartialStructuralEq`

This seems fine to me. I want to hear more from @ecstatic-morse about the issue they raised up above before I mark it as r+'ed.

ecstatic-morse

comment created time in 12 days

Pull request review commentrust-lang/rust

Querify whether a type implements `StructuralEq` and `PartialStructuralEq`

 impl<'tcx> ty::TyS<'tcx> {         }     } +    /// Returns `true` if this type implements both `PartialStructuralEq` and `StructuralEq`.+    ///+    /// These marker traits are implemented along with `PartialEq` and `Eq` when implementations+    /// for those traits are derived. They indicate that two values of this type are equal if all+    /// of their fields are equal. A quirk of the marker traits is that their implementation is+    /// never conditional on generic parameter bounds. For that reason, this helper function does+    /// not take a `ParamEnv`.+    ///+    /// This function is "shallow" because it may return `true` for a type whose fields are not+    /// `StructuralEq`. You will need to use a type visitor if you want to know whether a call to+    /// `PartialEq::eq` will proceed structurally for a given type.+    #[inline]+    pub fn is_structural_eq_shallow(&'tcx self, tcx: TyCtxt<'tcx>) -> bool {+        // Fast path for some builtin types+        if self.is_primitive() || self.is_str() {

Is it bad to leave them unhandled here for now? All that means is that you miss the fast path for those types, right?

Then that is not a correctness concern; it is at most a performance concern, right? Which to me implies that we can merge this without figuring out the answer to your question.......

ecstatic-morse

comment created time in 12 days

Pull request review commentrust-lang/rust

Querify whether a type implements `StructuralEq` and `PartialStructuralEq`

 impl<'tcx> ty::TyS<'tcx> {         }     } +    /// Returns `true` if this type implements both `PartialStructuralEq` and `StructuralEq`.+    ///+    /// These marker traits are implemented along with `PartialEq` and `Eq` when implementations+    /// for those traits are derived. They indicate that two values of this type are equal if all+    /// of their fields are equal. A quirk of the marker traits is that their implementation is+    /// never conditional on generic parameter bounds. For that reason, this helper function does+    /// not take a `ParamEnv`.+    ///+    /// This function is "shallow" because it may return `true` for a type whose fields are not+    /// `StructuralEq`. You will need to use a type visitor if you want to know whether a call to+    /// `PartialEq::eq` will proceed structurally for a given type.+    #[inline]+    pub fn is_structural_eq_shallow(&'tcx self, tcx: TyCtxt<'tcx>) -> bool {+        // Fast path for some builtin types+        if self.is_primitive() || self.is_str() {

I suspect if we attempt to handle this by implementing the trait in all the cases of interest, we're going to run into the problem where we cannot implement it for types with a for <'a> ..., which arise from function pointers with a reference argument. (See also https://github.com/rust-lang/rust/issues/46989#issuecomment-353805481 ... and I'm struggling to find a specific issue about this particular wart in the language today...)

ecstatic-morse

comment created time in 12 days

pull request commentrust-lang/rust

exhaustively check `ty::Kind` during structural match checking

@bors r+ rollup

lcnr

comment created time in 12 days

pull request commentrust-lang/rust

Separate unsized fn param from unsized locals

@spastorino wrote:

As you can see here, here, here and here, I've migrated existing code to use the new flag but it seems that I'm lacking something because the error I'm getting.

I skimmed over the branch and noticed a few places in visit_pat code where your branch is looking solely for the unsized_locals feature. Those spots will probably need to be modified/generalized in some way to also behave properly when the unsized_fn_params feature is on, if and only if the pat in question is a fn param.

(The above note is a summary of commentary I wrote on zulip over here)

spastorino

comment created time in 12 days

pull request commentrust-lang/rust

Fully destructure constants into patterns

Hmm the try build failed on the merge:

    |                                    ^^^^^^^^^ private field

error[E0599]: no method named `unwrap_memory` found for struct `std::cell::RefMut<'_, rustc_middle::mir::interpret::AllocMap<'_>>` in the current scope
   --> src/librustc_mir_build/hair/pattern/const_to_pat.rs:315:53
    |
315 |                     let data = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
    |                                                     ^^^^^^^^^^^^^ method not found in `std::cell::RefMut<'_, rustc_middle::mir::interpret::AllocMap<'_>>`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0599, E0616.
For more information about an error, try `rustc --explain E0599`.
error: could not compile `rustc_mir_build`.

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-Zbinary-dep-depinfo" "-j" "8" "--release" "--locked" "--color" "always" "--features" "jemalloc llvm" "--manifest-path" "/checkout/src/rustc/Cargo.toml" "--message-format" "json-render-diagnostics"
expected success, got: exit code: 101

@oli is this something that needs a rebase, or what?

oli-obk

comment created time in 12 days

pull request commentrust-lang/rust

Fully destructure constants into patterns

@bors try

(to set up valid toolchain to feed to crater.)

oli-obk

comment created time in 12 days

pull request commentrust-lang/rust

Fully destructure constants into patterns

This looks fine I guess.

Lets get a crater run going just to have that information on hand.

oli-obk

comment created time in 12 days

Pull request review commentrust-lang/rust

Fully destructure constants into patterns

 pub fn main() {     assert_eq!(y, 2);     let z = match &() {         ZST => 9,-        // FIXME: this should not be required-        _ => 42,

looks to me like the PR no longer changes this test, and so it seems like this question is ... if not resolved, then at least postponed for the time being? Can I mark this as "resolved"?

oli-obk

comment created time in 12 days

pull request commentrust-lang/rust

Implement new gdb/lldb pretty-printers

@bors r+

ortem

comment created time in 12 days

issue commentrust-lang/compiler-team

Implement LLVM-compatible source-based code coverage

Hmm. Our triage meeting was cancelled last Thursday due to Zoom issues. In hindsight I wish we had alerted people to the list of MCP's on the Friday steering meeting, but I failed to put that on the Friday agenda...

Having said that, I suspect we can probably move forward with this nonetheless.

richkadel

comment created time in 12 days

pull request commentrust-lang/rfcs

RFC: Add a new `#[instruction_set(...)]` attribute for supporting per-function instruction set changes

(to be clear, the lang team is essentially waiting to see responses to the comments that @joshtriplett posted up above

ketsuban

comment created time in 13 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

Hmm what does this output imply...

2020-05-15T17:42:01.2716820Z fetching https://static.rust-lang.org/dist/2020-02-20/channel-rust-nightly-git-commit-hash.txt
2020-05-15T17:42:01.2717650Z converted 2020-02-20 to 7760cd0fbbbf2c59a625e075a5bdfa88b8e30f8a
2020-05-15T17:42:01.2718440Z fetching https://static.rust-lang.org/dist/2020-02-21/channel-rust-nightly-git-commit-hash.txt
2020-05-15T17:42:01.2719200Z converted 2020-02-21 to 2c462a2f776b899d46743b1b44eda976e846e61d
2020-05-15T17:42:01.2719940Z looking for regression commit between 2020-02-20 and 2020-02-21
2020-05-15T17:42:01.2720150Z ERROR: error decoding response body: missing field `commit` at line 1 column 246
2020-05-15T17:42:01.2720260Z 
2020-05-15T17:42:01.2720430Z ```
2020-05-15T17:42:01.2721160Z thread 'ice_test' panicked at 'assertion failed: stderr.contains(&needle)', tests/ice.rs:100:5
2020-05-15T17:42:01.2721390Z note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2020-05-15T17:42:01.2721510Z 
2020-05-15T17:42:01.2721600Z 
2020-05-15T17:42:01.2721780Z failures:
2020-05-15T17:42:01.2721950Z     ice_test
2020-05-15T17:42:01.2722040Z 
2020-05-15T17:42:01.2722220Z test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
2020-05-15T17:42:01.2722340Z 
2020-05-15T17:42:01.2724610Z error: test failed, to rerun pass '--test ice'
pnkfelix

comment created time in 16 days

push eventpnkfelix/cargo-bisect-rustc

Felix S. Klock II

commit sha 11923382f6be9b6e2d72adeee523f80ef6263872

Infrastructure for testing the command line tool. Note: generates tests into fresh temp dir, which is deleted after testing is done (regardless of success or failure). You can change the `which_temp::WhichTempDir` type to revise this behavior. This infrastructure includes two tests: `tests/cli.rs` and `tests/ice.rs`. Each uses very different strategies for testing cargo-bisect-rustc. 1. `tests/cli.rs` uses a so-called meta-build strategy: the test inspects the `rustc` version, then generates build files that will inject (or remove, e.g. when testing `--regress=success`) `#[rustc_error]` from the source code based on the `rustc` version. This way, we get the effect of an error that will come or go based solely on the `rustc` version, without any dependence on the actual behavior of `rustc` itself (beyond its version string format remaining parsable). * This strategy should remain usable for the foreseeable future, without any need for intervention from `cargo-bisect-rustc` developers. 2. `tests/ice.rs` uses a totally different strategy: It embeds an ICE that we know originated at a certain version of the compiler. The ICE is embedded in the file `src/ice/included_main.rs`. The injection point associated with the ICE is encoded in the constant `INJECTION_COMMIT`. * Over time, since we only keep a certain number of builds associated with PR merge commits available to download, the embedded ICE, the `INJECTION_COMMIT` definition, and the search bounds defined in `INJECTION_LOWER_BOUND` and `INJECTION_UPPER_BOUND` will all have to be updated as soon as the commit for `INJECTION_COMMIT` is no longer available for download. * Thus, this testing strategy requires regular maintenance from the `cargo-bisect-rustc` developers. (However, it is more flexible than the meta-build strategy, in that you can embed arbitrary failures from the recent past using this approach. The meta-build approach can only embed things that can be expressed via features like `#[rustc_error]`, which cannot currently express ICE's. ---- Includes suggestions from code review Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com> ---- Includes some coments explaining the `WhichTempDir` type. (That type maybe should just be an enum rather than a trait you implement... not sure why I made it so general...) ---- Includes workaround for rustfmt issue. Specifically, workaround https://github.com/rust-lang/rustfmt/issues/3794 which was causing CI's attempt to run `cargo fmt -- --check` to erroneously report: ``` % cargo fmt -- --check error[E0583]: file not found for module `meta_build` --> /private/tmp/cbr/tests/cli.rs:11:20 | 11 | pub(crate) mod meta_build; | ^^^^^^^^^^ | = help: name the file either meta_build.rs or meta_build/mod.rs inside the directory "/private/tmp/cbr/tests/cli/cli" error[E0583]: file not found for module `command_invocation` --> /private/tmp/cbr/tests/ice.rs:34:20 | 34 | pub(crate) mod command_invocation; | ^^^^^^^^^^^^^^^^^^ | = help: name the file either command_invocation.rs or command_invocation/mod.rs inside the directory "/private/tmp/cbr/tests/ice/common" ``` ---- Includes fix for oversight in my cli test system: it needed to lookup target binary, not our PATH. (This functionality is also available via other means, such as `$CARGO_BIN_EXE_<name>` and https://crates.io/crates/assert_cmd. I opted not to use the builtin env variable because that is only available in very recent cargo versions, and I would prefer our test suite to work peven on older versions of cargo, if that is feasible...) ---- Includes applications of rustfmt suggestions, as well as an expansion of a comment in a manner compatible with rustfmt. (Namely, that replaced an inline comment which is erroneously deleted by rustfmt (see https://github.com/rust-lang/rustfmt/issues/2781 ) with an additional note in the comment above the definition.)

view details

Felix S. Klock II

commit sha da1ee9d3888ec20ba23c35507aec47eb7674939d

Update `Cargo.lock` according to addition of `test_bin` dep in prior commit.

view details

push time in 16 days

issue commentrust-lang/rustfmt

A comment is removed after `pub` keyword in a struct.

Yet another example:

pub type Export /*: Bound */ = S1;

This is one where I think a comment is justified; today we do not enforce such bounds (i.e. the compiler does not check that the right-hand side of a type definition actually conforms to such a bound), and the compiler actually errors if you try to include it (because we don't want people to mistakenly think that such bounds are enforced).

But the comment here serves a useful purpose (about the intent, that we intend for this type definition to conform to the bound).

xfix

comment created time in 16 days

issue commentrust-lang/rustfmt

Rustfmt can't find module if a directory and module is named the same

(It would be good if this issue's title included the detail that its specifically about resolution in cargo tests/ directory. At least, that detail was quite relevant to me when I was trying to figure out what was wrong when I encountered it.)

Marwes

comment created time in 16 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

Sigh: rustfmt does not understand my idiosyncratic module layout...

Seems likely related to this: https://github.com/rust-lang/rustfmt/issues/3794

I will work-around it locally.

pnkfelix

comment created time in 16 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

Sigh: rustfmt does not understand my idiosyncratic module layout...

pnkfelix

comment created time in 16 days

push eventpnkfelix/cargo-bisect-rustc

Felix S. Klock II

commit sha 7bd1ec404ff28377f2bfd2652fa86edea997f7e0

Revert "Include compiler crashes in ICE defintion" This reverts commit a3891cdd26d1c5d35257c351c7c86fa7e72604bb.

view details

Felix S. Klock II

commit sha 82e0b7908e7849c143a946049ceecd9d587366ee

Test infra needs tempfile crate.

view details

Felix S. Klock II

commit sha 014c23a68c7eb866a1e4b6586d15a1c4d7f02e28

Infrastructure for testing the command line tool. Note: generates tests into fresh temp dir, which is deleted after testing is done (regardless of success or failure). You can change the `which_temp::WhichTempDir` type to revise this behavior. This infrastructure includes two tests: `tests/cli.rs` and `tests/ice.rs`. Each uses very different strategies for testing cargo-bisect-rustc. 1. `tests/cli.rs` uses a so-called meta-build strategy: the test inspects the `rustc` version, then generates build files that will inject (or remove, e.g. when testing `--regress=success`) `#[rustc_error]` from the source code based on the `rustc` version. This way, we get the effect of an error that will come or go based solely on the `rustc` version, without any dependence on the actual behavior of `rustc` itself (beyond its version string format remaining parsable). * This strategy should remain usable for the foreseeable future, without any need for intervention from `cargo-bisect-rustc` developers. 2. `tests/ice.rs` uses a totally different strategy: It embeds an ICE that we know originated at a certain version of the compiler. The ICE is embedded in the file `src/ice/included_main.rs`. The injection point associated with the ICE is encoded in the constant `INJECTION_COMMIT`. * Over time, since we only keep a certain number of builds associated with PR merge commits available to download, the embedded ICE, the `INJECTION_COMMIT` definition, and the search bounds defined in `INJECTION_LOWER_BOUND` and `INJECTION_UPPER_BOUND` will all have to be updated as soon as the commit for `INJECTION_COMMIT` is no longer available for download. * Thus, this testing strategy requires regular maintenance from the `cargo-bisect-rustc` developers. (However, it is more flexible than the meta-build strategy, in that you can embed arbitrary failures from the recent past using this approach. The meta-build approach can only embed things that can be expressed via features like `#[rustc_error]`, which cannot currently express ICE's.

view details

Felix S Klock II

commit sha bed81613ed36c736a7b10edd6a7b6f05a3829934

Apply suggestions from code review Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>

view details

Felix S. Klock II

commit sha 76729f11998db04e704a5115bc08b90536aa5baf

fix bug post-rebase (another PR had capitalized a word in output; maybe I should consider a regexp here...)

view details

Felix S. Klock II

commit sha 670ec6e7fd81e7dfb7f04a9abbf2f7ca03264c5f

Add some coments explaning the `WhichTempDir` type. (That type maybe should just be an enum rather than a trait you implement... not sure why I made it so general...)

view details

Felix S. Klock II

commit sha 40ab1eb0d482438e27c2bd9b50153c46afdaf7b3

fix oversight in my cli test system: it needed to lookup target binary, not our PATH. (This functionality is also available via other means, such as `$CARGO_BIN_EXE_<name>` and https://crates.io/crates/assert_cmd. I opted not to use the builtin env variable because that is only available in very recent cargo versions, and I would prefer our test suite to work peven on older versions of cargo, if that is feasible...)

view details

Felix S. Klock II

commit sha 23e70adc8bfe06a1af7d136f07fff4a06382c36d

Update `Cargo.lock` according to addition of `test_bin` dep in prior commit.

view details

push time in 16 days

pull request commentrust-lang/cargo-bisect-rustc

Include compiler crashes in ICE defintion

Ah, Glacier invokes rustc directly. So maybe Glacier's logic is correct for direct rustc invocations, but not appropriate for cargo invocations?

Alexendoo

comment created time in 16 days

pull request commentrust-lang/cargo-bisect-rustc

Include compiler crashes in ICE defintion

I do see that Glacier is using this same logic (link taken from commit). So either I'm wrong or glacier is wrong. Hmm.

Alexendoo

comment created time in 16 days

pull request commentrust-lang/cargo-bisect-rustc

Include compiler crashes in ICE defintion

I don't think this PR was quite right; it treats error code 101 as a unique identifier for ICE's, but even normal static errors from rustc will produce that same error code, I believe.

This mistake ends up breaking certain uses of --regress=ice, such as one I'm trying to include in my test suite as part of PR #88.

I'm going to revert this PR as part of PR #88 and open an issue to re-add its effects in a manner compatible with --regress=ice

Alexendoo

comment created time in 16 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

Apparently I might need to use some relatively new functionality...

pnkfelix

comment created time in 17 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

Oh; I wonder if the problem is that cargo-bisect-rustc is not on the PATH???

pnkfelix

comment created time in 17 days

push eventpnkfelix/cargo-bisect-rustc

Felix S. Klock II

commit sha f239318aa1d5f005d26ba579610dc534bab952b5

WIP debugging what is going wrong with CI's attempt to run the test.

view details

push time in 17 days

push eventpnkfelix/cargo-bisect-rustc

Felix S. Klock II

commit sha 3e8a9322f693c825606e8330f5ffc7a4ea3194d1

WIP switch to `GenerateIntoSlashTemp` to test whether that fixes issue when testing on CI.

view details

push time in 17 days

push eventpnkfelix/cargo-bisect-rustc

Felix S Klock II

commit sha 34a1a2d3b4a3f2719e213d8ab69022e2367330ce

Apply suggestions from code review Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>

view details

push time in 17 days

Pull request review commentrust-lang/cargo-bisect-rustc

Add cli test framework

+const INJECTION_COMMIT: &'static str = "f8fd4624474a68bd26694eff3536b9f3a127b2d3";+const INJECTION_LOWER_BOUND: &'static str = "2020-02-06";+const INJECTION_UPPER_BOUND: &'static str = "2020-02-08";++const INJECTION_POINT: InjectionPoint = InjectionPoint {+    date: YearMonthDay(2020, 02, 07),+    associated_sha: INJECTION_COMMIT,+};++mod cli {+    pub(crate) mod meta_build;+}++pub(crate) use self::cli::meta_build;++mod common {+    pub(crate) mod command_invocation;+    pub(crate) mod make_a_crate;+    pub(crate) mod which_temp;+}++pub(crate) use self::common::command_invocation;+pub(crate) use self::common::make_a_crate;+pub(crate) use self::common::which_temp;++use self::meta_build::{DeltaKind, InjectionPoint, Test, YearMonthDay};+use self::which_temp::{WhichTempDir, WhichTempDirectory};++// These tests pass `--preserve` and `--access=github` because that is the best+// way to try to enusre that the tests complete as quickly as possible.
// way to try to ensure that the tests complete as quickly as possible.
pnkfelix

comment created time in 17 days

pull request commentrust-lang/rust

Fix E0284 to not use incorrect wording

unilaterally accepting for beta-backport.

estebank

comment created time in 17 days

pull request commentrust-lang/rust

Fix hang in lexical_region_resolve

unilaterally accepting for beta-backport.

matthewjasper

comment created time in 17 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

(CI test failure. Hmm. I wonder if something is wrong with how I am generated temporary directories?)

pnkfelix

comment created time in 18 days

pull request commentrust-lang/cargo-bisect-rustc

Add cli test framework

on my laptop, it takes about two minutes to run the test suite the first time.

The test suite uses --preserve, so that future runs will reuse the (per-user shared, for better or for worse) .rustup bisector downloads.

So, on my laptop, subsequent runs take about 30 seconds to run instead of 2 minutes.

pnkfelix

comment created time in 18 days

PR opened rust-lang/cargo-bisect-rustc

Add cli test framework

Infrastructure for testing the command line tool.

Note: generates tests into fresh temp dir, which is deleted after testing is done (regardless of success or failure). You can change the which_temp::WhichTempDir type to revise this behavior.

This infrastructure includes two tests: tests/cli.rs and tests/ice.rs. Each uses very different strategies for testing cargo-bisect-rustc.

  1. tests/cli.rs uses a so-called meta-build strategy: the test inspects the rustc version, then generates build files that will inject (or remove, e.g. when testing --regress=success) #[rustc_error] from the source code based on the rustc version. This way, we get the effect of an error that will come or go based solely on the rustc version, without any dependence on the actual behavior of rustc itself (beyond its version string format remaining parsable).

    • This strategy should remain usable for the foreseeable future, without any need for intervention from cargo-bisect-rustc developers.
  2. tests/ice.rs uses a totally different strategy: It embeds an ICE that we know originated at a certain version of the compiler. The ICE is embedded in the file src/ice/included_main.rs. The injection point associated with the ICE is encoded in the constant INJECTION_COMMIT.

    • Over time, since we only keep a certain number of builds associated with PR merge commits available to download, the embedded ICE, the INJECTION_COMMIT definition, and the search bounds defined in INJECTION_LOWER_BOUND and INJECTION_UPPER_BOUND will all have to be updated as soon as the commit for INJECTION_COMMIT is no longer available for download.

    • Thus, this testing strategy requires regular maintenance from the cargo-bisect-rustc developers. (However, it is more flexible than the meta-build strategy, in that you can embed arbitrary failures from the recent past using this approach. The meta-build approach can only embed things that can be expressed via features like #[rustc_error], which cannot currently express ICE's.

+513 -0

0 comment

11 changed files

pr created time in 18 days

push eventpnkfelix/cargo-bisect-rustc

Alex Macleod

commit sha 062c40356f6f56ca450cb488a2efdbb505b3f150

Add --regress=non-ice Used to find when an ICE has been fixed, e.g. helpful for https://github.com/rust-lang/glacier

view details

Alex Macleod

commit sha ada635bed7fff8a9c198e3f9fd2eeb12a019b2fd

Allow passing arguments to `--script`s Uses the same option/syntax as the one for cargo, this is also useful for glacier, where we want to use rustc directly rather than cargo

view details

Santiago Pastorino

commit sha 00f28b728bcecebc882f9ecbd43575d0072c3857

Merge pull request #66 from Alexendoo/script-args Allow passing arguments to `--script`s

view details

Felix S Klock II

commit sha 25e566a3eb5645b3100d9e07cfe88a1f184c5074

Merge pull request #65 from Alexendoo/non-ice Add --regress=non-ice

view details

Chris Simpkins

commit sha 9430a462dc179234fe1a2fe432af325fbbd20772

refactor least_satisfying to eliminate duplicated start date checks This occurred during nighty testing when a start date is defined on the command line

view details

Chris Simpkins

commit sha 678411820da5a365cdbd3aadaf7acd2ab3737897

refactor Err to bail! statements

view details

Chris Simpkins

commit sha e50052ec966ac6d58c28d02dd1572690ef751b11

label application and bisection entry points

view details

Chris Simpkins

commit sha e96974f8ae3775d225453fea97a6982c96e1cd24

label CI and nightly bisect entry points

view details

Chris Simpkins

commit sha 89725a43e31e6dee10e4968ccc8ce14cf8715101

refactor: Toolchain and associated testing source to toolchains.rs

view details

Chris Simpkins

commit sha cef9a0ee5a7a9eebb678d3b6fabc1db6c0c21322

fmt toolchains.rs

view details

Chris Simpkins

commit sha 85610b46fbdbbb7980eb4ad22faf588c42c1047c

cast error with into()

view details

Chris Simpkins

commit sha 8227356a2bf0640fc1eeb427dea568d544ead77d

refactor least_satisfying to remove start/end bounds checks

view details

Chris Simpkins

commit sha 39f2eb6d523465ae648c21bbd17c6f46460b17b3

add install stderr message in Toolchain install method

view details

Chris Simpkins

commit sha 9c49536f6b5f787abc0d6be2a9d4477a8ed24140

refactor approach to start / end bounds validations, deduplicate source

view details

Chris Simpkins

commit sha e153a0f37261b361c1c7cddbf69640984a6bd96a

move testing stderr message location

view details

Chris Simpkins

commit sha 95c34431e1d067ff2ad518ccf41ebef6ef3dd27d

address clippy lint issues in main.rs + toolchains.rs

view details

Chris Simpkins

commit sha c2e19daf906fadca9ef931e5323caa321d337138

fmt

view details

Chris Simpkins

commit sha d1e7eb8fce8afb9f713a85b372462e4aab6f8082

remove unnecessary tests

view details

Chris Simpkins

commit sha c950c79319382cb9beff5dacace48ca3ebc23d06

"CL" changed to "command line"

view details

Felix S Klock II

commit sha 1b1c1446e62edd3fab3545be331a3dcfb00007ff

Merge pull request #62 from chrissimpkins/remove-duplicated-start-check Refactor Toolchain testing, eliminate duplicated start date checks

view details

push time in 18 days

pull request commentrust-lang/rust

Remove Spans from HIR

@cjgillot Do we have metrics for how much (if any) invalidation this eliminates?

(As you said a lot of spans still remain, I wouldn't be surprised if the net change is approximately zero. But I am still curious whether we can easily gather data here.)

cjgillot

comment created time in 19 days

Pull request review commentrust-lang/rfcs

Inline assembly

+- Feature Name: `asm`+- Start Date: (fill me in with today's date, YYYY-MM-DD)+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++This RFC specifies a new syntax for inline assembly which is suitable for eventual stabilization.++The initial implementation of this feature will focus on the ARM, x86 and RISC-V architectures. Support for more architectures will be added based on user demand.++The transition from the existing `asm!` macro is described in RFC [2843][rfc-llvm-asm]. The existing `asm!` macro will be renamed to `llvm_asm!` to provide an easy way to maintain backwards-compatibility with existing code using inline asm. However `llvm_asm!` is not intended to ever be stabilized.++[rfc-llvm-asm]: https://github.com/rust-lang/rfcs/pull/2843++# Motivation+[motivation]: #motivation++In systems programming some tasks require dropping down to the assembly level. The primary reasons are for performance, precise timing, and low level hardware access. Using inline assembly for this is sometimes convenient, and sometimes necessary to avoid function call overhead.++The inline assembler syntax currently available in nightly Rust is very ad-hoc. It provides a thin wrapper over the inline assembly syntax available in LLVM IR. For stabilization a more user-friendly syntax that lends itself to implementation across various backends is preferable.++Inline assembly is widely used in the Rust community and is one of the top reasons keeping people on the nightly toolchain. Examples of crates using inline assembly include `cortex-m`, `x86`, `riscv`, `parking_lot`, `libprobe`, `msp430`, etc. A collection of use cases for inline asm can also be found in [this repository][catalogue].++[catalogue]: https://github.com/bjorn3/inline_asm_catalogue/++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++Rust provides support for inline assembly via the `asm!` macro.+It can be used to embed handwritten assembly in the assembly output generated by the compiler.+Generally this should not be necessary, but might be where the required performance or timing+cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.++> Note: the examples here are given in x86/x86-64 assembly, but ARM, AArch64 and RISC-V are also supported.++## Basic usage++Let us start with the simplest possible example:++```rust+unsafe {+    asm!("nop");+}+```++This will insert a NOP (no operation) instruction into the assembly generated by the compiler.+Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert+arbitrary instructions and break various invariants. The instructions to be inserted are listed+in the first argument of the `asm!` macro as a string literal.++## Inputs and outputs++Now inserting an instruction that does nothing is rather boring. Let us do something that+actually acts on data:++```rust+let x: u64;+unsafe {+    asm!("mov {}, 5", out(reg) x);+}+assert_eq!(x, 5);+```++This will write the value `5` into the `u64` variable `x`.+You can see that the string literal we use to specify instructions is actually a template string.+It is governed by the same rules as Rust [format strings][format-syntax].+The arguments that are inserted into the template however look a bit different then you may+be familiar with. First we need to specify if the variable is an input or an output of the+inline assembly. In this case it is an output. We declared this by writing `out`.+We also need to specify in what kind of register the assembly expects the variable.+In this case we put it in an arbitrary general purpose register by specifying `reg`.+The compiler will choose an appropriate register to insert into+the template and will read the variable from there after the inline assembly finishes executing.++Let us see another example that also uses an input:++```rust+let i: u64 = 3;+let o: u64;+unsafe {+    asm!("+        mov {0}, {1}+        add {0}, {number}+    ", out(reg) o, in(reg) i, number = const 5);+}+assert_eq!(o, 8);+```++This will add `5` to the input in variable `i` and write the result to variable `o`.+The particular way this assembly does this is first copying the value from `i` to the output,+and then adding `5` to it.++The example shows a few things:++First we can see that inputs are declared by writing `in` instead of `out`.++Second one of our operands has a type we haven't seen yet, `const`.+This tells the compiler to expand this argument to value directly inside the assembly template.+This is only possible for constants and literals.++Third we can see that we can specify an argument number, or name as in any format string.+For inline assembly templates this is particularly useful as arguments are often used more than once.+For more complex inline assembly using this facility is generally recommended, as it improves+readability, and allows reordering instructions without changing the argument order.++We can further refine the above example to avoid the `mov` instruction:++```rust+let mut x: u64 = 3;+unsafe {+    asm!("add {0}, {number}", inout(reg) x, number = const 5);+}+assert_eq!(x, 8);+```++We can see that `inout` is used to specify an argument that is both input and output.+This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register.++It is also possible to specify different variables for the input and output parts of an `inout` operand:++```rust+let x: u64 = 3;+let y: u64;+unsafe {+    asm!("add {0}, {number}", inout(reg) x => y, number = const 5);+}+assert_eq!(y, 8);+```++## Late output operands++The Rust compiler is conservative with its allocation of operands. It is assumed that an `out`+can be written at any time, and can therefore not share its location with any other argument.+However, to guarantee optimal performance it is important to use as few registers as possible,+so they won't have to be saved and reloaded around the inline assembly block.+To achieve this Rust provides a `lateout` specifier. This can be used on any output that is+written only after all inputs have been consumed.+There is also a `inlateout` variant of this specifier.++Here is an example where `inlateout` *cannot* be used:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+let c: u64 = 4;+unsafe {+    asm!("+        add {0}, {1}+        add {0}, {2}+    ", inout(reg) a, in(reg) b, in(reg) c);+}+assert_eq!(a, 12);+```++Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.++However the following example can use `inlateout` since the output is only modified after all input registers have been read:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!("add {0}, {1}", inlateout(reg) a, in(reg) b);+}+assert_eq!(a, 8);+```++As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register.++## Explicit register operands++Some instructions require that the operands be in a specific register.+Therefore, Rust inline assembly provides some more specific constraint specifiers.+While `reg` is generally available on any architecture, these are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi`+among others can be addressed by their name.++```rust+unsafe {+    asm!("out 0x64, rax", in("rax") cmd);+}+```++In this example we call the `out` instruction to output the content of the `cmd` variable+to port `0x64`. Since the `out` instruction only accepts `rax` (and its sub registers) as operand+we had to use the `rax` constraint specifier.++Note that unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.++Consider this example which uses the x86 `mul` instruction:++```rust+fn mul(a: u64, b: u64) -> u128 {+    let lo: u64;+    let hi: u64;++    unsafe {+        asm!(+            // The x86 mul instruction takes rax as an implicit input and writes+            // the 128-bit result of the multiplication to rax:rdx.+            "mul {}",+            in(reg) a,+            inlateout("rax") b => lo,+            lateout("rdx") hi+        );+    }++    hi as u128 << 64 + lo as u128+}+```++This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result.+The only explicit operand is a register, that we fill from the variable `a`.+The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`.+The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`.+The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.++## Clobbered registers++In many cases inline assembly will modify state that is not needed as an output.+Usually this is either because we have to use a scratch register in the assembly,+or instructions modify state that we don't need to further examine.+This state is generally referred to as being "clobbered".+We need to tell the compiler about this since it may need to save and restore this state+around the inline assembly block.++```rust+let ebx: u64;+let ecx: u64;++unsafe {+    asm!(+        "cpuid",+        // EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf+        inout("eax") 4 => _,+        // ECX 0 selects the L0 cache information.+        inout("ecx") 0 => ecx,+        lateout("ebx") ebx,+        lateout("edx") _+    );+}++println!(+    "L1 Cache: {}",+    ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)+);+```++In the example above we use the `cpuid` instruction to get the L1 cache size.+This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.++However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.++This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:++```rust+// Multiply x by 6 using shifts and adds+let mut x: u64 = 4;+unsafe {+    asm!("+        mov {tmp}, {x}+        shl {tmp}, 1+        shl {x}, 2+        add {x}, {tmp}+    ", x = inout(reg) x, tmp = out(reg) _);+}+assert_eq!(x, 4 * 6);+```++## Symbol operands++A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code.+This allows you to call a function or access a global variable without needing to keep its address in a register.++```rust+extern "C" fn foo(arg: i32) {+    println!("arg = {}", arg);+}++fn call_foo(arg: i32) {+    unsafe {+        asm!(+            "call {}"+            sym foo,+            // 1st argument in rdi, which is caller-saved+            inout("rdi") arg => _,+            // All caller-saved registers must be marked as clobberred+            out("rax") _, out("rcx") _, out("rdx") _, out("rsi") _,+            out("r8") _, out("r9") _, out("r10") _, out("r11") _,+            out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,+            out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,+            out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,+            out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,+        )+    }+}+```++Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`:+the compiler will automatically insert the appropriate mangled symbol name into the assembly code.++## Register template modifiers++In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register).++By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).++This default can be overriden by using modifiers on the template string operands, just like you would with format strings:++```rust+let mut x: u16 = 0xab;++unsafe {+    asm!("mov {0:h}, {0:b}", inout(reg_abcd) x);+}++assert_eq!(x, 0xabab);+```++In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently.++Let us assume that the register allocator has chosen to allocate `x` in the `ax` register.+The `h` modifier will emit the register name for the high byte of that register and the `b` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte.++If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.++## Options++By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.++Let's take our previous example of an `add` instruction:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!(+        "add {0}, {1}",+        inlateout(reg) a, in(reg) b,+        options(pure, nomem, nostack)+    );+}+assert_eq!(a, 8);+```++Options can be provided as an optional final argument to the `asm!` macro. We specified three options here:+- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely.+- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global).+- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments.++These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.++See the reference for the full list of available options and their effects.++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++Inline assembler is implemented as an unsafe macro `asm!()`.+The first argument to this macro is a template string literal used to build the final assembly.+The following arguments specify input and output operands.+When required, options are specified as the final argument.++The following ABNF specifies the general syntax:++```+dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"+reg_spec := <register class> / "<explicit register>"+operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"+reg_operand := dir_spec "(" reg_spec ")" operand_expr+operand := reg_operand / "const" const_expr / "sym" path+option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "att_syntax"+options := "options(" option *["," option] [","] ")"+asm := "asm!(" format_string *("," [ident "="] operand) ["," options] [","] ")"+```++The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.++[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax++## Template string++The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.++As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated.++The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.++The 4 targets specified in this RFC (x86, ARM, AArch64, RISC-V) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used by default. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior.++[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795++## Operand type++Several types of operands are supported:++* `in(<reg>) <expr>`+  - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.+  - The allocated register will contain the value of `<expr>` at the start of the asm code.+  - The allocated register must contain the same value at the end of the asm code (except if a `lateout` is allocated to the same register).+* `out(<reg>) <expr>`+  - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.+  - The allocated register will contain an undefined value at the start of the asm code.+  - `<expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.+  - An underscore (`_`) may be specified instead of an expression, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).+* `lateout(<reg>) <expr>`+  - Identical to `out` except that the register allocator can reuse a register allocated to an `in`.+  - You should only write to the register after all inputs are read, otherwise you may clobber an input.+* `inout(<reg>) <expr>`+  - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.+  - The allocated register will contain the value of `<expr>` at the start of the asm code.+  - `<expr>` must be a mutable initialized place expression, to which the contents of the allocated register is written to at the end of the asm code.+* `inout(<reg>) <in expr> => <out expr>`+  - Same as `inout` except that the initial value of the register is taken from the value of `<in expr>`.+  - `<out expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.+  - An underscore (`_`) may be specified instead of an expression for `<out expr>`, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).+  - `<in expr>` and `<out expr>` may have different types.+* `inlateout(<reg>) <expr>` / `inlateout(<reg>) <in expr> => <out expr>`

Inlateout can have an underscore for <out expr>, right?

I know the text immediately below says "Identical to inout, but there are multiple kinds of inout and they do not all have an <out expr>, so its better to be explicit here in either case (i.e. whether its supported or not, let's say so explicitly).

Amanieu

comment created time in 23 days

Pull request review commentrust-lang/rfcs

Inline assembly

+- Feature Name: `asm`+- Start Date: (fill me in with today's date, YYYY-MM-DD)+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++This RFC specifies a new syntax for inline assembly which is suitable for eventual stabilization.++The initial implementation of this feature will focus on the ARM, x86 and RISC-V architectures. Support for more architectures will be added based on user demand.++The transition from the existing `asm!` macro is described in RFC [2843][rfc-llvm-asm]. The existing `asm!` macro will be renamed to `llvm_asm!` to provide an easy way to maintain backwards-compatibility with existing code using inline asm. However `llvm_asm!` is not intended to ever be stabilized.++[rfc-llvm-asm]: https://github.com/rust-lang/rfcs/pull/2843++# Motivation+[motivation]: #motivation++In systems programming some tasks require dropping down to the assembly level. The primary reasons are for performance, precise timing, and low level hardware access. Using inline assembly for this is sometimes convenient, and sometimes necessary to avoid function call overhead.++The inline assembler syntax currently available in nightly Rust is very ad-hoc. It provides a thin wrapper over the inline assembly syntax available in LLVM IR. For stabilization a more user-friendly syntax that lends itself to implementation across various backends is preferable.++Inline assembly is widely used in the Rust community and is one of the top reasons keeping people on the nightly toolchain. Examples of crates using inline assembly include `cortex-m`, `x86`, `riscv`, `parking_lot`, `libprobe`, `msp430`, etc. A collection of use cases for inline asm can also be found in [this repository][catalogue].++[catalogue]: https://github.com/bjorn3/inline_asm_catalogue/++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++Rust provides support for inline assembly via the `asm!` macro.+It can be used to embed handwritten assembly in the assembly output generated by the compiler.+Generally this should not be necessary, but might be where the required performance or timing+cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.++> Note: the examples here are given in x86/x86-64 assembly, but ARM, AArch64 and RISC-V are also supported.++## Basic usage++Let us start with the simplest possible example:++```rust+unsafe {+    asm!("nop");+}+```++This will insert a NOP (no operation) instruction into the assembly generated by the compiler.+Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert+arbitrary instructions and break various invariants. The instructions to be inserted are listed+in the first argument of the `asm!` macro as a string literal.++## Inputs and outputs++Now inserting an instruction that does nothing is rather boring. Let us do something that+actually acts on data:++```rust+let x: u64;+unsafe {+    asm!("mov {}, 5", out(reg) x);+}+assert_eq!(x, 5);+```++This will write the value `5` into the `u64` variable `x`.+You can see that the string literal we use to specify instructions is actually a template string.+It is governed by the same rules as Rust [format strings][format-syntax].+The arguments that are inserted into the template however look a bit different then you may+be familiar with. First we need to specify if the variable is an input or an output of the+inline assembly. In this case it is an output. We declared this by writing `out`.+We also need to specify in what kind of register the assembly expects the variable.+In this case we put it in an arbitrary general purpose register by specifying `reg`.+The compiler will choose an appropriate register to insert into+the template and will read the variable from there after the inline assembly finishes executing.++Let us see another example that also uses an input:++```rust+let i: u64 = 3;+let o: u64;+unsafe {+    asm!("+        mov {0}, {1}+        add {0}, {number}+    ", out(reg) o, in(reg) i, number = const 5);+}+assert_eq!(o, 8);+```++This will add `5` to the input in variable `i` and write the result to variable `o`.+The particular way this assembly does this is first copying the value from `i` to the output,+and then adding `5` to it.++The example shows a few things:++First we can see that inputs are declared by writing `in` instead of `out`.++Second one of our operands has a type we haven't seen yet, `const`.+This tells the compiler to expand this argument to value directly inside the assembly template.+This is only possible for constants and literals.++Third we can see that we can specify an argument number, or name as in any format string.+For inline assembly templates this is particularly useful as arguments are often used more than once.+For more complex inline assembly using this facility is generally recommended, as it improves+readability, and allows reordering instructions without changing the argument order.++We can further refine the above example to avoid the `mov` instruction:++```rust+let mut x: u64 = 3;+unsafe {+    asm!("add {0}, {number}", inout(reg) x, number = const 5);+}+assert_eq!(x, 8);+```++We can see that `inout` is used to specify an argument that is both input and output.+This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register.++It is also possible to specify different variables for the input and output parts of an `inout` operand:++```rust+let x: u64 = 3;+let y: u64;+unsafe {+    asm!("add {0}, {number}", inout(reg) x => y, number = const 5);+}+assert_eq!(y, 8);+```++## Late output operands++The Rust compiler is conservative with its allocation of operands. It is assumed that an `out`+can be written at any time, and can therefore not share its location with any other argument.+However, to guarantee optimal performance it is important to use as few registers as possible,+so they won't have to be saved and reloaded around the inline assembly block.+To achieve this Rust provides a `lateout` specifier. This can be used on any output that is+written only after all inputs have been consumed.+There is also a `inlateout` variant of this specifier.++Here is an example where `inlateout` *cannot* be used:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+let c: u64 = 4;+unsafe {+    asm!("+        add {0}, {1}+        add {0}, {2}+    ", inout(reg) a, in(reg) b, in(reg) c);+}+assert_eq!(a, 12);+```++Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.++However the following example can use `inlateout` since the output is only modified after all input registers have been read:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!("add {0}, {1}", inlateout(reg) a, in(reg) b);+}+assert_eq!(a, 8);+```++As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register.++## Explicit register operands++Some instructions require that the operands be in a specific register.+Therefore, Rust inline assembly provides some more specific constraint specifiers.+While `reg` is generally available on any architecture, these are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi`+among others can be addressed by their name.++```rust+unsafe {+    asm!("out 0x64, rax", in("rax") cmd);+}+```++In this example we call the `out` instruction to output the content of the `cmd` variable+to port `0x64`. Since the `out` instruction only accepts `rax` (and its sub registers) as operand+we had to use the `rax` constraint specifier.++Note that unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.++Consider this example which uses the x86 `mul` instruction:++```rust+fn mul(a: u64, b: u64) -> u128 {+    let lo: u64;+    let hi: u64;++    unsafe {+        asm!(+            // The x86 mul instruction takes rax as an implicit input and writes+            // the 128-bit result of the multiplication to rax:rdx.+            "mul {}",+            in(reg) a,+            inlateout("rax") b => lo,+            lateout("rdx") hi+        );+    }++    hi as u128 << 64 + lo as u128+}+```++This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result.+The only explicit operand is a register, that we fill from the variable `a`.+The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`.+The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`.+The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.++## Clobbered registers++In many cases inline assembly will modify state that is not needed as an output.+Usually this is either because we have to use a scratch register in the assembly,+or instructions modify state that we don't need to further examine.+This state is generally referred to as being "clobbered".+We need to tell the compiler about this since it may need to save and restore this state+around the inline assembly block.++```rust+let ebx: u64;+let ecx: u64;++unsafe {+    asm!(+        "cpuid",+        // EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf+        inout("eax") 4 => _,+        // ECX 0 selects the L0 cache information.+        inout("ecx") 0 => ecx,+        lateout("ebx") ebx,+        lateout("edx") _+    );+}++println!(+    "L1 Cache: {}",+    ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)+);+```++In the example above we use the `cpuid` instruction to get the L1 cache size.+This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.++However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.++This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:++```rust+// Multiply x by 6 using shifts and adds+let mut x: u64 = 4;+unsafe {+    asm!("+        mov {tmp}, {x}+        shl {tmp}, 1+        shl {x}, 2+        add {x}, {tmp}+    ", x = inout(reg) x, tmp = out(reg) _);+}+assert_eq!(x, 4 * 6);+```++## Symbol operands++A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code.+This allows you to call a function or access a global variable without needing to keep its address in a register.++```rust+extern "C" fn foo(arg: i32) {+    println!("arg = {}", arg);+}++fn call_foo(arg: i32) {+    unsafe {+        asm!(+            "call {}"+            sym foo,+            // 1st argument in rdi, which is caller-saved+            inout("rdi") arg => _,+            // All caller-saved registers must be marked as clobberred+            out("rax") _, out("rcx") _, out("rdx") _, out("rsi") _,+            out("r8") _, out("r9") _, out("r10") _, out("r11") _,+            out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,+            out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,+            out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,+            out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,+        )+    }+}+```++Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`:+the compiler will automatically insert the appropriate mangled symbol name into the assembly code.++## Register template modifiers++In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register).++By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).++This default can be overriden by using modifiers on the template string operands, just like you would with format strings:++```rust+let mut x: u16 = 0xab;++unsafe {+    asm!("mov {0:h}, {0:b}", inout(reg_abcd) x);+}++assert_eq!(x, 0xabab);+```++In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently.++Let us assume that the register allocator has chosen to allocate `x` in the `ax` register.+The `h` modifier will emit the register name for the high byte of that register and the `b` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte.++If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.++## Options++By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.++Let's take our previous example of an `add` instruction:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!(+        "add {0}, {1}",+        inlateout(reg) a, in(reg) b,+        options(pure, nomem, nostack)+    );+}+assert_eq!(a, 8);+```++Options can be provided as an optional final argument to the `asm!` macro. We specified three options here:+- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely.+- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global).+- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments.++These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.++See the reference for the full list of available options and their effects.++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++Inline assembler is implemented as an unsafe macro `asm!()`.+The first argument to this macro is a template string literal used to build the final assembly.+The following arguments specify input and output operands.+When required, options are specified as the final argument.++The following ABNF specifies the general syntax:++```+dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"+reg_spec := <register class> / "<explicit register>"+operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"+reg_operand := dir_spec "(" reg_spec ")" operand_expr+operand := reg_operand / "const" const_expr / "sym" path+option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn"+options := "options(" option *["," option] [","] ")"+asm := "asm!(" format_string *("," [ident "="] operand) ["," options] [","] ")"+```++The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.++[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax++## Template string++The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.++As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated.++The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.++The 4 targets specified in this RFC (x86, ARM, AArch64, RISC-V) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior.++[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795++## Operand type

Oh I'm sorry; I somehow managed to read the section about clobbering without noting the general syntax you have chosen for it.

Amanieu

comment created time in 23 days

Pull request review commentrust-lang/rfcs

Inline assembly

+- Feature Name: `asm`+- Start Date: (fill me in with today's date, YYYY-MM-DD)+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++This RFC specifies a new syntax for inline assembly which is suitable for eventual stabilization.++The initial implementation of this feature will focus on the ARM, x86 and RISC-V architectures. Support for more architectures will be added based on user demand.++The transition from the existing `asm!` macro is described in RFC [2843][rfc-llvm-asm]. The existing `asm!` macro will be renamed to `llvm_asm!` to provide an easy way to maintain backwards-compatibility with existing code using inline asm. However `llvm_asm!` is not intended to ever be stabilized.++[rfc-llvm-asm]: https://github.com/rust-lang/rfcs/pull/2843++# Motivation+[motivation]: #motivation++In systems programming some tasks require dropping down to the assembly level. The primary reasons are for performance, precise timing, and low level hardware access. Using inline assembly for this is sometimes convenient, and sometimes necessary to avoid function call overhead.++The inline assembler syntax currently available in nightly Rust is very ad-hoc. It provides a thin wrapper over the inline assembly syntax available in LLVM IR. For stabilization a more user-friendly syntax that lends itself to implementation across various backends is preferable.++Inline assembly is widely used in the Rust community and is one of the top reasons keeping people on the nightly toolchain. Examples of crates using inline assembly include `cortex-m`, `x86`, `riscv`, `parking_lot`, `libprobe`, `msp430`, etc. A collection of use cases for inline asm can also be found in [this repository][catalogue].++[catalogue]: https://github.com/bjorn3/inline_asm_catalogue/++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++Rust provides support for inline assembly via the `asm!` macro.+It can be used to embed handwritten assembly in the assembly output generated by the compiler.+Generally this should not be necessary, but might be where the required performance or timing+cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.++> Note: the examples here are given in x86/x86-64 assembly, but ARM, AArch64 and RISC-V are also supported.++## Basic usage++Let us start with the simplest possible example:++```rust+unsafe {+    asm!("nop");+}+```++This will insert a NOP (no operation) instruction into the assembly generated by the compiler.+Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert+arbitrary instructions and break various invariants. The instructions to be inserted are listed+in the first argument of the `asm!` macro as a string literal.++## Inputs and outputs++Now inserting an instruction that does nothing is rather boring. Let us do something that+actually acts on data:++```rust+let x: u64;+unsafe {+    asm!("mov {}, 5", out(reg) x);+}+assert_eq!(x, 5);+```++This will write the value `5` into the `u64` variable `x`.+You can see that the string literal we use to specify instructions is actually a template string.+It is governed by the same rules as Rust [format strings][format-syntax].+The arguments that are inserted into the template however look a bit different then you may+be familiar with. First we need to specify if the variable is an input or an output of the+inline assembly. In this case it is an output. We declared this by writing `out`.+We also need to specify in what kind of register the assembly expects the variable.+In this case we put it in an arbitrary general purpose register by specifying `reg`.+The compiler will choose an appropriate register to insert into+the template and will read the variable from there after the inline assembly finishes executing.++Let us see another example that also uses an input:++```rust+let i: u64 = 3;+let o: u64;+unsafe {+    asm!("+        mov {0}, {1}+        add {0}, {number}+    ", out(reg) o, in(reg) i, number = const 5);+}+assert_eq!(o, 8);+```++This will add `5` to the input in variable `i` and write the result to variable `o`.+The particular way this assembly does this is first copying the value from `i` to the output,+and then adding `5` to it.++The example shows a few things:++First we can see that inputs are declared by writing `in` instead of `out`.++Second one of our operands has a type we haven't seen yet, `const`.+This tells the compiler to expand this argument to value directly inside the assembly template.+This is only possible for constants and literals.++Third we can see that we can specify an argument number, or name as in any format string.+For inline assembly templates this is particularly useful as arguments are often used more than once.+For more complex inline assembly using this facility is generally recommended, as it improves+readability, and allows reordering instructions without changing the argument order.++We can further refine the above example to avoid the `mov` instruction:++```rust+let mut x: u64 = 3;+unsafe {+    asm!("add {0}, {number}", inout(reg) x, number = const 5);+}+assert_eq!(x, 8);+```++We can see that `inout` is used to specify an argument that is both input and output.+This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register.++It is also possible to specify different variables for the input and output parts of an `inout` operand:++```rust+let x: u64 = 3;+let y: u64;+unsafe {+    asm!("add {0}, {number}", inout(reg) x => y, number = const 5);+}+assert_eq!(y, 8);+```++## Late output operands++The Rust compiler is conservative with its allocation of operands. It is assumed that an `out`+can be written at any time, and can therefore not share its location with any other argument.+However, to guarantee optimal performance it is important to use as few registers as possible,+so they won't have to be saved and reloaded around the inline assembly block.+To achieve this Rust provides a `lateout` specifier. This can be used on any output that is+written only after all inputs have been consumed.+There is also a `inlateout` variant of this specifier.++Here is an example where `inlateout` *cannot* be used:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+let c: u64 = 4;+unsafe {+    asm!("+        add {0}, {1}+        add {0}, {2}+    ", inout(reg) a, in(reg) b, in(reg) c);+}+assert_eq!(a, 12);+```++Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.++However the following example can use `inlateout` since the output is only modified after all input registers have been read:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!("add {0}, {1}", inlateout(reg) a, in(reg) b);+}+assert_eq!(a, 8);+```++As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register.++## Explicit register operands++Some instructions require that the operands be in a specific register.+Therefore, Rust inline assembly provides some more specific constraint specifiers.+While `reg` is generally available on any architecture, these are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi`+among others can be addressed by their name.++```rust+unsafe {+    asm!("out 0x64, rax", in("rax") cmd);+}+```++In this example we call the `out` instruction to output the content of the `cmd` variable+to port `0x64`. Since the `out` instruction only accepts `rax` (and its sub registers) as operand+we had to use the `rax` constraint specifier.++Note that unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.++Consider this example which uses the x86 `mul` instruction:++```rust+fn mul(a: u64, b: u64) -> u128 {+    let lo: u64;+    let hi: u64;++    unsafe {+        asm!(+            // The x86 mul instruction takes rax as an implicit input and writes+            // the 128-bit result of the multiplication to rax:rdx.+            "mul {}",+            in(reg) a,+            inlateout("rax") b => lo,+            lateout("rdx") hi+        );+    }++    hi as u128 << 64 + lo as u128+}+```++This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result.+The only explicit operand is a register, that we fill from the variable `a`.+The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`.+The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`.+The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.++## Clobbered registers++In many cases inline assembly will modify state that is not needed as an output.+Usually this is either because we have to use a scratch register in the assembly,+or instructions modify state that we don't need to further examine.+This state is generally referred to as being "clobbered".+We need to tell the compiler about this since it may need to save and restore this state+around the inline assembly block.++```rust+let ebx: u64;+let ecx: u64;++unsafe {+    asm!(+        "cpuid",+        // EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf+        inout("eax") 4 => _,+        // ECX 0 selects the L0 cache information.+        inout("ecx") 0 => ecx,+        lateout("ebx") ebx,+        lateout("edx") _+    );+}++println!(+    "L1 Cache: {}",+    ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)+);+```++In the example above we use the `cpuid` instruction to get the L1 cache size.+This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.++However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.++This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:++```rust+// Multiply x by 6 using shifts and adds+let mut x: u64 = 4;+unsafe {+    asm!("+        mov {tmp}, {x}+        shl {tmp}, 1+        shl {x}, 2+        add {x}, {tmp}+    ", x = inout(reg) x, tmp = out(reg) _);+}+assert_eq!(x, 4 * 6);+```++## Symbol operands++A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code.+This allows you to call a function or access a global variable without needing to keep its address in a register.++```rust+extern "C" fn foo(arg: i32) {+    println!("arg = {}", arg);+}++fn call_foo(arg: i32) {+    unsafe {+        asm!(+            "call {}"+            sym foo,+            // 1st argument in rdi, which is caller-saved+            inout("rdi") arg => _,+            // All caller-saved registers must be marked as clobberred+            out("rax") _, out("rcx") _, out("rdx") _, out("rsi") _,+            out("r8") _, out("r9") _, out("r10") _, out("r11") _,+            out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,+            out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,+            out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,+            out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,+        )+    }+}+```++Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`:+the compiler will automatically insert the appropriate mangled symbol name into the assembly code.++## Register template modifiers++In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register).++By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).++This default can be overriden by using modifiers on the template string operands, just like you would with format strings:++```rust+let mut x: u16 = 0xab;++unsafe {+    asm!("mov {0:h}, {0:b}", inout(reg_abcd) x);+}++assert_eq!(x, 0xabab);+```++In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently.++Let us assume that the register allocator has chosen to allocate `x` in the `ax` register.+The `h` modifier will emit the register name for the high byte of that register and the `b` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte.++If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.++## Options++By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.++Let's take our previous example of an `add` instruction:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!(+        "add {0}, {1}",+        inlateout(reg) a, in(reg) b,+        options(pure, nomem, nostack)+    );+}+assert_eq!(a, 8);+```++Options can be provided as an optional final argument to the `asm!` macro. We specified three options here:+- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely.+- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global).+- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments.++These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.++See the reference for the full list of available options and their effects.++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++Inline assembler is implemented as an unsafe macro `asm!()`.+The first argument to this macro is a template string literal used to build the final assembly.+The following arguments specify input and output operands.+When required, options are specified as the final argument.++The following ABNF specifies the general syntax:++```+dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"+reg_spec := <register class> / "<explicit register>"+operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"+reg_operand := dir_spec "(" reg_spec ")" operand_expr+operand := reg_operand / "const" const_expr / "sym" path+option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn"+options := "options(" option *["," option] [","] ")"+asm := "asm!(" format_string *("," [ident "="] operand) ["," options] [","] ")"+```++The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.++[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax++## Template string++The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.++As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated.++The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.++The 4 targets specified in this RFC (x86, ARM, AArch64, RISC-V) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior.++[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795++## Operand type

Hmm. But there is also clobber to consider, which assigns to the expression without giving it a well-defined value.

That is, if I understand correctly:

let foo: u32;
asm!("...", out(reg) foo);
a_use_of(foo); // legal
let foo: u32;
asm!("...", clobber(reg) foo);
a_use_of(foo); // illegal

(also, does the current system have a notion of inclobber, which is like inout in that it only clobbers the variable after it has read the relevant data from it? Does it need such a notion?)

I don't remember if the current move/borrow-checker, liveness, and variable-initialization analyses currently have a way to express the clobber effect, but even if they don't, I cannot imagine it would be terribly hard to add.


In any case, it would be good to spell this out explicitly in the RFC, since I was looking for it as I was reading and could not find it.

Amanieu

comment created time in 23 days

issue commentrust-lang/compiler-team

survey overview and discussion

An initial attempt to summarize the survey results: https://hackmd.io/gv41a48mRb-KV4SoJ0nXCA?edit

nikomatsakis

comment created time in 23 days

issue commentrust-lang/rust

Compile-time stack overflow when trait impl contains extern crate

discussed at T-compiler meeting. Assigning to @eddyb

dtolnay

comment created time in 24 days

issue commentrust-lang/rust

rust-lld since 1.38 overlaps .text with .rodata for embedded arm target

discussed at T-compiler meeting. Self-assigning to look at @ashtneoi 's x86 repro, and see if I can isolate if this an upstream lld bug or not.

lightblu

comment created time in 24 days

issue commentrust-lang/rust

Rustc overflow its stack when using impl Trait and the struct containing the function itself

discussed at T-compiler meeting. Reprioritizing as P-medium, since its not a true regression and not an active soundness hole.

lszxb

comment created time in 24 days

pull request commentrust-lang/rust

Update the `cc` crate

discussed at T-compiler meeting. Accepted for beta-backport.

alexcrichton

comment created time in 24 days

pull request commentrust-lang/rust

Do not try to find binop method on RHS `TyErr`

unilaterally accepting for beta-backport.

estebank

comment created time in 24 days

issue commentrust-lang/rust

Compile-time stack overflow when trait impl contains extern crate

triage: nominating for discussion as part of attempt to burn down set of unassigned P-high issues at an otherwise light triage meeting.

dtolnay

comment created time in 25 days

issue commentrust-lang/rust

rust-lld since 1.38 overlaps .text with .rodata for embedded arm target

triage: visiting as part of general attempt to burn down set of unassigned P-high non-ICE issues. I note that I "threatened" to close this issue as "nothing further for T-compiler to do here" back in November of 2019, but it sounds ike recent reports say that there may be evidence that this is target agnostic.

Nominating for discussion at T-compiler meeting, mostly to see if anyone there has ready ability to reproduce locally.

lightblu

comment created time in 25 days

issue commentrust-lang/rust

Rustc doesn't report line numbers for type errors within proc macro async fn within macro_rules macro

triage: visited as part of general query of unassigned P-high non-ICE issues. But it looks like @nellshamrell is taking a look at this, so I'm marking as assigned to nell for now.

natemara

comment created time in 25 days

issue commentrust-lang/rust

Rustc overflow its stack when using impl Trait and the struct containing the function itself

nominating for discussion as part of attempt to burn down set of unassigned P-high issues at an otherwise light triage meeting.

lszxb

comment created time in 25 days

issue commentrust-lang/rust

compiletest does not signal when a ui (or compile-fail) test with `//~ WARN` gets unexpected warnings

assigning to self to follow-up and determine if this is even a problem at this point.

pnkfelix

comment created time in 25 days

issue commentrust-lang/rust

compiletest does not signal when a ui (or compile-fail) test with `//~ WARN` gets unexpected warnings

Is this actually still a problem, given that #55596 has been resolved?

pnkfelix

comment created time in 25 days

pull request commentrust-lang/rust

resolve: Relax fresh binding disambiguation slightly to fix regression

unilaterally accepting for beta-backport.

petrochenkov

comment created time in 25 days

pull request commentrust-lang/rust

Hide some members of TypeckTables behind queries

Are there tests illustrating what kinds of code this is make work better with incremental compilation? (How were you testing the effectiveness of these changes?)

cjgillot

comment created time in a month

pull request commentrust-lang/rust

forbid `dyn Trait` in patterns

@bors r+

lcnr

comment created time in a month

pull request commentrust-lang/rust

Avoid duplicating code for each query

(tagging as rollup=never since we want to track its performance impact separately from other PR's)

cjgillot

comment created time in a month

pull request commentrust-lang/rust

Avoid duplicating code for each query

@bors r+ rollup=never

cjgillot

comment created time in a month

PR closed rust-lang/rust

Avoid duplicating code for each query S-waiting-on-review

There are at the moment roughly 170 queries in librustc. The way ty::query is structured, a lot of code is duplicated for each query. I suspect this to be responsible for a part of librustc'c compile time.

The first part of this PR reduces the amount of code generic on the query, replacing it by code generic on the key-value types. I can split it out if needed.

In a second part, the non-inlined methods in the QueryAccessors and QueryDescription traits are made into a virtual dispatch table. This allows to reduce even more the number of generated functions.

This allows to save 1.5s on check build, and 10% on the size of the librustc.rlib. (Attributed roughly half and half). My computer is not good enough to measure properly compiling time. I have no idea of the effect on performance. A perf run may be required.

cc #65031

+240 -103

23 comments

10 changed files

cjgillot

pr closed time in a month

PullRequestEvent

pull request commentrust-lang/rust

Avoid duplicating code for each query

This looks great. I am especially happy with how the commits in this PR were laid out; it made it very easy to review.

cjgillot

comment created time in a month

Pull request review commentrust-lang/rust

Avoid duplicating code for each query

 where /// side-effects -- e.g., in order to report errors for erroneous programs. /// /// Note: The optimization is only available during incr. comp.+#[inline(never)]

(no, your description says your rig is not suitable for local benchmarking, so that cannot be the answer...)

cjgillot

comment created time in a month

Pull request review commentrust-lang/rust

Avoid duplicating code for each query

 fn ensure_query_impl<CTX, C>(     } } -fn force_query_impl<C, CTX>(+#[inline(never)]

(same as above, just wondering what prompted this use of #[inline(never)]...)

cjgillot

comment created time in a month

Pull request review commentrust-lang/rust

Avoid duplicating code for each query

 where /// side-effects -- e.g., in order to report errors for erroneous programs. /// /// Note: The optimization is only available during incr. comp.+#[inline(never)]

why the #[inline(never)] marker here? Did you observe a need for it on some benchmark locally?

cjgillot

comment created time in a month

more