-
Notifications
You must be signed in to change notification settings - Fork 13.3k
literal pattern lowering: use the pattern's type instead of the literal's in const_to_pat
#138992
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
Conversation
This allows us to remove the field `treat_byte_string_as_slice` from `TypeckResults`, since the pattern's type contains everything necessary to get the correct lowering for byte string literal patterns. This leaves the implementation of `string_deref_patterns` broken, to be fixed in the next commit.
Some changes occurred in match checking cc @Nadrieril |
Actually, maybe it would make more sense for this to only use the pattern type for byte string literals. It's hacky either way, but for Edit:
On a technical level at least, this does seem to work; nothing's stopping a |
Since |
The one awkward thing I can see with that is that errors for trying to use non- Footnotes
|
Pretty sure valtree construction fails on String. Const to pat never sees it |
That's what I would have thought, since I'd expect it to have a pointer in it, but debug logging for Branch([Branch([Branch([Branch([Branch([Branch([Leaf(0x0000000000000001)]), Branch([])]), Branch([Leaf(0x0000000000000000)]), Branch([])]), Branch([])]), Leaf(0x0000000000000000)])]) The check/error for structural equality is in Maybe there's a bug in valtree construction and it's not getting stopped where it should? |
Ah, I stand corrected. Thank you
Hmm... Funny wrt Vec being the non struct eq type. So yea, we should try moving the struct eq checks into valtree creation. Maybe not in this PR tho. I think we can land your PR as is, but I think we'll need some more tests. Consts of |
I've added some tests for those cases, as well as for consts of types
I'll see how easy it would be to move the structural equality checks to valtree creation in another PR. |
// See also `tests/ui/match/pattern-deref-miscompile.rs`, which tests that byte string literal | ||
// patterns check slices' length appropriately when matching on slices. | ||
match BSTR_UNSIZED { | ||
BSTR_SIZED => {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the difference in the repr between this and mentioning the pattern inline that causes this error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be these lines in the literal pattern checking rules. Byte string literal patterns are assigned a slice reference type if the current scrutinee is known to be a slice reference, and otherwise default to the type of the literal (an array reference). Since that link's from the master
branch, that's also where treat_byte_string_as_slice
was assigned. There's no array unsizing logic for named constant patterns (type-checking code here), so it fails to unify &[u8]
with &[u8;3]
. If, hypothetically, that was special-cased, and the pattern was assigned the type &[u8]
rather than the constant's type, then that example would work too (though without the change this PR makes, it'd also have to set treat_byte_string_as_slice
or it'd be missing length checks).
Thanks, I'm convinced now there are no issues with this change @bors r+ |
…, r=oli-obk literal pattern lowering: use the pattern's type instead of the literal's in `const_to_pat` This has two purposes: - First, it enables removing the `treat_byte_string_as_slice` fields from `TypeckResults` and `ConstToPat`. A byte string pattern's type will be `&[u8]` when matching on a slice reference, so `const_to_pat` will lower it to a slice ref pattern. I believe this is tested by `tests/ui/match/pattern-deref-miscompile.rs`. - Second, it will simplify the implementation of byte string literals in deref patterns. If byte string patterns can be given the type `[u8; N]` or `[u8]` during HIR typeck, then nothing needs to be changed in `const_to_pat` in order to lower the patterns `deref!(b"..."): Vec<u8>` and `deref!(b"..."): Box<[u8; 3]>`. Implementation-wise, this uses `lit_to_const` to make a const with the pattern's type and the literal's valtree; that feels to me like the best way to make sure that the valtree representations of the pattern type and literal are the same. Though it may necessitate later changes to `lit_to_const` to accommodate giving byte string literal patterns non-reference types—would that be reasonable? This unfortunately doesn't work for the `string_deref_patterns` feature (since that gives string literal patterns the `String` type), so I added a workaround for that. However, once `deref_patterns` supports string literals, it may be able to replace `string_deref_patterns`; the special case for `String` can removed at that point. r? `@oli-obk`
…iaskrgr Rollup of 6 pull requests Successful merges: - rust-lang#138992 (literal pattern lowering: use the pattern's type instead of the literal's in `const_to_pat`) - rust-lang#139211 (interpret: add a version of run_for_validation for &self) - rust-lang#139235 (`AstValidator` tweaks) - rust-lang#139237 (Add a dep kind for use of the anon node with zero dependencies) - rust-lang#139260 (Add dianqk to codegen reviewers) - rust-lang#139264 (Fix two incorrect turbofish suggestions) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#138992 - dianne:simplify-byte-string-to-pat, r=oli-obk literal pattern lowering: use the pattern's type instead of the literal's in `const_to_pat` This has two purposes: - First, it enables removing the `treat_byte_string_as_slice` fields from `TypeckResults` and `ConstToPat`. A byte string pattern's type will be `&[u8]` when matching on a slice reference, so `const_to_pat` will lower it to a slice ref pattern. I believe this is tested by `tests/ui/match/pattern-deref-miscompile.rs`. - Second, it will simplify the implementation of byte string literals in deref patterns. If byte string patterns can be given the type `[u8; N]` or `[u8]` during HIR typeck, then nothing needs to be changed in `const_to_pat` in order to lower the patterns `deref!(b"..."): Vec<u8>` and `deref!(b"..."): Box<[u8; 3]>`. Implementation-wise, this uses `lit_to_const` to make a const with the pattern's type and the literal's valtree; that feels to me like the best way to make sure that the valtree representations of the pattern type and literal are the same. Though it may necessitate later changes to `lit_to_const` to accommodate giving byte string literal patterns non-reference types—would that be reasonable? This unfortunately doesn't work for the `string_deref_patterns` feature (since that gives string literal patterns the `String` type), so I added a workaround for that. However, once `deref_patterns` supports string literals, it may be able to replace `string_deref_patterns`; the special case for `String` can removed at that point. r? ``@oli-obk``
`deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns When `deref_patterns` is enabled, this allows string literal patterns to be used where `str` is expected and byte string literal patterns to be used where `[u8]` or `[u8; N]` is expected. This lets them be used in explicit `deref!("...")` patterns to match on `String`, `Box<str>`, `Vec<u8>`, `Box<[u8;N]>`, etc. (as well as to match on slices and arrays obtained through other means). Implementation-wise, this follows up on rust-lang#138992: similar to how byte string literals matching on `&[u8]` is implemented, this changes the type of the patterns as determined by HIR typeck, which informs const-to-pat on how to translate them to THIR (though strings needed a bit of extra work since we need references to call `<str as PartialEq>::eq` in the MIR lowering for string equality tests). This PR does not add support for implicit deref pattern syntax (e.g. `"..."` matching on `String`, as `string_deref_patterns` allows). I have that implemented locally, but I'm saving it for a follow-up PR[^1]. This also does not add support for using named or associated constants of type `&str` where `str` is expected (nor likewise with named byte string constants). It'd be possible to add that if there's an appetite for it, but I figure it's simplest to start with literals. This is gated by the `deref_patterns` feature since it's motivated by deref patterns. That said, its impact reaches outside of deref patterns; it may warrant a separate experiment and feature gate, particularly factoring in the follow-up[^1]. Even without deref patterns, I think there's probably motivation for these changes. The update to the unstable book added by this will conflict with rust-lang#140022, so they shouldn't be merged at the same time. Tracking issue for deref patterns: rust-lang#87121 r? `@oli-obk` cc `@Nadrieril` [^1]: The piece missing from this PR to support implicit deref pattern syntax is to allow string literal patterns to implicitly dereference their scrutinees before matching (see rust-lang#44849). As a consequence, it also makes examples like the one in that issue work (though it's still gated by `deref_patterns`). I can provide more information on how I've implemented it or open a draft if it'd help in reviewing this PR.
`deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns When `deref_patterns` is enabled, this allows string literal patterns to be used where `str` is expected and byte string literal patterns to be used where `[u8]` or `[u8; N]` is expected. This lets them be used in explicit `deref!("...")` patterns to match on `String`, `Box<str>`, `Vec<u8>`, `Box<[u8;N]>`, etc. (as well as to match on slices and arrays obtained through other means). Implementation-wise, this follows up on rust-lang#138992: similar to how byte string literals matching on `&[u8]` is implemented, this changes the type of the patterns as determined by HIR typeck, which informs const-to-pat on how to translate them to THIR (though strings needed a bit of extra work since we need references to call `<str as PartialEq>::eq` in the MIR lowering for string equality tests). This PR does not add support for implicit deref pattern syntax (e.g. `"..."` matching on `String`, as `string_deref_patterns` allows). I have that implemented locally, but I'm saving it for a follow-up PR[^1]. This also does not add support for using named or associated constants of type `&str` where `str` is expected (nor likewise with named byte string constants). It'd be possible to add that if there's an appetite for it, but I figure it's simplest to start with literals. This is gated by the `deref_patterns` feature since it's motivated by deref patterns. That said, its impact reaches outside of deref patterns; it may warrant a separate experiment and feature gate, particularly factoring in the follow-up[^1]. Even without deref patterns, I think there's probably motivation for these changes. The update to the unstable book added by this will conflict with rust-lang#140022, so they shouldn't be merged at the same time. Tracking issue for deref patterns: rust-lang#87121 r? ``@oli-obk`` cc ``@Nadrieril`` [^1]: The piece missing from this PR to support implicit deref pattern syntax is to allow string literal patterns to implicitly dereference their scrutinees before matching (see rust-lang#44849). As a consequence, it also makes examples like the one in that issue work (though it's still gated by `deref_patterns`). I can provide more information on how I've implemented it or open a draft if it'd help in reviewing this PR.
Rollup merge of rust-lang#140028 - dianne:lit-deref-pats-p1, r=oli-obk `deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns When `deref_patterns` is enabled, this allows string literal patterns to be used where `str` is expected and byte string literal patterns to be used where `[u8]` or `[u8; N]` is expected. This lets them be used in explicit `deref!("...")` patterns to match on `String`, `Box<str>`, `Vec<u8>`, `Box<[u8;N]>`, etc. (as well as to match on slices and arrays obtained through other means). Implementation-wise, this follows up on rust-lang#138992: similar to how byte string literals matching on `&[u8]` is implemented, this changes the type of the patterns as determined by HIR typeck, which informs const-to-pat on how to translate them to THIR (though strings needed a bit of extra work since we need references to call `<str as PartialEq>::eq` in the MIR lowering for string equality tests). This PR does not add support for implicit deref pattern syntax (e.g. `"..."` matching on `String`, as `string_deref_patterns` allows). I have that implemented locally, but I'm saving it for a follow-up PR[^1]. This also does not add support for using named or associated constants of type `&str` where `str` is expected (nor likewise with named byte string constants). It'd be possible to add that if there's an appetite for it, but I figure it's simplest to start with literals. This is gated by the `deref_patterns` feature since it's motivated by deref patterns. That said, its impact reaches outside of deref patterns; it may warrant a separate experiment and feature gate, particularly factoring in the follow-up[^1]. Even without deref patterns, I think there's probably motivation for these changes. The update to the unstable book added by this will conflict with rust-lang#140022, so they shouldn't be merged at the same time. Tracking issue for deref patterns: rust-lang#87121 r? ``@oli-obk`` cc ``@Nadrieril`` [^1]: The piece missing from this PR to support implicit deref pattern syntax is to allow string literal patterns to implicitly dereference their scrutinees before matching (see rust-lang#44849). As a consequence, it also makes examples like the one in that issue work (though it's still gated by `deref_patterns`). I can provide more information on how I've implemented it or open a draft if it'd help in reviewing this PR.
This has two purposes:
treat_byte_string_as_slice
fields fromTypeckResults
andConstToPat
. A byte string pattern's type will be&[u8]
when matching on a slice reference, soconst_to_pat
will lower it to a slice ref pattern. I believe this is tested bytests/ui/match/pattern-deref-miscompile.rs
.[u8; N]
or[u8]
during HIR typeck, then nothing needs to be changed inconst_to_pat
in order to lower the patternsderef!(b"..."): Vec<u8>
andderef!(b"..."): Box<[u8; 3]>
.Implementation-wise, this uses
lit_to_const
to make a const with the pattern's type and the literal's valtree; that feels to me like the best way to make sure that the valtree representations of the pattern type and literal are the same. Though it may necessitate later changes tolit_to_const
to accommodate giving byte string literal patterns non-reference types—would that be reasonable?This unfortunately doesn't work for the
string_deref_patterns
feature (since that gives string literal patterns theString
type), so I added a workaround for that. However, oncederef_patterns
supports string literals, it may be able to replacestring_deref_patterns
; the special case forString
can removed at that point.r? @oli-obk