-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking issue for RFC 2203, "Constants in array repeat expressions" #49147
Comments
I had an investigation on this issue. I think removing below lines can achieve our goals. But I'm not sure whether it is enough. rust/src/librustc_mir/borrow_check/nll/type_check/mod.rs Lines 1232 to 1238 in 1eab9c5
rust/src/librustc_typeck/check/mod.rs Lines 4017 to 4025 in 1eab9c5
And another question, given that this change should be guarded by a feature gate, how can we suggest user to enable this feature when a compile error occurs? I'd appreciate it if somebody can write a mentoring instruction. |
See rust-lang/rfcs#2203 (comment) - I don't think we should implement this before the MIR borrowck becomes the default - while it may be possible, it's getting increasingly risky to do such things. |
So I just realized that "constant" has been a red herring all along for this problem: For One example of a runtime repeated expression we could allow is I propose (a bit late) that we consider a value (dataflow) analysis,
Another advantage of this is that it's not limited to |
Trying to recast what you are saying in my terms, we have I think that's a remark I already made somewhere else earlier this year but I have no idea where.^^ |
Yes, except I only realized it can apply to all copies at the very end of writing my entire comment, so my reasoning may look quite roundabout. I suspect this might not even be the only place where we can generalize a type-based analysis to a value-based one (like const-checking has). We could even mix this with polymorphism, by putting "refinement types" through generics. |
@eddyb hmm, interesting thought. So this is basically "doubling down" on the value-based reasoning we use for consts, and applying it here as well? I don't entirely hate that, particularly if we can kind of "reuse" the form of the rule from consts exactly. |
I ran into the following constraints with trying to use primitive array repeat in enum Wrap { ... }
struct MyStruct<'a> {
arr: &'a mut [Option<Wrap>]
}
impl<'a> MyStruct<'a> {
pub fn new(list: &'a mut [Option<Wrap>]) -> Self { Self{ arr: list} } }
}
// works fine, and is very ergonomic
let mut z = MyStruct{ arr: &mut [] };
// however the logical follow-up and equally ergonomic &mut [None;N] fails...
// all fine, Copy-trait not needed (*1)
let mut empty1: [Option<Wrap>;11] = Default::default();
let mut a = MyStruct{ arr: &mut empty1 };
// need type ascription, Copy-trait not needed (*2)
let mut empty2 = Default::default():[Option<Wrap>;11];
let mut b = MyStruct::new(&mut empty2);
// need type ascription, Copy-trait for Wrap
let mut empty3 = [Default::default();11]:[Option<Wrap>;11]; // (*3)
let mut empty4 = [Option::default();11]:[Option<Wrap>;11]; // (*4)
let mut empty5 = [None;11]:[Option<Wrap>;11]; // (*5)
// need type ascription, parenthesized expression ... but alas, lifetime fails when (expr)
let mut c = MyStruct{ arr: &mut ([Default::default();11]:[Option<Wrap>;11]) }; // (*6) , also parens expr
let mut d = MyStruct::new( &mut ([Default::default();11]:[Option<Wrap>;11]) ); // (*6b) , also parens expr
// need Copy-trait for Wrap
let mut e = MyStruct{ arr: &mut [Default::default();11] }; // (*7)
let mut f = MyStruct{ arr: &mut [None;11] }; // (*8)
let mut g = MyStruct::new(&mut [None;11]); // (*9) All the cases from (*1) to (*9) try to accomplish similar initialization. Ideally, shouldn't they all work similarly? I really want to use (*9), (*8) or (*7) - and not (*1) or (*2) which are not ergonomic.
|
@nikomatsakis Indeed, I think we should double down on value reasoning in favor of ergonomics.
This is not required in the accepted RFC, you will be able to just write
As for your ascription questions: you can make these replacements in your code:
Then your code looks like this (click to expand).enum Wrap { ... }
struct MyStruct<'a> {
arr: &'a mut [Option<Wrap>]
}
impl<'a> MyStruct<'a> {
pub fn new(list: &'a mut [Option<Wrap>]) -> Self { Self{ arr: list} } }
}
// works fine, and is very ergonomic
let mut z = MyStruct{ arr: &mut [] };
// however the logical follow-up and equally ergonomic &mut [None;N] fails...
// all fine, Copy-trait not needed (*1)
let mut empty1: [_;11] = Default::default();
let mut a = MyStruct{ arr: &mut empty1 };
// need type ascription, Copy-trait not needed (*2)
let mut empty2 = <[_;11]>::default();
let mut b = MyStruct::new(&mut empty2);
// need type ascription, Copy-trait for Wrap
let mut empty3 = [Default::default();11]; // (*3)
let mut empty4 = [Option::default();11]; // (*4)
let mut empty5 = [None;11]; // (*5)
// need type ascription, parenthesized expression ... but alas, lifetime fails when (expr)
let mut c = MyStruct{ arr: &mut [Default::default();11] }; // (*6) , also parens expr
let mut d = MyStruct::new( &mut [Default::default();11] ); // (*6b) , also parens expr
// need Copy-trait for Wrap
let mut e = MyStruct{ arr: &mut [Default::default();11] }; // (*7)
let mut f = MyStruct{ arr: &mut [None;11] }; // (*8)
let mut g = MyStruct::new(&mut [None;11]); // (*9) Further notes from looking at the result of that:
@runelabs I hope I've clarified a few things and/or resolved most of your concerns. |
@eddyb Thanks, I hadn't thought of |
|
Is the |
@eddyb hmm maybe we could/should just rename "fixed by NLL" to "needs NLL", which is ... strictly more general? (Or is that label not a true generalization? I'm still musing over the english semantics here. I guess "fixed by NLL" implies that NLL is sufficient but not (necessarily) necessary, while "needs NLL" implies NLL is necessary but not (necessarily) sufficient...)
|
Discussed briefly on Zulip -- would we want to experiment with this on 2018 only to begin with? |
split MaybeUninit into several features, expand docs a bit This splits the `maybe_uninit` feature gate into several: * `maybe_uninit` for what we will hopefully stabilize soon-ish. * `maybe_uninit_ref` for creating references into `MaybeUninit`, for which the rules are not yet clear. * `maybe_uninit_slice` for handling slices of `MaybeUninit`, which needs more API design work. * `maybe_uninit_array` for creating arrays of `MaybeUninit` using a macro (because we don't have rust-lang#49147 yet). Is that an okay thing to do? The goal is to help people avoid APIs we do not want to stabilize yet. I used this to make sure rustc itself does not use `get_ref` and `get_mut`. I also extended the docs to advise against uninitialized integers -- again this is something for which the rules are still being discussed.
I left a comment elsewhere, I think it would be fine if this were restricted to Rust 2018: #54542 (comment) |
@oli-obk so, what do we do about the dropping thing? |
I'm still unsure we should do this at all (as mentioned earlier). I would rather make a decision on that first before putting in more effort |
You mean, supporting only |
Yes, that is what I mean. It would simplify a lot, and iirc that was always on the table. |
Not checking for drop has an additional effect that enabling this feature gate changes the semantics of programs that already compile successfully (or is a separate bug?): //#![feature(const_in_array_repeat_expressions)]
struct S(&'static str);
impl Drop for S {
fn drop(&mut self) {
println!("{}", self.0);
}
}
fn main() {
// S is dropped or not depending on the feature gate.
[&S("a"); 4];
} |
The feature |
Ah good catch :D yea, this issue should be closed. We removed this feature without replacement as the feature was extremely buggy and problematic and in the future we'll be able to use the |
Should the accepted RFC be marked as "retracted" or something? |
@SimonSapin Good call. I'll make a quick RFCs-PR and bring it up in the lang meeting tomorrow. |
MaybeUninit::uninit_array's docs still link to this as a "future feature", seems like that mention should be removed |
update comment at MaybeUninit::uninit_array rust-lang#49147 is closed; this now instead needs inline const expressions (rust-lang#76001).
22: Make the creation of TxRingEntry and RxRingEntry const r=adamgreig a=thalesfragoso This allow for people to create `RingEntry` on a const context, which saves a considerable amount of stack during initialization if having them in a `static`. I also left the non const `Default` implementations for compatibility and also because of rust-lang/rust#49147, which causes the creation of entries a bit cumbersome since `Aligned` isn't `Copy`, so users can use `default` on non const contexts if they want to. CC @adamgreig Co-authored-by: Thales Fragoso <thales.fragosoz@gmail.com>
877: Bump MSRV to Rust 1.38 r=taiki-e a=taiki-e It was released [nearly 3 years ago](https://blog.rust-lang.org/2019/09/26/Rust-1.38.0.html) and meets our MSRV policy. This allows using const_in_array_repeat_expressions (rust-lang/rust#49147) and `<pointer>.cast()`. Co-authored-by: Taiki Endo <te316e89@gmail.com>
This is a tracking issue for the RFC "Constants in array repeat expressions" (rust-lang/rfcs#2203) (feature gate:
const_in_array_repeat_expressions
).Steps:
Implementation history:
Unresolved questions:
const fn
, but poses the risk of breaking code that would otherwise work fine if we decide to promote when it would not have been necessary. The alternative is to rely on inline const expressions instead (Tracking Issue for inline const patterns (RFC 2920) #76001).const {}
block for the repeat expression?The text was updated successfully, but these errors were encountered: