Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAllow where clauses involving types which don't include a type parameter. #27972
Conversation
rust-highfive
assigned
nikomatsakis
Aug 24, 2015
eefriedman
referenced this pull request
Aug 24, 2015
Closed
Can `derive` be smarter about lifetime parameters? #27950
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
Be careful not to cause an ICE when translating a function that contains a bogus bound: #[no_mangle]
pub fn bogus<'a>(x: &'a mut ()) where &'a mut (): Clone {
<&'a mut ()>::clone(&x);
} |
This comment has been minimized.
This comment has been minimized.
|
The original RFC specified this behavior, but I think we all agree this is a fine change. |
This comment has been minimized.
This comment has been minimized.
|
Yes, I agree this is reasonable, but I think we may not want to just lift the restriction without possibly placing other restrictions. I had intended to write an RFC at some point, though it may be overkill. My thought is that we should make a best-effort to validate where-clauses, which means that if you define a function that contains a where-clause which is not satisfiable (e.g., This is probably fairly easy to implement. The existing |
This comment has been minimized.
This comment has been minimized.
nikomatsakis
added
T-lang
I-needs-decision
I-nominated
labels
Aug 24, 2015
This comment has been minimized.
This comment has been minimized.
|
Nominating for "needs decision" by the @rust-lang/lang team. |
This comment has been minimized.
This comment has been minimized.
|
If I'm understanding correctly, the suggested rule is something along the lines of "all where clauses which don't contain a type parameter must be satisfiable if you replace all generic lifetimes with 'static"? That seems reasonable... |
This comment has been minimized.
This comment has been minimized.
|
I would prefer to check for satisfiability in intercrate mode after you instantiate type parameters by type variables. |
This comment has been minimized.
This comment has been minimized.
|
We already validate where clauses to an extent... trait ZZ {}
fn _f() where std::fmt::Display : ZZ {}
fn main() {}
Unfortunately, the current check completely ignores anything which includes a lifetime, for example: trait ZZ<'a> {}
fn _f<'a>() where std::fmt::Display : ZZ<'a> {}
fn main() {}I have no idea how to fix this. |
This comment has been minimized.
This comment has been minimized.
|
is this on a patched compiler? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I think #27987 is related. |
This comment has been minimized.
This comment has been minimized.
|
Sorry for the delay here. This got overlooked in our lang team triage due to the silliness that our filter was looking for issues, not PRs. I think we DID discuss it at some point anyhow, in fact, but none of us can recall the decision that was reached. |
This comment has been minimized.
This comment has been minimized.
|
OK, so, sorry this took forever, but we talked about it in the lang team mtg and came to the conclusion that it is fine to lift this rule, and it does not have to be an error if a where clause is unsatisfied. Unfortunately, my notes from the discussion are kind of insufficient and I cannot remember all the reasoning that led to this conclusion. Certainly issuing hard errors is backwards incompatible, and feels in some sense a bit artificial, since in general we assume that where clauses hold, so this would require special code. I seem to recall that we realized that there were other equally invalid cases where we couldn't issue errors, so it was ok for such where clauses to be accepted, and we can always issue lint warnings later etc. @rust-lang/lang anybody remember more details? |
nikomatsakis
removed
I-needs-decision
I-nominated
labels
Oct 16, 2015
This comment has been minimized.
This comment has been minimized.
|
I'm removing the I-nominated and I-needs-decision tags, in any case. |
This comment has been minimized.
This comment has been minimized.
|
@eefriedman I'll happily r+ the patch if you rebase. |
This comment has been minimized.
This comment has been minimized.
|
What should be done to cover this case: #[no_mangle]
pub fn bogus<'a>(x: &'a mut ()) where &'a mut (): Clone {
<&'a mut ()>::clone(&x);
}I imagine a patch would require this not ICE-ing. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 Ah yes, good question. Your earlier comment got overlooked, thanks for bringing it up again. I guess I can see three options:
Seems in some way analogous to matching on an empty enum -- what do we do in that case again? |
nikomatsakis
added
the
I-nominated
label
Oct 16, 2015
This comment has been minimized.
This comment has been minimized.
|
What the hey, i'll nominate again to think this over :) |
This comment has been minimized.
This comment has been minimized.
|
I think generating an LLVM |
This comment has been minimized.
This comment has been minimized.
|
From a brief look, it appears that matching on an empty enum invokes LLVM unreachable, so I think I'm ok with that, just for consistency sake (though I don't particularly like that we use it for an empty enum). In the @rust-lang/lang meeting, @huonw mentioned something about an LLVM instruction that generates an illegal instruction, but I couldn't find any such thing (maybe I didn't look hard enough). @huonw any links? In general, some kind of failure or fault seems better than arbitrary undefined behavior -- but I think the same holds for Anyway I think ultimately I would prefer to handle all such "logically impossible" cases in the same way. |
This comment has been minimized.
This comment has been minimized.
|
The intrinsic to generate a trap is http://llvm.org/docs/LangRef.html#llvm-trap-intrinsic . Whether it makes sense to generate trap vs. just unreachable is basically just a question of how much hand-holding we want to do for unsafe code. |
This comment has been minimized.
This comment has been minimized.
|
What's your problem with matching on an empty enum being an That would however require adding an |
This comment has been minimized.
This comment has been minimized.
|
On Fri, Oct 23, 2015 at 01:03:58PM -0700, arielb1 wrote:
My problem is that it results in undefined behavior if somebody makes |
This comment has been minimized.
This comment has been minimized.
|
how could one |
nikomatsakis
removed
the
I-nominated
label
Oct 29, 2015
This comment has been minimized.
This comment has been minimized.
|
@arielb1 one could create an instance of an empty enum by accident, or have the enum being empty by accident. Basically something went wrong in your logic if we go to that point, clearly, so doing undefined things doesn't seem like it's going to help anybody. |
This comment has been minimized.
This comment has been minimized.
|
/me suggests emitting a trap for such matches in debug-builds and an unreachable in release-builds. |
This comment has been minimized.
This comment has been minimized.
|
On Thu, Oct 29, 2015 at 02:38:37PM -0700, Felix S Klock II wrote:
I could get behind this, though I might prefer a panic in debug builds |
This comment has been minimized.
This comment has been minimized.
|
Anyway, a match on an empty enum is occasionally used to intentionally introduce an Creating an instance of an empty enum is not particularly easy. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 I know it is used that way; the question I think is whether a trap would be equally effective for optimization (and if not, what kind of impact we are talking about) |
This comment has been minimized.
This comment has been minimized.
|
What is the status of this PR? |
arielb1
added
the
I-nominated
label
Dec 31, 2015
This comment has been minimized.
This comment has been minimized.
|
We talked about this in the @rust-lang/lang meeting but didn't reach a firm conclusion. I think at this point probably the most appealing option is to permit such where-clauses but report errors if they don't hold (at the definition site). Yes, this is the opposite of what I wrote before, but it sidesteps @arielb1's example, and there isn't really a compelling reason to go out of our way to permit such a fn. Furthermore, if we ever encounter such a reason, it is backwards compatible to permit such where-clauses. The only hazard is that this might break some code, given that it will presumably also apply to all elaborated where clauses. I'd be surprised, though, if that affected any real code in practice. In any case it seems that RFC 1214 is already enforced some of these regulations (but I think not all, right?). I'd have to go back over and check more carefully, can't remember off the top of my head. |
nikomatsakis
removed
the
I-nominated
label
Jan 8, 2016
This comment has been minimized.
This comment has been minimized.
|
@eefriedman are you interested in trying to implement the "report errors at definition site if the where-clauses don't hold" semantics? I think it would be relatively straightforward -- there is already some code that is careful not to add such where-clauses into the parameter environment, presumably it could be made to return those clauses and then we could check them instead (or something like that, in any case). |
This comment has been minimized.
This comment has been minimized.
|
Closing in favor of issue #21203 |
eefriedman commentedAug 24, 2015
There isn't any semantic reason to disallow a
whereclause based on the fact that it doesn't contain a type parameter.r? @nikomatsakis