diff --git a/meetings/2021.02.09-lazy-norm.md b/meetings/2021.02.09-lazy-norm.md new file mode 100644 index 0000000..035c258 --- /dev/null +++ b/meetings/2021.02.09-lazy-norm.md @@ -0,0 +1,80 @@ +# cg meeting 09.02.2020 + +*mostly taken from https://hackmd.io/9LIywezOQj-h5HX8vvEnSw?view* + +Lazy norm deals with 2 different issues: + +- We must not typeck anonymous constants in some early queries, most notably `query type_of` and `query predicates_of`. Even if we were to use some hacks, there is a limit to how independent we can make this. One hard barrier is `query crate_variances`. +- Delay unification of constants during typeck. An example for why this is necessary: + - not relevant for today, skip + - `D` is an anonymous constant with two generic parameters + - We can not unify `D<$0, $2>` with `D<$1, $2>` + - If `$0 = $1` we know that they are equal + - Analogous to associated types + - `<$0 as Trait<$2>>::X = <$1 as Trait<$2>>::X` + - @lcnr: still not sure if this is actually necessary. + +--- + +When using the `const_generics` feature gate, anonymous constants currently have all the generic parameters of their parent, even if they are unused inside of the constant. + +This breaks some programs, some of which already compile on stable. + +```rust +// unused-subst-4 +fn bind(value: [u8; N]) -> [u8; 3 + 4] { + todo!() +} + +fn main() { + let mut arr: ?0 = Default::default(); + arr = bind(arr); //~ ERROR mismatched type + // ?0 = [u8; ?c2] + // [u8; D<[u8; ?c2]>] <: [u8; ?c2] + // D<[u8; ?c2]> = ?c2 + // --> occurs check violation +} +``` + +Two solutions: +- eagerly filter the supplied generic params to the anonymous constant + * if we remove parameters that are not explicitly used, have to filter out the where-clauses + * generating the `ty::Predicate` from the HIR (i.e., `predicates_of` query) + * annoying thing about `T::Item` which is expanded to `>::Item` + * but that implies a `T: Trait`, which would bring in `U` + * will pull in too many parameters, still prevent some programs from compiling (e.g., `fn foo() -> [u8; size_of::()] where T: PartialEq` will pull in `U` but it's not really needed) + * back-compat when later improving the filtering? probably fine + * additional weirdness` +```rust +pub trait Trait { + const ASSOC_CONST: usize = 0; +} + +impl Trait<()> for u8 {} + +pub fn foo() -> [T; u8::ASSOC_CONST] +where + u8: Trait, + // pulling in this predicate changes the way we resolve + // `u8::ASSOC_CONST` here. + // + // Do we even want this, optionally change the way we + // resolve associated constants in anonymous constants? +{ + todo!() +} +``` +- start out with still using all generic parameters. Once we can `typeck` the anonymous constant, filter everything which is unused in the mir of the constant. + - captures exactly the parameters which are needed + - less self-contained than the first option + - will we encounter cycles where type checking the anonymous constants needs to look at the anon const substs of itself? I think this is unlikely, but would prevent us from using this option. How likely is this? + - requires further testing/exploration + - In general, how do we deal with predicates on anonymous constants? Can we even use anonymous constants in ways which do not also require the predicates of the parent item? + - Predicates required for well-formedness which get removed with this approach, not yet an issue, but maybe in the future. (https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/meeting.2009.2E02.2E2021/near/225715123) +# end of meeting +> - still have to modify `predicates_of` for anonymous constants, can't just use the parent ones, https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/lazy.20norm.20future.20compat/near/217663295 +> +># Optional stuff :sparkles: +> +>- https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/lazy.20norm.20recursive.20impls +> - eagerly evaluate fully concrete anonymous constants? probably