Uh oh!
There was an error while loading. Please reload this page.
Remove markers and replace with a default rule for unused type/lifetime parameters - #12
Remove markers and replace with a default rule for unused type/lifetime parameters#12nikomatsakis wants to merge 2 commits into
Conversation
bill-myers
commented
Mar 17, 2014
Could also make unused types and lifetimes a compiler error, and suggest to the user to apply a variance marker in the message. |
edwardw
commented
Mar 17, 2014
Then the marker types themselves become illegal. |
bill-myers
commented
Mar 17, 2014
The marker types have lang items, and those lang items would count as usage of the parameter. |
There was a problem hiding this comment.
Maybe it is just me, but from an engineering point of view, this seems like a really horrible idiom and we should not encourage it. If there is a need for this we should have some sort of explicit visibility thing in the language. I don't think we should change our type system to help its use.
There was a problem hiding this comment.
It's not obvious to me why this is horrible or what the alternatives would be.
There was a problem hiding this comment.
Sorry, that was strong language to use without explanation.
I meant it is horrible because it feels like a hack - you add an unused parameter to enforce using the struct in a certain scope - there is no indication of intent there. Someone reading the code would not know that that was what the lifetime parameter was for if they didn't know about the idiom. I would prefer something explicit to limit the usage, rather than implicitly relying on lifetime checking where there is not really a lifetime (from the perspective of inside the strucure). I also have no idea what such a thing would look like though.
There was a problem hiding this comment.
Well, we have an existing design that gives a hint at what it looks like -- marker::ContravariantLifetime<'a>
nikomatsakis
commented
Mar 18, 2014
@bill-myers yes, you're right, I should at least list "error" as an alternative. It's also appealing to force explicitness. I think my hope was that we could remove -- or almost remove -- markers entirely. In fact, given the rules here, I think we could remove them entirely, since they could be defined "in language". For example, Similar tricks should work for lifetimes. |
There was a problem hiding this comment.
Wouldn't a lint (warning you about bivariant type parameters or lifetime parameters) deal with this? The lint could then point the programmer at the std::kinds::marker module, and then the programmer who had some particular intuition about what that phantom type was for could actually explicitly write out their intent.
(You have of course mentioned std::kinds::marker below. I just want to understand if the purpose of this RFC is to reduce risk, which I think a lint will be better at, or for programmer convenience, which is where choosing the defaults to match expectations (or perhaps to match actual frequency of occurrence) would be relevant.)
((ugh, this is exactly what bill-myers said above. Sorry for the noise.. :( ))
pnkfelix
commented
Mar 18, 2014
(Ah, niko's response to bill-myers implies to me that there are indeed goals here beyond just reducing risk. That is fine, though I think it may make the RFC stronger to list those other goals explicitly, if possible.) |
nikomatsakis
commented
Mar 18, 2014
On Tue, Mar 18, 2014 at 09:07:33AM -0700, Felix S Klock II wrote:
I released the RFC prematurely, I think. I updated it. I'm also |
nikomatsakis
commented
Mar 18, 2014
I just pushed a revised version of the RFC. |
emberian
commented
Mar 20, 2014
I agree with @bill-myers here. Unused type/lifetime parameters should be an error, or at the very least a deny-by-default lint. See https://botbot.me/mozilla/rust/msg/12337250/ for confusion in the wild. Especially since this is such a sublte issue (at least IMO) it's better to have compiler help than just documentation. |
emberian
commented
Mar 20, 2014
Actually I take that back. I re-read the RFC and am in favor. +1 |
nikomatsakis
commented
Mar 20, 2014
There is one complication -- I hadn't considered cycles among types, (I'm a bit torn about this myself; I definitely prefer error to the |
lifthrasiir
commented
Mar 21, 2014
@cmr Unused lifetime parameters are sometimes useful, as in https://github.com/mozilla/rust/blob/ce62032/src/libstd/fmt/mod.rs#L1167-L1179 which allows for macros with optionally used lifetime parameters. |
huonw
commented
Mar 21, 2014
cc rust-lang/rust#5922 (@lifthrasiir, that macro is actually incorrect if we ever get hygienic lifetimes; and if we don't then one should be able to disable the warning lint (assuming it's a lint...).) |
gasche
commented
Mar 25, 2014
I have bad feelings about the proposed behavior in this RFC. My impression is that ML languages have under-estimated the importance of bivariance for too long (e.g. there is no syntax for that in the OCaml surface syntax), and that the discussed change makes Rust take the same road. I think it is important, for the language to be "complete" and robust to unplanned scenarios, that bivariance of parameters (type or lifetime) be supported. Given that std::kind::marker does not have a BivariantType marker (which is also a sign of Rust's design neglecting bivariance), how would one specify that a type is bivariant if the variance inference is tweaked not to detect it? It is very likely that I misunderstood the proposed change and that there is a way to opt-in to bivariance -- in which case I think the RFC could be debated for taste reasons, but is acceptable. An alternative proposal that I think would solve the problem of user surprise at bivariant parameters is the following: warn on "unused" type and lifetime parameters, with a warning message that mentions the problem and prompt people to explicitly add a variance annotation (or marker type or, better in most cases, In ML, bivariant type parameters are very useful to build "phantom types" (which rely on module abstraction). The idea is to have a type definition One could also consider scenarios where users may want to remove fields of a The last argument would be that Niko's proposed change to the current inference algorithms makes the logic sensibly more complex; simple is always better, especially in a type system. (Another experience I had in ML-land is that variance have very different meanings for the author and the users of a library, that people tend to conflate. There are two interpretations for |
nikomatsakis
commented
Mar 26, 2014
This is helpful feedback. I have indeed intentionally neglected
I don't think Rust has an equivalent to this ML separation between I think the Rust-y way to do what you are describing would be to have Right now, at least as much as I understand how bivariance plays out, |
nikomatsakis
commented
Mar 26, 2014
On Tue, Mar 25, 2014 at 09:19:10AM -0700, gasche wrote:
Maybe my view is blurred, but I don't really understand this point. |
gasche
commented
Mar 26, 2014
Sorry for being unclear. I guess my general point is that not being able to express bivariance could become, not a major blocker, but at least an occasional pain, if combined with other type-system features that are not present in Rust today. Formulated as is, you see that it is a rather weak objection from a pragmatic point of view. It would not be worth a design change if the present design naturally omitted bivariance; but it does suggest that willingly making your system slightly less regular and more complex to remove bivariance (as proposed in this RFC) may be a cause of regret in a (far) future. The two features I considered were:
|
nikomatsakis
commented
Mar 26, 2014
On Wed, Mar 26, 2014 at 05:57:45AM -0700, gasche wrote:
It is also plausible to imagine a future way to explicitly "opt in" to
I don't quite follow this part. While I don't know why we would want |
flaper87
commented
Mar 29, 2014
I'm not an expert on this field but based on my understanding, I like this proposal. I like the fact that it clears out the inference algorithm by removing possible weird cases that users may actually ignore (which I think makes the type-system safer) and it removes the variance markers. That said, I think having a way to opt-in to bivariance is also important. The whole point of this RFC should be to make the type inference safer without forbidding other things - which follows pretty much what is being done for kinds. As a final note, I think the lint that has been mentioned could be implemented now and warn the user about unused types and lifetimes. |
nikomatsakis
commented
Jun 19, 2014
Just a brief update: I am not sure if I still like this plan. In weekly meeting we decided to do some measurements (which I still haven't done) to try and understand how often this comes up. |
Inspired by @edwardw's PR rust-lang/rust#12828, this RFC proposes a small change to the behavior of variance inference if a type or lifetime parameter is unused. The goal is to more accurately capture user's intended behavior.