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

Fully destructure slice and array constants into patterns #77390

Closed
wants to merge 7 commits into from

Conversation

oli-obk
Copy link
Contributor

@oli-obk oli-obk commented Oct 1, 2020

There were a lot of workarounds for making such constants not opaque, now we expand all constants into patterns unless they are not structural match

@rust-highfive
Copy link
Collaborator

r? @varkor

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 1, 2020
@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 1, 2020

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Oct 1, 2020

⌛ Trying commit 14a0b10 with merge 6f61447b8e9a5d5b75684be6181567232aced705...

@bors
Copy link
Contributor

bors commented Oct 1, 2020

☀️ Try build successful - checks-actions, checks-azure
Build commit: 6f61447b8e9a5d5b75684be6181567232aced705 (6f61447b8e9a5d5b75684be6181567232aced705)

@rust-timer
Copy link
Collaborator

Queued 6f61447b8e9a5d5b75684be6181567232aced705 with parent 00730fd, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (6f61447b8e9a5d5b75684be6181567232aced705): comparison url.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying rollup- to bors.

Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up.

@bors rollup=never

@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 2, 2020

ok, this is a perf improvement across the board. Unless people start putting include_bytes!(some_humongous_file) into constants used in patterns we're going to be fine. And if they do, we can always add an arbitrary limit after which we treat a slice/array constant as opaque

ready for review @varkor

// (ty::ConstKind::Value(ConstValue::ByRef { .. }), ty::Slice(_)) => { ... }
_ => Some(ConstantValue(value)),
}
Some(ConstantValue(value))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related to exhaustiveness checking? Shouldn't opaque consts be treated as matching nothing for that as they might not be structural-match?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is, very good catch. We still need a variant for string slices here, as string slices are not opaque, but ConstantValue is gone now and the replacement Str only handles &str constants. There are further improvements we can do here now that everything is explicit, but I'd rather not touch compare_const_vals in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should note that I understand basically nothing of this code, if I caught anything that was an accident.^^

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if the last 2 comments are bugfixes, is it possible to add a test?

Copy link
Contributor Author

@oli-obk oli-obk Oct 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was no bugfix, no behaviour was changed, all I did was to move the bail-out (that was guaranteed to happen later) to an earlier site so the rest of the code that I was able to remove became dead code. This PR generally is mostly just removing dead code that became obsolete after destructuring all structural-eq constants into (non-const) patterns. This means except for &str, all PatKind::Const are now opaque.

Edit: they were behaving opaquely before already, but there was lots of code making sure we didn't run into ICEs around them by bailing out as "not contributing to exhaustiveness".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Maybe add some doc comments to PatKind explaining this. :)

@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 2, 2020

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Oct 2, 2020

⌛ Trying commit 638a29f7e10dae8d154fc4c7624ed8b0ea33df8a with merge be5d6894699da44f42b10af9e2afd5a423ca67d0...

/// Literal values.
ConstantValue(&'tcx ty::Const<'tcx>),
/// String literals
Str(&'tcx ty::Const<'tcx>),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so this type is indeed only used for exhaustiveness checking, that's why we do not need consts in here? Maybe add that to the type doccomment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are strings special here?

@bors
Copy link
Contributor

bors commented Oct 2, 2020

☀️ Try build successful - checks-actions, checks-azure
Build commit: be5d6894699da44f42b10af9e2afd5a423ca67d0 (be5d6894699da44f42b10af9e2afd5a423ca67d0)

@rust-timer
Copy link
Collaborator

Queued be5d6894699da44f42b10af9e2afd5a423ca67d0 with parent 154f1f5, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (be5d6894699da44f42b10af9e2afd5a423ca67d0): comparison url.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying rollup- to bors.

Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up.

@bors rollup=never

@varkor
Copy link
Member

varkor commented Oct 10, 2020

Once there's a comment explaining why strings are special, this should be good.
cc @Nadrieril, who might have comments.

@RalfJung
Copy link
Member

Once there's a comment explaining why strings are special, this should be good.
cc @Nadrieril, who might have comments.

I hope Oli can also add a comment clarifying this. :)

@Nadrieril
Copy link
Member

Omg yes you removed slice_pat_covered_by_const! I hated that function. I'm happy about this, const handling was a major source of complexity.
If I understand correctly, what you're doing is removing code that is now dead since #70743? I haven't read that PR in enough detail to check if all the code you're removing is inaccessible.

ty::Bool => {
[true, false].iter().map(|&b| ConstantValue(ty::Const::from_bool(cx.tcx, b))).collect()
}
ty::Bool => vec![make_range(0, 1)],
ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => {
Copy link
Member

@Nadrieril Nadrieril Oct 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this affect diagnostics? I'd expect this would display "pattern 0 not covered" instead of "pattern false not covered", but that would clearly be caught by the tests. I don't understand what piece of code makes it so it doesn't.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had also wondered this, but assumed this would be caught by tests, so it must have been okay. But you're right that it would be better to understand this (and add a comment).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because while decisions are made on Constructors, they do not directly flow into diagnostics. Instead diagnostics are reported on Pats in https://github.com/rust-lang/rust/blob/6553d38bcb0c9193808ae93db8bd95bcf4c4824a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs

@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 12, 2020

If I understand correctly, what you're doing is removing code that is now dead since #70743? I haven't read that PR in enough detail to check if all the code you're removing is inaccessible.

Well, I also made a small change here (&[u8] and &[u8; N] constants get converted into slice patterns, thus leaving no constants but &str or opaque constants as PatKind::Const). This allowed all of that code to become dead, but parts of it were already dead after #70743

@varkor
Copy link
Member

varkor commented Oct 12, 2020

I'm concerned by #77390 (comment). I think we should delay merging this until @Nadrieril's concerns have been addressed.

@bors r-

@bors bors 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Oct 12, 2020
@Nadrieril
Copy link
Member

Well, I also made a small change here (&[u8] and &[u8; N] constants get converted into slice patterns, thus leaving no constants but &str or opaque constants as PatKind::Const). This allowed all of that code to become dead, but parts of it were already dead after #70743

Wait, integer and float ranges are still PatKind::Const, right?

@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 12, 2020

Wait, integer and float ranges are still PatKind::Const, right?

hmm yes, oops, forgot about those. Booleans and chars, too.

@@ -158,6 +158,9 @@ crate enum PatKind<'tcx> {
subpattern: Pat<'tcx>,
},

/// Opaque constant. This will be treated as a single, but unknown value.
/// Except for `&str`, which will be handled as a string pattern and thus exhaustiveness
/// checking will detect if you use the same string twice in different patterns.
Constant {
Copy link
Member

@Nadrieril Nadrieril Oct 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should also mention int ranges etc then

@RalfJung
Copy link
Member

I'm concerned by #77390 (comment). I think we should delay merging this until @Nadrieril's concerns have been addressed.

CI is already running, so you also need to
@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 12, 2020
@oli-obk oli-obk removed the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Oct 12, 2020
@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 15, 2020

@Nadrieril can you help me with the latest commit? I have absolutely no clue how to create a Constructor::Opaque that will work. Everything I read and tested led me to believe the last commit should work, but instead it still ICEs the example I showed you and treats raw pointer patterns like wildcard patterns

@Nadrieril
Copy link
Member

So, your example ICEs in stable (playground link), so that's probably unrelated to the current PR.
Then, if I remove the double ref it doesn't ICE but emits an "unreachable pattern" warning that's clearly incorrect, again on stable (playground link).
So the problems may not come from you getting the Opaque constructor wrong. I'll have a look tomorrow or this week-end and see if I understand what's happening

@Nadrieril
Copy link
Member

Nadrieril commented Oct 17, 2020

I'm pretty sure I found how to fix one of the bugs: see #78057 . I'm not familiar enough with const-to-pat.rs to fix it myself.
I'm still going through the PR to try to make Opaque work

@Nadrieril
Copy link
Member

Nadrieril commented Oct 17, 2020

I was struggling to realize why I couldn't make Opaque work, and I've found why: if I replace every construction of Opaque with a panic!(), it appears that it's not constructed at all for most of the cases I was testing! In fact const_to_pat expands constants to PatKind::Wild in many error cases like

let msg = format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
path, path,
);
self.saw_const_match_error.set(true);
if self.include_lint_checks {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg)
}
PatKind::Wild

I don't like these wildcards. Wrt _match.rs, I'd like to emit PatKind::Constant instead. Would that break anything? Who else uses the output of const_to_pat?
The alternative is that I ignore those cases since they are errors anyways.

EDIT: this breaks things. This is not very important, I'll leave further discussion for #78057

@Nadrieril
Copy link
Member

@oli-obk I fixed Opaque! I submitted #78072 that contains your changes plus mine.
I also filed two issues #78071 and #78057 from the discussion we had here. They are not regressions nor directly related to the current PR so I thought we'd deal with them separately.

@oli-obk
Copy link
Contributor Author

oli-obk commented Oct 20, 2020

closing in favour of #78072

Thanks so much!

@oli-obk oli-obk closed this Oct 20, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Oct 22, 2020
…, r=varkor

Cleanup constant matching in exhaustiveness checking

This supercedes rust-lang#77390. I made the `Opaque` constructor work.
I have opened two issues rust-lang#78071 and rust-lang#78057 from the discussion we had on the previous PR. They are not regressions nor directly related to the current PR so I thought we'd deal with them separately.

I left a FIXME somewhere because I didn't know how to compare string constants for equality. There might even be some unicode things that need to happen there. In the meantime I preserved previous behavior.

EDIT: I accidentally fixed rust-lang#78071
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Oct 22, 2020
…, r=varkor

Cleanup constant matching in exhaustiveness checking

This supercedes rust-lang#77390. I made the `Opaque` constructor work.
I have opened two issues rust-lang#78071 and rust-lang#78057 from the discussion we had on the previous PR. They are not regressions nor directly related to the current PR so I thought we'd deal with them separately.

I left a FIXME somewhere because I didn't know how to compare string constants for equality. There might even be some unicode things that need to happen there. In the meantime I preserved previous behavior.

EDIT: I accidentally fixed rust-lang#78071
@oli-obk oli-obk deleted the pat_opt branch March 16, 2021 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants