Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] implement explicit deref patterns through k#deref #119467

Closed
wants to merge 9 commits into from

Conversation

fee1-dead
Copy link
Member

@fee1-dead fee1-dead commented Dec 31, 2023

Some technical considerations: (feel free to add to the list)

  1. The first commits in this PR are based on Treat k#ident keywords as valid tokens #119351, adding support for the k#ident syntax.
  2. Variants added: ast::PatKind::Deref, hir::PatKind::Deref, thir::PatKind::DerefPattern, mir::TestKind::Deref.
  3. We use Deref for now, but we might want a different trait (DerefPure) later.
  4. In typeck, we deref the expected (input type of the expression) type exactly once for simplicity, and then type check the inner pattern with <expected as Deref>::Target. Doing multiple derefs with a single k#deref isn't supported for now, and we might want to explore how to do implicit/multiple derefs later.
  5. The actual codegen first takes the place being matched (let us call that place), creates a temporary references &place, then calls deref. (place2 = Deref::deref(&place)). The inner patterns then use (*place2) for continued matching. This means: (TODO: add test for types that cannot be moved out)
match vec![1] {
    k#deref [x] => {} // `x` here has type `i32`, not `&i32`
}
  1. We skip generating false edges from or to arms with deref patterns. This behavior should be fixed before this PR actually get merged, since it means that any unreachable arm under deref patterns would not be borrowcked. (see the vec-2.rs test for this) Clarification: skipping false edges are done because deref patterns generate temporaries that are used to create bindings. When false edges are generated for deref patterns the temporaries don't get assigned to since they are assigned to during the tests and not before an arm block starts, which lead to borrowck errors.
  2. The key to the matching algorithm is in sort_candidate, where we replace the original match pair of PatKind::DerefPattern with the inner pattern on the new temporary created by the deref. Note that since sort_candidate can be called on multiple candidates after a test is performed, we need to ensure that the peeling of deref pattern on a match pair only happens once (through is_first), so that the subsequent match arms all do their derefs individually and get tested individually.
  3. The current impl only does Deref as being deliberately minimal. We would want to figure out the binding mode and try doing the appropriate deref in the future.
  4. There is no guarantee that only a single deref occurs. In fact, point 7, through is_first is opposed to this idea. We'd probably want to explore whether is_first is really necessary with more testing.

cc @compiler-errors @BoxyUwU @Nadrieril @matthewjasper @tgross35 @CAD97 (would like to hear from you about the implementation)

@rustbot
Copy link
Collaborator

rustbot commented Dec 31, 2023

r? @petrochenkov

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Dec 31, 2023
@fee1-dead fee1-dead changed the title [WIP] implement deref patterns through k#deref [WIP] implement explicit deref patterns through k#deref Dec 31, 2023
@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
    Checking same-file v1.0.6
    Checking crossbeam-channel v0.5.8
    Checking term v0.7.0
    Checking color-eyre v0.6.2
error[E0004]: non-exhaustive patterns: `rustc_hir::PatKind::Deref(_)` not covered
    --> src/tools/clippy/clippy_utils/src/hir_utils.rs:959:15
959  |         match pat.kind {
959  |         match pat.kind {
     |               ^^^^^^^^ pattern `rustc_hir::PatKind::Deref(_)` not covered
note: `rustc_hir::PatKind<'_>` defined here
    --> /checkout/compiler/rustc_hir/src/hir.rs:1152:1
     |
     |
1152 | pub enum PatKind<'hir> {
...
...
1193 |     Deref(&'hir Pat<'hir>),
     = note: the matched value is of type `rustc_hir::PatKind<'_>`
     = note: the matched value is of type `rustc_hir::PatKind<'_>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
     |
1020 ~             PatKind::Never | PatKind::Wild => {},
1021 ~             rustc_hir::PatKind::Deref(_) => todo!(),

    Checking rustc_version v0.4.0
    Checking getopts v0.2.21
    Checking comma v1.0.0
    Checking comma v1.0.0
    Checking bytes v1.4.0
    Checking levenshtein v1.0.5
    Checking ui_test v0.21.2
    Checking tester v0.9.1
error[E0004]: non-exhaustive patterns: `rustc_hir::PatKind::Deref(_)` not covered
     |
1708 |     match pat.kind {
1708 |     match pat.kind {
     |           ^^^^^^^^ pattern `rustc_hir::PatKind::Deref(_)` not covered
note: `rustc_hir::PatKind<'_>` defined here
    --> /checkout/compiler/rustc_hir/src/hir.rs:1152:1
     |
     |
1152 | pub enum PatKind<'hir> {
...
...
1193 |     Deref(&'hir Pat<'hir>),
     = note: the matched value is of type `rustc_hir::PatKind<'_>`
     = note: the matched value is of type `rustc_hir::PatKind<'_>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1735 ~         },
1735 ~         },
1736 ~         rustc_hir::PatKind::Deref(_) => todo!(),

For more information about this error, try `rustc --explain E0004`.
error: could not compile `clippy_utils` (lib) due to 2 previous errors
warning: build failed, waiting for other jobs to finish...

@petrochenkov
Copy link
Contributor

r? compiler
I'm overloaded with reviews.

@rustbot rustbot assigned WaffleLapkin and unassigned petrochenkov Dec 31, 2023
@petrochenkov
Copy link
Contributor

petrochenkov commented Dec 31, 2023

Also, k#ident is an even worse hack than r#ident.
If context-sensitive keywords don't work in this position, use something like do yeet or builtin #.

@fee1-dead
Copy link
Member Author

re k#ident: I will change this soon.

For point number 6, Nadrieril suggested that we do the Deref more than once: one when we do the test, to allow subsequent tests to match on the deref temporary, and do it again when pre-binding, for the false edges to work correctly. This would be unsound if we used Deref, which is a safe trait, but would not be an issue once we switch to using DerefPure.

@WaffleLapkin
Copy link
Member

@petrochenkov I don't think I agree. k# and r# are basically identical. Moreover k#something is oftentimes used as a placeholder by T-lang when designing stuff, so it's not taken from nowhere (I think they even wanted to use it for actual feature prototypes, although we never went along with it so far...).

I think it should be totally fine as a placeholder here and can't really see any issues...

@bors
Copy link
Contributor

bors commented Jan 4, 2024

☔ The latest upstream changes (presumably #119578) made this pull request unmergeable. Please resolve the merge conflicts.

@WaffleLapkin WaffleLapkin added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 12, 2024
@Nadrieril Nadrieril added the F-deref_patterns `#![feature(deref_patterns)]` label Mar 8, 2024
@fee1-dead
Copy link
Member Author

closing in favor of #122222.

@fee1-dead fee1-dead closed this Mar 15, 2024
@fee1-dead fee1-dead deleted the derefpat branch March 15, 2024 05:02
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 21, 2024
…r=compiler-errors

deref patterns: bare-bones feature gate and typechecking

I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [`@cramertj` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this `@cramertj?).` Tracking issue: rust-lang#87121.

This is the barest-bones implementation I could think of:
- explicit syntax, reusing `box <pat>` because that saves me a ton of work;
- use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`);
- no support for mutable patterns with `DerefMut` for now;
- MIR lowering will come in the next PR. It's the trickiest part.

My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon.

This is in large part salvaged from `@fee1-dead's` rust-lang#119467.

r? `@compiler-errors`
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Mar 21, 2024
…r=compiler-errors

deref patterns: bare-bones feature gate and typechecking

I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [``@cramertj`` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ``@cramertj?).`` Tracking issue: rust-lang#87121.

This is the barest-bones implementation I could think of:
- explicit syntax, reusing `box <pat>` because that saves me a ton of work;
- use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`);
- no support for mutable patterns with `DerefMut` for now;
- MIR lowering will come in the next PR. It's the trickiest part.

My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon.

This is in large part salvaged from ``@fee1-dead's`` rust-lang#119467.

r? ``@compiler-errors``
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 21, 2024
…r=compiler-errors

deref patterns: bare-bones feature gate and typechecking

I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [```@cramertj``` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ```@cramertj?).``` Tracking issue: rust-lang#87121.

This is the barest-bones implementation I could think of:
- explicit syntax, reusing `box <pat>` because that saves me a ton of work;
- use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`);
- no support for mutable patterns with `DerefMut` for now;
- MIR lowering will come in the next PR. It's the trickiest part.

My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon.

This is in large part salvaged from ```@fee1-dead's``` rust-lang#119467.

r? ```@compiler-errors```
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 21, 2024
…r=compiler-errors

deref patterns: bare-bones feature gate and typechecking

I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [````@cramertj```` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ````@cramertj?).```` Tracking issue: rust-lang#87121.

This is the barest-bones implementation I could think of:
- explicit syntax, reusing `box <pat>` because that saves me a ton of work;
- use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`);
- no support for mutable patterns with `DerefMut` for now;
- MIR lowering will come in the next PR. It's the trickiest part.

My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon.

This is in large part salvaged from ````@fee1-dead's```` rust-lang#119467.

r? ````@compiler-errors````
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Mar 21, 2024
Rollup merge of rust-lang#122222 - Nadrieril:deref-pat-feature-gate, r=compiler-errors

deref patterns: bare-bones feature gate and typechecking

I am restarting the deref patterns experimentation. This introduces a feature gate under the lang-team [experimental feature](https://github.com/rust-lang/lang-team/blob/master/src/how_to/experiment.md) process, with [````@cramertj```` as lang-team liaison](rust-lang/lang-team#88) (it's been a while though, you still ok with this ````@cramertj?).```` Tracking issue: rust-lang#87121.

This is the barest-bones implementation I could think of:
- explicit syntax, reusing `box <pat>` because that saves me a ton of work;
- use `Deref` as a marker trait (instead of a yet-to-design `DerefPure`);
- no support for mutable patterns with `DerefMut` for now;
- MIR lowering will come in the next PR. It's the trickiest part.

My goal is to let us figure out the MIR lowering part, which might take some work. And hopefully get something working for std types soon.

This is in large part salvaged from ````@fee1-dead's```` rust-lang#119467.

r? ````@compiler-errors````
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-deref_patterns `#![feature(deref_patterns)]` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants