1. 51

I’m posting this because it has several features which are exciting not just from a language perspective but also from an engineering and practices perspective. TL;DR:

  • source-based code coverage
  • stable mechanism for collecting info on build timings
  • much more flexible optional dependency features system, with namespaces and weak requirements

There’s other stuff, including lots of stabilized APIs, but this is really the core of what excites me here.

  1. 6

    source-based code coverage

    I’m probably dense, but I don’t get it. I read the Rust release notes, I google the clang feature. Code coverage of what? Test coverage?

    1. 18

      It’s in the linked docs, but “coverage” here means “the code is executed.” It tells you where your dead code is, and can be summarized into four useful high-level statistics:

      • Function coverage is the percentage of functions executed at least once.
      • Instantiation coverage is the percentage of function instantiations executed at least once (this is for generics and macro-generated functions).
      • Line coverage is the percentage of lines of code executed at least once.
      • Region coverage is the percentage of code regions executed at least once (there’s a particular definition of a “region” but basically it’s more granular than the function-level metrics).
      1. 3

        Specifically to the question: it’s quite easy to record coverage in a binary (i.e. which instructions were executed), you add some instrumentation on each branch to record what the target was and you can then generate a list of the basic blocks that were executed. You need some extra tooling to map these back to locations in the source code. This is what source-based code coverage mean. Often, it’s implemented by inserting the instrumentation in the front end (which has more relevant information for the coverage), though it’s also possible to use source locations in debug info to map from pure binary coverage info back to the source code. The latter approach is nice if you can make it work because it can be non-disruptive: if your CPU and OS support modern tracing functionality then they can generate basic-block-level traces for arbitrary binaries and you can then map this back to the source code for the exact version that was executed.

        1. 1

          Thanks!

      2. 2

        Stabilized Not for !.

        Interesting that any trait with only methods and no functions can be implemented for the never type since they can’t be called: Primitive Type never.

        1. 3

          Interesting that any trait with only methods and no functions can be implemented for the never type

          In other contexts, that is called the bottom type, because it sits at the bottom of the type lattice, and is therefore a subtype of every other type. So I find this fairly unsurprising.

          1. 1

            Isn’t that the initial type? I thought the bottom type was () since we can always reach it

            1. 4

              No. ‘bottom’ refers to subtyping relationships, not compositional relationships. It’s true you can make anything from (), |, and *. But () isn’t a subtype of ()|().

              E: this is general nomenclature. It’s possible rust has its own vocabulary I don’t know about.