-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Classify various const generics bugs #68400
Comments
Most of the issues are probably #68398, but there's also https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=8fb424e1ae41c73a264e7ad1c991686d. |
Please cc me on each fix for anything const-generics-related. A very important milestone is #70107, anything that it creates errors in (without ICE-ing) should probably be considered "fixed as not-a-bug" or rather the bug was in the quality of diagnostics but the code was still wrong. |
#69239 seems to be related to #69913, afaict the most useful way to fix this would be #70122 which we decided was not worth it. #70507, #69816, #63695, #61936 something something const args in methods, if I remember correctly these can't be fixed easily rn, @eddyb I can't find where you mentioned this. (maybe #70167 (comment)) |
Yeah we should just ban const args on |
They should work. This would be an unnatural restriction, even a temporary one. That said, I'm not sure how to type-check them yet either. |
Afaik type args work with TypeRelative segments, which means that I am missing a crucial difference between const and type args. :/ Can you explain this to me/guide me to some relevant ressources? |
@lcnr Types don't have types (or more correctly, the type of all types is the same, some hypothetical Furthermore, the constant expression is a separate body that has to be fully type-checked before it can be evaluated. So you have to compute the type before you type-check the constant expression, before you can evaluate it, before you can use it in the original body, which is the only one that knows the type. You could bypass this with lazy normalization, maybe, but it's too easy to end up with a cyclic dependency between the constant expression and the surrounding body. Maybe we could type-check the constant expression and get the type from there without having an expected type? And only use it if the type is correct? But then
Disallowing impossible to implement features is not really unnatural. We also ban specifying generics when |
While this makes sense, do we even want to know the type/value of the generic argument before the relevant parameters are known? I still think that I am missing something here, as it seems easily solvable for me. 😐 Looking at this example: struct A<const N: usize>;
impl A<7> {
fn test<const M: bool>() {}
}
impl A<42> {
fn test<const M: Option<()>>() {}
}
let a = A::<7>;
a.test::<true>(); Due to type inference, we should know that I would not expect, or want, the following to compile for example let a = A;
a.test::<true>();
// we could infer from `true` that we require a method
// `test<const _: bool>()` which means that `N` must be `7`. This seems really fragile and causes the problems mentioned by @eddyb. I don't yet see how my approach can lead to cycle errors 🤔 |
It's like this: const main_ANON0: ??? = true;
fn main() {
// ...
a.test::<main_ANON0>();
} You can infer the type The cycle would be if |
From a user's perspective, there's no reason this shouldn't work. It's unnatural from a language POV. This is theoretically possible to implement. If the existing infrastructure in rustc makes that difficult, then something should change there. |
I never want to infer the type of My expectation is that we never actually need Once we know that |
The existing infrastructure is sound wrt incremental and query execution order. Most of the things proposed at various times, that don't fit the current system, turn out to not have that property!
You have no access to side-effects (see my previous paragraph: they would be unsound), |
Note that the only reason we found something that may work is that all of the regular queries still do the things I've described above as almost guaranteeing a query cycle. But we could have The normal query would call the Inside the So we would add such query variants, as-needed, every time we want to break a cycle. |
Taken from zulip, the following issues are not blocked at the moment:
^ done
This also seems like it requires an unrelated fix: #71611 |
Support const args in type dependent paths (Take 2) once more, except it is sound this time 🥰 previously rust-lang#71154 ----- ```rust #![feature(const_generics)] struct A; impl A { fn foo<const N: usize>(&self) -> usize { N } } struct B; impl B { fn foo<const N: usize>(&self) -> usize { 42 } } fn main() { let a = A; a.foo::<7>(); } ``` When calling `type_of` for generic const arguments, we now use the `TypeckTables` of the surrounding body to get the expected type. This alone causes cycle errors though, as we now have `typeck_tables_of(main)` -> `...` -> `type_of(main_ANON0 := 7)` -> `typeck_tables_of(main)` ⚡ (see rust-lang#68400 (comment)) To prevent this we must not call `type_of(const_arg)` during `typeck_tables_of`. This is achieved by calling `type_of(param_def_id)` instead. We have to somehow remember the `DefId` of the param through all of typeck, which is done using the struct `ty::WithOptConstParam<DefId>`, which replaces `DefId` where needed and contains an `Option<DefId>` to be able to store the const parameter in case it exists. Queries which are currently cached on disk are split into two variants: `query_name`(cached) and `query_name_(of|for)_const_arg`(not cached), with `query_name_of_const_arg` taking a pair `(did, param_did): (LocalDefId, DefId)`. For some queries a method `query_name_of_opt_const_arg` is added to `TyCtxt` which takes a `ty::WithOptConstParam` and either calls `query_name` or `query_name_of_const_arg` depending on the value of `const_param_did`. r? @eddyb @varkor
I think the issues raised here specifically have been addressed now that #74113 has been merged. |
@eddyb identified several bugs in Playground examples on Discord, starting here. We should classify them and make sure we have representative edge cases for each when they've fixed.
The text was updated successfully, but these errors were encountered: