Hello everyone, I have some free time and thought I could contribute a bit to the rust compiler. I have a bit of experience implementing stuff and already know what I want to try (proposal 2 from this comment https://github.com/rust-lang/rust/issues/68436#issuecomment-663190861). I know that it might be a bit early to start implementing such a vague proposal, but it sparked my interest and I mostly am doing it in order to get a bit familiar with the internals of rustc (so please forgive me if there are some obvious missuses of types).
TL;DR of the proposal:
The success of compiling the following code depends on the concrete value of C
, resulting in post-monomorphisation errors, which are undesired.
fn foo<const C: usize>() {
let x = [u8; C - 2];
}
Proposal: Add a type of where bound that exposes all const-generic expressions inside the function so that the call site can check them pre-monomorphisation:
fn foo<const C: usize>() where (C-2) {
let x = [u8; C - 2];
}
Obviously all just hypothetical syntax.
I'm working based on this rustc commit: 0f5c76951327b912c8e92e83235430ebd9b349d9
What I have done already:
- added some required variants and types to
rustc_ast
in order parse the syntax (WherePredicate::ConstPredicate
basically a wrapper aroundAnonConst
) - added the corresponding types to
rustc_ast_lowering
- added and stubbed the doc types
- The following code gets parsed into an
AST
(contrary to the example above I used={}
as the syntax, as it was easier to implement and could obviously be changed later on. (For the interested, the problem withwhere (<const expr>)
was that their exist types that start with an(
and as such parsing it would require more logic.
fn foo<const C: usize>() where ={C-2} {
let x = [u8; C - 2];
}
Where I'm currently unsure if it is the correct approach is the following (in rustc_typecheck/src/collect
starting at line 2042 ):
&hir::WherePredicate::ConstPredicate(ref const_pred) => {
let const_def_id = icx.tcx.hir().local_def_id(const_pred.const_expr.hir_id);
let c = ty::Const::from_anon_const(icx.tcx, const_def_id);
let pred = ty::PredicateAtom::WellFormed(c.into());
predicates.push((pred.to_predicate(icx.tcx), const_pred.span));
}
What happens here is that I take the anonymous const expression from the where bound and put it inside a WellFormed
predicate.
Now I currently have two questions:
Is it correct to use WellFormed
predicate? There is also a ConstEvaluatable
predicate, however I could not find out how to correctly set the SubstRef
field.
Currently the code fails to compile with an error in rustc_typecheck/src/collect/type_of
where it tries to find out what type the AnonConst
is. This happens due to the code encountering an unexpected parent node variant (in this case a Fn
). My guess would be that I should be able to treat it as if the expression was found inside the function body and was wondering if the lines 312-316 are the ones responsible for this case? (I don't really understand line 304-310 as they just return the type usize
, maybe someone could explain to me what case this is?).
I already have a rough idea what the next step should be after this:
- Check for every const expr inside a function (including where bound on called functions) that it can be evaluated pre-monomorph or if not, that it exists as a where bound
In case this is the wrong place for these questions I would appreciate a hint for the correct place
Thanks in advance, Raidwas