-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Implement associated constants #23606
Conversation
r? @pcwalton (rust_highfive has picked a reviewer for you, use r? to override) |
🎉 This is great! |
ref_id: ast::NodeId) | ||
-> Option<&'tcx Expr> | ||
{ | ||
let rcvr_substs = ty::node_id_item_substs(tcx, ref_id).substs; |
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.
So you're expecting substitutions to be there, which means this can't be used earlier...
But this is an ExprPath
, isn't it? Which means that at least the <T as Trait>::CONST
case could be handled here, if an astconv
interface were provided.
That reminds me, I meant to check if it's possible to move const_eval
and everything depending on it to rustc_typeck
and integrate it properly.
Maybe this can all be done in a follow-up PR after the groundwork has been laid.
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.
Good point; I'm not really sure. The traits
code is probably the main bit that I don't understand as well as I should here, so here (and even more so in rustc_typeck::check::compare_method
) there may be a couple of details that are just superstitiously copied.
One thing that concerns me is that maybe we could have a path like <<T>::U as Trait>::CONST
or <[T; <U>::N] as Trait>::CONST
(or the nested UFCS could be in the trait, too). The former is disallowed right now because <T>::U
can't be used to refer to an associated type; I don't know if that ever will be allowed in the future. The latter is of course one of the things I don't have working yet, but it seems like it could be done.
As for moving const_eval
to rustc_typeck
, probably the main obstacle there is that rustc_trans
uses it. It's kind of awkward because middle::const_eval
and trans::consts
kind of duplicate some of each others' logic, but the former is more broadly used. But I think that const_eval
is doing some things wrong that are done right in trans::consts
. E.g. in const_eval
all floats are treated as f64
, and compare_const_vals
treats them as totally ordered.
Exciting. I'll take a look. I agree that the interplay of constants, type-checking, and traits is subtle-- it's going to wind up (I think) as a kind of best-effort thing in the end, though I'd like to see add some amount of reasoning for treating constants more "generically" and deferring the actual evaluation until trans when types are known. This is probably related to some refactoring I've been doing for doing better normalization, but anyway. |
I don't quite understand what you're saying. Certainly I'm interested in interaction between constants and types (note that I proposed rust-lang/rfcs#884, which is necessary, though far from sufficient, for some concrete applications I have in mind). Are you saying that you have a justification for deferring evaluation until trans, or that you want to know would I say about this? (I do think that such a change needs to happen, at least in some cases, but it's not directly relevant to this PR, I believe.) |
It seems this may lead to old- |
☔ The latest upstream changes (presumably #23654) made this pull request unmergeable. Please resolve the merge conflicts. |
I have gotten match patterns working, though using associated consts in range patterns causes the same ICE as array sizes. (Actually, if we deferred checking that the lower bound is below the upper bound until I will try to rebase today. |
c6ca1b8
to
e43afbc
Compare
I wasn't really saying either of those things. Well, I do have justifications for potentially deferring evaluation until monomorphization -- e.g., type-checking Anyway, sorry for the delay. I intend to review today (actually, yesterday, but a lot of stuff came up and I wound up away from my computer for much of the day). |
I was assuming type-checking would be more conservative than trans, not less. |
So I've been reading through and so far I'm enjoying what I read -- but one comment. We definitely want a feature-gate on this work before it can land! Can you add a feature-gate for defining a trait with an associated constant? (I think that's probably sufficient; we could add a feature-gate for referencing such a constant as well, but so long as we don't export any public interfaces that define them, that shouldn't be necessary.) |
Done! The feature gate covers both traits and impls, since you can define an inherent associated const. |
Hmm, I fixed the last error to get a full |
☔ The latest upstream changes (presumably #23796) made this pull request unmergeable. Please resolve the merge conflicts. |
69bf389
to
451c7b3
Compare
Rebased. Hmm, is there a way to restart the Travis CI build? |
☔ The latest upstream changes (presumably #23673) made this pull request unmergeable. Please resolve the merge conflicts. |
@quantheory cool, thanks. I read through most of the PR and didn't have any major comments, it all seemed quite nice. But then I got distracted again by the beta deadline and in particular researching and implementing rust-lang/rfcs#1023. Argh. I will look it over again today -- but now that there is a feature-gate, I feel pretty good about landing this before I understand every bit. We can improve over time. |
451c7b3
to
00267eb
Compare
@nikomatsakis OK, cool. Just rebased! |
OK, so I was doing some experimentation. I found that the following example ICEs: // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(associated_consts)]
use std::marker::MarkerTrait;
trait Foo: MarkerTrait {
const ID: i32;
}
trait Bar: MarkerTrait {
const ID: i32;
}
impl Foo for i32 {
const ID: i32 = 1;
}
impl Bar for i32 {
const ID: i32 = 3;
}
const X: i32 = <i32>::ID;
fn main() {
assert_eq!(1, X);
} the problem is not super deep, it's just that the "ambiguity reporting" code assumes methods. |
So I'm basically ready to r+. I'm just wondering whether it makes sense to hold this till after the beta branch is cut this evening. |
(Basically, I'm inclined to wait because it seems like landing this patch can only create merge conflicts and other uncertainty, and the feature is feature-gated anyhow. Landing all the critical PRs before the branch deadline is always challenging anyway.) |
☔ The latest upstream changes (presumably #23936) made this pull request unmergeable. Please resolve the merge conflicts. |
d38d43f
to
2cd6cd6
Compare
☔ The latest upstream changes (presumably #24674) made this pull request unmergeable. Please resolve the merge conflicts. |
Introduces new variants and types in syntax::ast, middle::ty, and middle::def.
…ociated constants is not yet working.
2cd6cd6
to
4c0ac6d
Compare
@nikomatsakis bump |
@quantheory try #rust-internals IRC? |
Giving p=1 due to the fact that this has been hanging around. Thanks @quantheory for your persistence. |
📌 Commit 4c0ac6d has been approved by |
Closes #17841. The majority of the work should be done, e.g. trait and inherent impls, different forms of UFCS syntax, defaults, and cross-crate usage. It's probably enough to replace the constants in `f32`, `i8`, and so on, or close to good enough. There is still some significant functionality missing from this commit: - ~~Associated consts can't be used in match patterns at all. This is simply because I haven't updated the relevant bits in the parser or `resolve`, but it's *probably* not hard to get working.~~ - Since you can't select an impl for trait-associated consts until partway through type-checking, there are some problems with code that assumes that you can check constants earlier. Associated consts that are not in inherent impls cause ICEs if you try to use them in array sizes or match ranges. For similar reasons, `check_static_recursion` doesn't check them properly, so the stack goes ka-blooey if you use an associated constant that's recursively defined. That's a bit trickier to solve; I'm not entirely sure what the best approach is yet. - Dealing with consts associated with type parameters will raise some new issues (e.g. if you have a `T: Int` type parameter and want to use `<T>::ZERO`). See rust-lang/rfcs#865. - ~~Unused associated consts don't seem to trigger the `dead_code` lint when they should. Probably easy to fix.~~ Also, this is the first time I've been spelunking in rustc to such a large extent, so I've probably done some silly things in a couple of places.
🎉 |
Congrats. |
Thanks @quantheory, this is a huge boon for us! |
Anyone considered replacing |
@burdges I think this is one of the examples given in the original RFC |
Closes #17841.
The majority of the work should be done, e.g. trait and inherent impls, different forms of UFCS syntax, defaults, and cross-crate usage. It's probably enough to replace the constants in
f32
,i8
, and so on, or close to good enough.There is still some significant functionality missing from this commit:
Associated consts can't be used in match patterns at all. This is simply because I haven't updated the relevant bits in the parser orresolve
, but it's probably not hard to get working.check_static_recursion
doesn't check them properly, so the stack goes ka-blooey if you use an associated constant that's recursively defined. That's a bit trickier to solve; I'm not entirely sure what the best approach is yet.T: Int
type parameter and want to use<T>::ZERO
). See Update RFC 195 to account for RFC 246. rfcs#865.Unused associated consts don't seem to trigger thedead_code
lint when they should. Probably easy to fix.Also, this is the first time I've been spelunking in rustc to such a large extent, so I've probably done some silly things in a couple of places.