Skip to content

Stabilize #![feature(slice_patterns)] in 1.42.0#67712

Merged
bors merged 8 commits into
rust-lang:masterfrom
Centril:stabilize-slice_patterns
Jan 18, 2020
Merged

Stabilize #![feature(slice_patterns)] in 1.42.0#67712
bors merged 8 commits into
rust-lang:masterfrom
Centril:stabilize-slice_patterns

Conversation

@Centril
Copy link
Copy Markdown
Contributor

@Centril Centril commented Dec 30, 2019

Stabilization report

The following is the stabilization report for #![feature(slice_patterns)].
This report is the collaborative effort of @matthewjasper and @Centril.

Tracking issue: #62254
Version target: 1.42 (2020-01-30 => beta, 2020-03-12 => stable).

Backstory: slice patterns

It is already possible to use slice patterns on stable Rust to match on arrays and slices. For example, to match on a slice, you may write:

fn foo(slice: &[&str]) {
    match slice {
        [] => { dbg!() }
        [a] => { dbg!(a); }
        [a, b] => { dbg!(a, b); }
        _ => {}
    //  ^ Fallback -- necessary because the length is unknown!
    }
}

To match on an array, you may instead write:

fn bar([a, b, c]: [u8; 3]) {}
//     --------- Length is known, so pattern is irrefutable.

However, on stable Rust, it is not yet possible to match on a subslice or subarray.

A quick user guide: Subslice patterns

The ability to match on a subslice or subarray is gated under #![feature(slice_patterns)] and is what is proposed for stabilization here.

The syntax of subslice patterns

Subslice / subarray patterns come in two flavors syntactically.

Common to both flavors is they use the token .., referred as a "rest pattern" in a pattern context. This rest pattern functions as a variable-length pattern, matching whatever amount of elements that haven't been matched already before and after.

When .. is used syntactically as an element of a slice-pattern, either directly (1), or as part of a binding pattern (2), it becomes a subslice pattern.

On stable Rust, a rest pattern .. can also be used in a tuple or tuple-struct pattern with let (x, ..) = (1, 2, 3); and let TS(x, ..) = TS(1, 2, 3); respectively.

(1) Matching on a subslice without binding it

fn base(string: &str) -> u8 {
    match string.as_bytes() {
        [b'0', b'x', ..] => 16,
        [b'0', b'o', ..] => 8,
        [b'0', b'b', ..] => 2,
        _ => 10,
    }
}

fn main() {
    assert_eq!(base("0xFF"), 16);
    assert_eq!(base("0x"), 16);
}

In the function base, the pattern [b'0', b'x', ..] will match on any byte-string slice with the prefix 0x. Note that .. may match on nothing, so 0x is a valid match.

(2) Binding a subslice:

fn main() {
    #[derive(PartialEq, Debug)]
    struct X(u8);
    let xs: Vec<X> = vec![X(0), X(1), X(2)];

    if let [start @ .., end] = &*xs {
        //              --- bind on last element, assuming there is one.
        //  ---------- bind the initial elements, if there are any.
        assert_eq!(start, &[X(0), X(1)] as &[X]);
        assert_eq!(end, &X(2));
        let _: &[X] = start;
        let _: &X = end;
    }
}

In this case, [start @ .., end] will match any non-empty slice, binding the last element to end and any elements before that to start. Note in particular that, as above, start may match on the empty slice.

Only one .. per slice pattern

In today's stable Rust, a tuple (struct) pattern (a, b, c) can only have one subtuple pattern (e.g., (a, .., c)). That is, if there is a rest pattern, it may only occur once. Any .. that follow, as in e.g., (a, .., b, ..) will cause an error, as there is no way for the compiler to know what b applies to. This rule also applies to slice patterns. That is, you may also not write [a, .., b, ..].

Motivation

Slice patterns provide a natural and efficient way to pattern match on slices and arrays. This is particularly useful as slices and arrays are quite a common occurence in modern software targeting modern hardware. However, as aforementioned, it's not yet possible to perform incomplete matches, which is seen in fn base, an example taken from the rustc codebase itself. This is where subslice patterns come in and extend slice patterns with the natural syntax xs @ .. and .., where the latter is already used for tuples and tuple structs. As an example of how subslice patterns can be used to clean up code, we have PR #67569. In this PR, slice patterns enabled us to improve readability and reduce unsafety, at no loss to performance.

Technical specification

Grammar

The following specification is a sub-set of the grammar necessary to explain what interests us here. Note that stabilizing subslice patterns does not alter the stable grammar. The stabilization contains purely semantic changes.

Binding = reference:"ref"? mutable:"mut"? name:IDENT;

Pat =
  | ... // elided
  | Rest: ".."
  | Binding:{ binding:Binding { "@" subpat:Pat }? }
  | Slice:{ "[" elems:Pat* %% "," "]" }
  | Paren:{ "(" pat:Pat ")" }
  | Tuple:{ path:Path? "(" elems:Pat* &% "," ")" }
  ;

Notes:

  1. (..) is interpreted as a Tuple, not a Paren.
    This means that [a, (..)] is interpreted as Slice[Binding(a), Tuple[Rest]] and not Slice[Binding(a), Paren(Rest)].

Name resolution

A slice pattern is resolved as a product context and .. is given no special treatment.

Abstract syntax of slice patterns

The abstract syntax (HIR level) is defined like so:

enum PatKind {
    ... // Other unimportant stuff.
    Wild,
    Binding {
        binding: Binding,
        subpat: Option<Pat>,
    },
    Slice {
        before: List<Pat>,
        slice: Option<Pat>,
        after: List<Pat>,
    },
}

The executable definition is found in hir::PatKind.

Lowering to abstract syntax

Lowering a slice pattern to its abstract syntax proceeds by:

  1. Lowering each element pattern of the slice pattern, where:

    1. .. is lowered to _,
      recording that it was a subslice pattern,

    2. binding @ .. is lowered to binding @ _,
      recording that it was a subslice pattern,

    3. and all other patterns are lowered as normal,
      recording that it was not a subslice pattern.

  2. Taking all lowered elements until the first subslice pattern.

  3. Take all following elements.

    If there are any,

    1. The head is the sub-slice pattern.
    2. The tail (after) must not contain a subslice pattern,
      or an error occurs.

The full executable definition can be found in LoweringContext::lower_pat_slice.

Type checking slice patterns

Default binding modes

A slice pattern is a non-reference pattern as defined in is_non_ref_pat. This means that when type checking a slice pattern, as many immediate reference types are peeled off from the expected type as possible and the default binding mode is adjusted to by-reference before checking the slice pattern. See #63118 for an algorithmic description.

See RFC 2359's guide-level explanation and the tests listed below for examples of what effect this has.

Checking the pattern

Type checking a slice pattern proceeds as follows:

  1. Resolve any type variables by a single level.
    If the result still is a type variable, error.

  2. Determine the expected type for any subslice pattern (slice_ty) and for elements (inner_ty) depending on the expected type.

    1. If the expected type is an array ([E; N]):

      1. Evaluate the length of the array.
        If the length couldn't be evaluated, error.
        This may occur when we have e.g., const N: usize.
        Now N is known.

      2. If there is no sub-slice pattern,
        check len(before) == N,
        and otherwise error.

      3. Otherwise,
        set S = N - len(before) - len(after),
        and check N >= 0 and otherwise error.
        Set slice_ty = [E; S].

      Set inner_ty = E.

    2. If the expected type is a slice ([E]),
      set inner_ty = E and slice_ty = [E].

    3. Otherwise, error.

  3. Check each element in before and after against inner_ty.

  4. If it exists, check slice against slice_ty.

For an executable definition, see check_pat_slice.

Typed abstract syntax of slice and array patterns

The typed abstract syntax (HAIR level) is defined like so:

enum PatKind {
    ... // Other unimportant stuff.
    Wild,
    Binding {
        ... // Elided.
    }
    Slice {
        prefix: List<Pat>,
        slice: Option<Pat>,
        suffix: List<Pat>,
    },
    Array {
        prefix: List<Pat>,
        slice: Option<Pat>,
        suffix: List<Pat>,
    },
}

The executable definition is found in hair::pattern::PatKind.

Lowering to typed abstract syntax

Lowering a slice pattern to its typed abstract syntax proceeds by:

  1. Lowering each pattern in before into prefix.
  2. Lowering the slice, if it exists, into slice.
    1. A Wild pattern in abstract syntax is lowered to Wild.
    2. A Binding pattern in abstract syntax is lowered to Binding { .. }.
  3. Lowering each pattern in after into after.
  4. If the type is [E; N], construct PatKind::Array { prefix, slice, after }, otherwise PatKind::Slice { prefix, slice, after }.

The executable definition is found in PatCtxt::slice_or_array_pattern.

Exhaustiveness checking

Let E be the element type of a slice or array.

  • For array types, [E; N] with a known length N, the full set of constructors required for an exahustive match is the sequence ctors(E)^N where ctors denotes the constructors required for an exhaustive match of E.

  • Otherwise, for slice types [E], or for an array type with an unknown length [E; ?L], the full set of constructors is the infinite sequence ⋃_i=0^∞ ctors(E)^i. This entails that an exhaustive match without a cover-all pattern (e.g. _ or binding) or a subslice pattern (e.g., [..] or [_, _, ..]) is impossible.

  • PatKind::{Slice, Array}(prefix, None, suffix @ []) cover a sequence of of len(prefix) covered by patterns. Note that suffix.len() > 0 with slice == None is unrepresentable.

  • PatKind::{Slice, Array}(prefix, Some(s), suffix) cover a sequence with prefix as the start and suffix as the end and where len(prefix) + len(suffix) <= len(sequence). The .. in the middle is interpreted as an unbounded number of _s in terms of exhaustiveness checking.

MIR representation

The relevant MIR representation for the lowering into MIR, which is discussed in the next section, includes:

enum Rvalue {
    // ...
    /// The length of a `[X]` or `[X; N]` value.
    Len(Place),
}

struct Place {
    base: PlaceBase,
    projection: List<PlaceElem>,
}

enum ProjectionElem {
    // ...
    ConstantIndex {
        offset: Nat,
        min_length: Nat,
        from_end: bool,
    },
    Subslice {
        from: Nat,
        to: Nat,
        from_end: bool,
    },
}

Lowering to MIR

  • For a slice pattern matching a slice, where the pattern has N elements specified, there is a check that the Rvalue::Len of the slice is at least N to decide if the pattern can match.

  • There are two kinds of ProjectionElem used for slice patterns:

    1. ProjectionElem::ConstantIndex is an array or slice element with a known index. As a shorthand it's written base[offset of min_length] if from_end is false and base[-offset of min_length] if from_end is true. base[-offset of min_length] is the len(base) - offsetth element of base.

    2. ProjectionElem::Subslice is a subslice of an array or slice with known bounds. As a shorthand it's written base[from..to] if from_end is false and base[from:-to] if from_end is true. base[from:-to] is the subslice base[from..len(base) - to].

    • Note that ProjectionElem::Index is used for indexing expressions, but not for slice patterns. It's written base[idx].
  • When binding an array pattern, any individual element binding is lowered to an assignment or borrow of base[offset of len] where offset is the element's index in the array and len is the array's length.

  • When binding a slice pattern, let N be the number of elements that have patterns. Elements before the subslice pattern (prefix) are lowered to base[offset of N] where offset is the element's index from the start. Elements after the subslice pattern (suffix) are lowered to base[-offset of N] where offset is the element's index from the end, plus 1.

  • Subslices of arrays are lowered to base[from..to] where from is the number of elements before the subslice pattern and to = len(array) - len(suffix) is the length of the array minus the number of elements after the subslice pattern.

  • Subslices of slices are lowered to base[from:-to] where from is the number of elements before the subslice pattern (len(prefix)) and to is the number of elements after the subslice pattern (len(suffix)).

Safety and const checking

  • Subslice patterns do not introduce any new unsafe operations.

  • As subslice patterns for arrays are irrefutable, they are allowed in const contexts. As are [..] and [ref y @ ..] patterns for slices. However, ref mut bindings are only allowed with feature(const_mut_refs) for now.

  • As other subslice patterns for slices require a match, if let, or while let, they are only allowed with feature(const_if_match, const_fn) for now.

  • Subslice patterns may occur in promoted constants.

Borrow and move checking

  • A subslice pattern can be moved from if it has an array type [E; N] and the parent array can be moved from.

  • Moving from an array subslice pattern moves from all of the elements of the array within the subslice.

    • If the subslice contains at least one element, this means that dynamic indexing (arr[idx]) is no longer allowed on the array.

    • The array can be reinitialized and can still be matched with another slice pattern that uses a disjoint set of elements.

  • A subslice pattern can be mutably borrowed if the parent array/slice can be mutably borrowed.

  • When determining whether an access conflicts with a borrow and at least one is a slice pattern:

    • x[from..to] always conflicts with x and x[idx] (where idx is a variable).

    • x[from..to] conflicts with x[idx of len] if from <= idx and idx < to (that is, idx ∈ from..to).

    • x[from..to] conflicts with x[from2..to2] if from < to2 and from2 < to (that is, (from..to) ∩ (from2..to2) ≠ ∅).

    • x[from:-to] always conflicts with x, x[idx], and x[from2:-to2].

    • x[from:-to] conflicts with x[idx of len] if from <= idx.

    • x[from:-to] conflicts with x[-idx of len] if to < idx.

  • A constant index from the end conflicts with other elements as follows:

    • x[-idx of len] always conflicts with x and x[idx].

    • x[-idx of len] conflicts with x[-idx2 of len2] if idx == idx2.

    • x[-idx of len] conflicts with x[idx2 of len2] if idx + idx2 >= max(len, len2).

Tests

The tests can be primarily seen in the PR itself. Here are some of them:

Parsing (3)

Lowering (2)

Type checking (5)

Exhaustiveness and usefulness checking (20)

Borrow checking (28)

MIR lowering (1)

Evaluation (19)

Misc (1)

History

Related / possible future work

There is on-going work to improve pattern matching in other ways (the relevance of some of these are indirect, and only by composition):

As for more direct improvements to slice patterns, some avenues could be:

  • Box patterns, e.g., box [a, b, .., c] to match on Box<[T]>.
    Tracking issue: Tracking issue for box_patterns feature #29641
    This issue currently has no path to stabilization.

    Note that it is currently possible to match on Box<[T]> or Vec<T> by first dereferencing them to slices.

  • DerefPure, which would allow e.g., using slice patterns to match on Vec<T> (e.g., moving out of it).

Another idea which was raised by RFC 2707 and RFC 2359 was to allow binding a subtuple pattern. That is, we could allow (a, xs @ .., b). However, while we could allow by-value bindings to .. as in xs @ .. at zero cost, the same cannot be said of by-reference bindings, e.g. (a, ref xs @ .., b). The issue here becomes that for a reference to be legal, we have to represent xs contiguously in memory. In effect, we are forced into a HList based representation for tuples.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 30, 2019
@Centril Centril added relnotes Marks issues that should be documented in the release notes of the next release. T-lang Relevant to the language team labels Dec 30, 2019
@Centril Centril added this to the 1.42 milestone Dec 30, 2019
@Centril
Copy link
Copy Markdown
Contributor Author

Centril commented Dec 30, 2019

Stabilization proposal

Dear community & language team,
I propose that we stabilize #![feature(slice_patterns)].

@rfcbot merge

Tracking issue: #62254
Version target: 1.42 (2020-01-30 => beta, 2020-03-12 => stable).

Please see the attached report above for details.

@rfcbot
Copy link
Copy Markdown

rfcbot commented Dec 30, 2019

Team member @Centril has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Dec 30, 2019
@brson
Copy link
Copy Markdown
Contributor

brson commented Dec 30, 2019

Incredible PR OP. Thanks @matthewjasper and @Centril.

@SimonSapin
Copy link
Copy Markdown
Contributor

This looks great! Thanks for everyone’s work on the implementation and on such a detailed report.

The tail (after) must not contain a subslice pattern, or an error occurs.

This answers a question I had when reading "A quick user guide": no more than one rest pattern may be used in a given slice pattern or array pattern. This would be worth pointing out in high-level documentation for this feature. Do we have such docs or is The Reference the closest?

On stable Rust, a rest pattern .. can also be used in a tuple or tuple-struct pattern with let (x, ..) = (1, 2, 3); and let TS(x, ..) = TS(1, 2, 3); respectively.

One could imagine bindings for such rest patterns that create a smaller tuple: let (x, y @ ..) = (1, 2, 3); assert_eq!(y, (2, 3)) but that is not supported or planned, right?

Is .. in a struct pattern not called a rest pattern? StructName { field_name: pat, .. }

This entails that an exhaustive match without a cover-all pattern (e.g. _, binding, [..]) is impossible.

Taking this literally suggests that a single pattern that matches any slice is mandatory, and this example would fail exhaustiveness checking:

match some_slice: &[T] {
    &[] => "zero",
    &[_a] => "one",
    &[_a, _b] => "two",
    &[_a, _b, _c, ..] => "many",
}

Is that the case, or is the compiler able to reason about the union of matched slice lengths? If the latter, I think “an exhaustive match without a rest pattern is impossible” would be more correct.

@Centril
Copy link
Copy Markdown
Contributor Author

Centril commented Dec 30, 2019

This answers a question I had when reading "A quick user guide": no more than one rest pattern may be used in a given slice pattern or array pattern. This would be worth pointing out in high-level documentation for this feature. Do we have such docs or is The Reference the closest?

I've added a short section to the user-guide part of the report. :) The reference only documents stable Rust, and so it will need to be updated with some of the contents from this report.

One could imagine bindings for such rest patterns that create a smaller tuple: let (x, y @ ..) = (1, 2, 3); assert_eq!(y, (2, 3)) but that is not supported or planned, right?

Heh... I managed to forget this one in the "Related future work". I've added it now. That said, supporting (x, y @ ..) is not currently planned. It should be feasible to support it for by-value bindings, but once you have e.g. (x, ref y @ ..) it becomes a problem in terms of constraining layout optimizations of tuples and you'll need to make trade-offs (alternatively, ref y @ .. produces (&T_N, ..., &T_M), but that is possibly surprising and inconsistent).

Is .. in a struct pattern not called a rest pattern? StructName { field_name: pat, .. }

No, a struct pattern does not consist of a sequence of patterns, but rather a sequence of FieldPats. The .. in a struct pattern is also special and is not an ast::PatKind::Rest.

Taking this literally suggests that a single pattern that matches any slice is mandatory, and this example would fail exhaustiveness checking:

The example results in an exhaustive match:

#![feature(slice_patterns)]

fn main() {
    let some_slice: &[u8] = &[];
    match some_slice {
        &[] => {}
        &[_a] => {}
        &[_a, _b] => {}
        &[_a, _b, _c, ..] => {}
    }
}

Is that the case, or is the compiler able to reason about the union of matched slice lengths? If the latter, I think “an exhaustive match without a rest pattern is impossible” would be more correct.

The compiler can reason about the fact that e.g. together, [] and [_, ..] cover the full set (as your example shows). I've clarified the report to note that both cover-all and subslice patterns work.

@SimonSapin
Copy link
Copy Markdown
Contributor

Heh... I managed to forget this one in the "Related future work".

I should have clarified that I am not particularly in favor of adding support for bindings for sub-tuples. I only meant to confirm that they are not supported or planned. (The way the report mentioned rest patterns without bindings in tuples after rest patterns without and with bindings in slices suggested that this might be the "natural" next step.) I feel they are much less useful since tuples are usually heterogeneous, and they have complications (as you said with references) that I think are not worth getting into.

@bors

This comment has been minimized.

Comment thread src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs Outdated
Comment thread src/test/ui/ignore-all-the-things.rs Outdated
@matthewjasper matthewjasper removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 2, 2020
@pnkfelix
Copy link
Copy Markdown
Contributor

pnkfelix commented Jan 6, 2020

From "Borrow and Move checking":

  • ...
    • The array can be reinitialized and can still be matched with another slice pattern that uses a disjoint set of elements.

I am not sure how you intend for the above sentence to be interpreted. In my experience, slice patterns currently will not let you rematch an array where you have moved out via a slice pattern, even with a pattern that is disjoint compared to the previously matched part.

For example, consider the following playpen

#![feature(slice_patterns)]

#[derive(Clone, Debug)]
struct D(&'static str);

impl Drop for D {
    fn drop(&mut self) { println!("Dropping D({})", self.0); }
}

fn main() {
    let a = [D("a0"),D("a1"),D("a2"),D("a3"),D("a4"),D("a5"),D("a6"),D("a7")];
    println!("before matches");
    match a {
        [_, _, s2_5 @ .., _, _] => { println!("sub2_5 {:?}", s2_5); }
    }
    println!("between matches");
    match a {
        [_, _, _, _, _, _, s6_7 @ ..] => { println!("sub6_7 {:?}", s6_7); }
    }
    println!("after matches");
}

Here, the 8-element array a matched, first with a pattern that moves out elements a[2] .. a[5], and the second moves out elements a[6] .. a[7].

Or at least, it would if it compiled. But on the playpen, it currently issues the following error:

error[E0382]: use of moved value: `a`
  --> src/main.rs:17:11
   |
14 |         [_, _, s2_5 @ .., _, _] => { println!("sub2_5 {:?}", s2_5); }
   |                --------- value moved here
...
17 |     match a {
   |           ^ value used here after partial move
   |
   = note: move occurs because `a[..]` has type `D`, which does not implement the `Copy` trait

error: aborting due to previous error

Can you clarify what the above text is talking about?

  • If the above text is intended to mean you can match against a disjoint slice pattern within the same match expression, that is a super important distinction to draw and probably worth spelling out more explicitly, perhaps even with some examples.

@Centril
Copy link
Copy Markdown
Contributor Author

Centril commented Jan 7, 2020

@pnkfelix

I am not sure how you intend for the above sentence to be interpreted. In my experience, slice patterns currently will not let you rematch an array where you have moved out via a slice pattern, even with a pattern that is disjoint compared to the previously matched part.

For example, consider the following playpen

@matthewjasper tells me that this is a case of the #53114 bug. That is, it's a case of _ doing a "read" where it shouldn't. If you use let bindings instead it works out (playground):

#![feature(slice_patterns)]
#![allow(warnings)]

struct X;

fn main() {
    let arr = [X, X, X, X, X, X];
    let [_, x @ .. ,   _, _] = arr;
    let [_, _, _, _, y @ ..] = arr;
}

See src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs for the test case.

My personal view is that this is an orthogonal bug that can be fixed separately. (However it does seem like a bug that now has renewed usefulness in being fixed soon, so maybe let's P-high that?)

@rfcbot rfcbot added the final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. label Jan 7, 2020
@rfcbot
Copy link
Copy Markdown

rfcbot commented Jan 7, 2020

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot removed the proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. label Jan 7, 2020
@Centril
Copy link
Copy Markdown
Contributor Author

Centril commented Jan 8, 2020

To clarify the behavior that @pnkfelix was witnessing, I've filed #67990, which hardens the testing of slice patterns some more wrt. match and documents the behavior due to #53114.

bors added a commit that referenced this pull request Jan 18, 2020
Rollup of 5 pull requests

Successful merges:

 - #67712 (Stabilize `#![feature(slice_patterns)]` in 1.42.0)
 - #68224 (Prevent urls in headings)
 - #68340 (clean up e0200 explanation)
 - #68341 (Fix syscalls tables in docs of std::time.)
 - #68342 (improve type_name_of_val docs)

Failed merges:

r? @ghost
@bors bors merged commit 57b6843 into rust-lang:master Jan 18, 2020
@Centril Centril deleted the stabilize-slice_patterns branch January 18, 2020 22:09
matthiaskrgr added a commit to matthiaskrgr/rust-clippy that referenced this pull request Jan 18, 2020
slice_patterns have been stabilized.
matthiaskrgr added a commit to matthiaskrgr/rust-clippy that referenced this pull request Jan 18, 2020
slice_patterns have been stabilized.
bors added a commit to rust-lang/rust-clippy that referenced this pull request Jan 18, 2020
rustup rust-lang/rust#67712

slice_patterns have been stabilized.

changelog: none
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 19, 2020
Changes:
````
Treat more strange pattern
Split up `if_same_then_else` ui test
Apply review comments
Run `update_lints`
Reduce span range
Rename `ok_if_let` to `if_let_some_result`
Apply review comments
Add suggestion in `if_let_some_result`
rustup rust-lang#67712
Allow `unused_self` lint at the function level
Downgrade range_plus_one to pedantic
Rustup to rust-lang#68204
Add lifetimes to `LateLintPass`
Fix rustc lint import paths generated by `new_lint`
Add lint for default lint description
Update documentation for adding new lints
Generate new lints easily
Split up `booleans` ui test
Fix the ordering on `nonminimal_bool`
````
@Centril
Copy link
Copy Markdown
Contributor Author

Centril commented Jan 22, 2020

The stabilization also is extensively covered in Thomas Hartmann's blog post: https://thomashartmann.dev/blog/feature(slice_patterns)/.

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Mar 13, 2020
Version 1.42.0 (2020-03-12)
==========================

Language
--------
- [You can now use the slice pattern syntax with subslices.][67712] e.g.
  ```rust
  fn foo(words: &[&str]) {
      match words {
          ["Hello", "World", "!", ..] => println!("Hello World!"),
          ["Foo", "Bar", ..] => println!("Baz"),
          rest => println!("{:?}", rest),
      }
  }
  ```
- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
  that you can create an enum that has the exact layout and ABI of the type
  it contains.
- [There are some *syntax-only* changes:][67131]
   - `default` is syntactically allowed before items in `trait` definitions.
   - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
     leave out their bodies in favor of `;`.
   - Bounds on associated types in `impl`s are now syntactically allowed
     (e.g. `type Foo: Ord;`).
   - `...` (the C-variadic type) may occur syntactically directly as the type of
      any function parameter.

  These are still rejected *semantically*, so you will likely receive an error
  but these changes can be seen and parsed by procedural macros and
  conditional compilation.

Compiler
--------
- [Added tier 2* support for `armv7a-none-eabi`.][68253]
- [Added tier 2 support for `riscv64gc-unknown-linux-gnu`.][68339]
- [`Option::{expect,unwrap}` and
   `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages
   pointing to the location where they were called, rather than
   `core`'s internals. ][67887]

* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.

Libraries
---------
- [`iter::Empty<T>` now implements `Send` and `Sync` for any `T`.][68348]
- [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type
   to implement `Sized`.][67935]
- [`io::Cursor` now derives `PartialEq` and `Eq`.][67233]
- [`Layout::new` is now `const`.][66254]
- [Added Standard Library support for `riscv64gc-unknown-linux-gnu`.][66899]


Stabilized APIs
---------------
- [`CondVar::wait_while`]
- [`CondVar::wait_timeout_while`]
- [`DebugMap::key`]
- [`DebugMap::value`]
- [`ManuallyDrop::take`]
- [`matches!`]
- [`ptr::slice_from_raw_parts_mut`]
- [`ptr::slice_from_raw_parts`]

Cargo
-----
- [You no longer need to include `extern crate proc_macro;` to be able to
  `use proc_macro;` in the `2018` edition.][cargo/7700]

Compatibility Notes
-------------------
- [`Error::description` has been deprecated, and its use will now produce a
  warning.][66919] It's recommended to use `Display`/`to_string` instead.
- [`use $crate;` inside macros is now a hard error.][37390] The compiler
  emitted forward compatibility warnings since Rust 1.14.0.
- [As previously announced, this release reduces the level of support for
  32-bit Apple targets to tier 3.][apple-32bit-drop]. This means that the
  source code is still available to build, but the targets are no longer tested
  and no release binary is distributed by the Rust project. Please refer to the
  linked blog post for more information.

[37390]: rust-lang/rust#37390
[68253]: rust-lang/rust#68253
[68348]: rust-lang/rust#68348
[67935]: rust-lang/rust#67935
[68339]: rust-lang/rust#68339
[68122]: rust-lang/rust#68122
[67712]: rust-lang/rust#67712
[67887]: rust-lang/rust#67887
[67131]: rust-lang/rust#67131
[67233]: rust-lang/rust#67233
[66899]: rust-lang/rust#66899
[66919]: rust-lang/rust#66919
[66254]: rust-lang/rust#66254
[cargo/7700]: rust-lang/cargo#7700
[`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key
[`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value
[`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take
[`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html
[`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html
[`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html
[`CondVar::wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while
[`CondVar::wait_timeout_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_timeout_while
flip1995 pushed a commit to flip1995/rust-clippy that referenced this pull request May 5, 2020
Changes:
````
Treat more strange pattern
Split up `if_same_then_else` ui test
Apply review comments
Run `update_lints`
Reduce span range
Rename `ok_if_let` to `if_let_some_result`
Apply review comments
Add suggestion in `if_let_some_result`
rustup rust-lang/rust#67712
Allow `unused_self` lint at the function level
Downgrade range_plus_one to pedantic
Rustup to rust-lang/rust#68204
Add lifetimes to `LateLintPass`
Fix rustc lint import paths generated by `new_lint`
Add lint for default lint description
Update documentation for adding new lints
Generate new lints easily
Split up `booleans` ui test
Fix the ordering on `nonminimal_bool`
````
@cdecompilador
Copy link
Copy Markdown

How will this work with string slices?

@oli-obk
Copy link
Copy Markdown
Contributor

oli-obk commented Jul 12, 2021

This feature is for array slices. If you want to talk about string slices, I think the internals forum would be the right place. This issue has been closed for over a year, please consider opening a new issue once a github issue becomes the right place.

msk pushed a commit to msk/pkgsrc that referenced this pull request May 11, 2026
Version 1.42.0 (2020-03-12)
==========================

Language
--------
- [You can now use the slice pattern syntax with subslices.][67712] e.g.
  ```rust
  fn foo(words: &[&str]) {
      match words {
          ["Hello", "World", "!", ..] => println!("Hello World!"),
          ["Foo", "Bar", ..] => println!("Baz"),
          rest => println!("{:?}", rest),
      }
  }
  ```
- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
  that you can create an enum that has the exact layout and ABI of the type
  it contains.
- [There are some *syntax-only* changes:][67131]
   - `default` is syntactically allowed before items in `trait` definitions.
   - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
     leave out their bodies in favor of `;`.
   - Bounds on associated types in `impl`s are now syntactically allowed
     (e.g. `type Foo: Ord;`).
   - `...` (the C-variadic type) may occur syntactically directly as the type of
      any function parameter.

  These are still rejected *semantically*, so you will likely receive an error
  but these changes can be seen and parsed by procedural macros and
  conditional compilation.

Compiler
--------
- [Added tier 2* support for `armv7a-none-eabi`.][68253]
- [Added tier 2 support for `riscv64gc-unknown-linux-gnu`.][68339]
- [`Option::{expect,unwrap}` and
   `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages
   pointing to the location where they were called, rather than
   `core`'s internals. ][67887]

* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.

Libraries
---------
- [`iter::Empty<T>` now implements `Send` and `Sync` for any `T`.][68348]
- [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type
   to implement `Sized`.][67935]
- [`io::Cursor` now derives `PartialEq` and `Eq`.][67233]
- [`Layout::new` is now `const`.][66254]
- [Added Standard Library support for `riscv64gc-unknown-linux-gnu`.][66899]


Stabilized APIs
---------------
- [`CondVar::wait_while`]
- [`CondVar::wait_timeout_while`]
- [`DebugMap::key`]
- [`DebugMap::value`]
- [`ManuallyDrop::take`]
- [`matches!`]
- [`ptr::slice_from_raw_parts_mut`]
- [`ptr::slice_from_raw_parts`]

Cargo
-----
- [You no longer need to include `extern crate proc_macro;` to be able to
  `use proc_macro;` in the `2018` edition.][cargo/7700]

Compatibility Notes
-------------------
- [`Error::description` has been deprecated, and its use will now produce a
  warning.][66919] It's recommended to use `Display`/`to_string` instead.
- [`use $crate;` inside macros is now a hard error.][37390] The compiler
  emitted forward compatibility warnings since Rust 1.14.0.
- [As previously announced, this release reduces the level of support for
  32-bit Apple targets to tier 3.][apple-32bit-drop]. This means that the
  source code is still available to build, but the targets are no longer tested
  and no release binary is distributed by the Rust project. Please refer to the
  linked blog post for more information.

[37390]: rust-lang/rust#37390
[68253]: rust-lang/rust#68253
[68348]: rust-lang/rust#68348
[67935]: rust-lang/rust#67935
[68339]: rust-lang/rust#68339
[68122]: rust-lang/rust#68122
[67712]: rust-lang/rust#67712
[67887]: rust-lang/rust#67887
[67131]: rust-lang/rust#67131
[67233]: rust-lang/rust#67233
[66899]: rust-lang/rust#66899
[66919]: rust-lang/rust#66919
[66254]: rust-lang/rust#66254
[cargo/7700]: rust-lang/cargo#7700
[`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key
[`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value
[`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take
[`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html
[`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html
[`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html
[`CondVar::wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while
[`CondVar::wait_timeout_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_timeout_while
jperkin added a commit to TritonDataCenter/pkgsrc that referenced this pull request May 14, 2026
Version 1.42.0 (2020-03-12)
==========================

Language
--------
- [You can now use the slice pattern syntax with subslices.][67712] e.g.
  ```rust
  fn foo(words: &[&str]) {
      match words {
          ["Hello", "World", "!", ..] => println!("Hello World!"),
          ["Foo", "Bar", ..] => println!("Baz"),
          rest => println!("{:?}", rest),
      }
  }
  ```
- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
  that you can create an enum that has the exact layout and ABI of the type
  it contains.
- [There are some *syntax-only* changes:][67131]
   - `default` is syntactically allowed before items in `trait` definitions.
   - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
     leave out their bodies in favor of `;`.
   - Bounds on associated types in `impl`s are now syntactically allowed
     (e.g. `type Foo: Ord;`).
   - `...` (the C-variadic type) may occur syntactically directly as the type of
      any function parameter.

  These are still rejected *semantically*, so you will likely receive an error
  but these changes can be seen and parsed by procedural macros and
  conditional compilation.

Compiler
--------
- [Added tier 2* support for `armv7a-none-eabi`.][68253]
- [Added tier 2 support for `riscv64gc-unknown-linux-gnu`.][68339]
- [`Option::{expect,unwrap}` and
   `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages
   pointing to the location where they were called, rather than
   `core`'s internals. ][67887]

* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.

Libraries
---------
- [`iter::Empty<T>` now implements `Send` and `Sync` for any `T`.][68348]
- [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type
   to implement `Sized`.][67935]
- [`io::Cursor` now derives `PartialEq` and `Eq`.][67233]
- [`Layout::new` is now `const`.][66254]
- [Added Standard Library support for `riscv64gc-unknown-linux-gnu`.][66899]


Stabilized APIs
---------------
- [`CondVar::wait_while`]
- [`CondVar::wait_timeout_while`]
- [`DebugMap::key`]
- [`DebugMap::value`]
- [`ManuallyDrop::take`]
- [`matches!`]
- [`ptr::slice_from_raw_parts_mut`]
- [`ptr::slice_from_raw_parts`]

Cargo
-----
- [You no longer need to include `extern crate proc_macro;` to be able to
  `use proc_macro;` in the `2018` edition.][cargo/7700]

Compatibility Notes
-------------------
- [`Error::description` has been deprecated, and its use will now produce a
  warning.][66919] It's recommended to use `Display`/`to_string` instead.
- [`use $crate;` inside macros is now a hard error.][37390] The compiler
  emitted forward compatibility warnings since Rust 1.14.0.
- [As previously announced, this release reduces the level of support for
  32-bit Apple targets to tier 3.][apple-32bit-drop]. This means that the
  source code is still available to build, but the targets are no longer tested
  and no release binary is distributed by the Rust project. Please refer to the
  linked blog post for more information.

[37390]: rust-lang/rust#37390
[68253]: rust-lang/rust#68253
[68348]: rust-lang/rust#68348
[67935]: rust-lang/rust#67935
[68339]: rust-lang/rust#68339
[68122]: rust-lang/rust#68122
[67712]: rust-lang/rust#67712
[67887]: rust-lang/rust#67887
[67131]: rust-lang/rust#67131
[67233]: rust-lang/rust#67233
[66899]: rust-lang/rust#66899
[66919]: rust-lang/rust#66919
[66254]: rust-lang/rust#66254
[cargo/7700]: rust-lang/cargo#7700
[`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key
[`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value
[`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take
[`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html
[`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html
[`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html
[`CondVar::wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while
[`CondVar::wait_timeout_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_timeout_while
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.