crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.42k stars 1.62k forks source link

Compatibility profiles for CI tests and the compiler #11706

Open HertzDevil opened 2 years ago

HertzDevil commented 2 years ago

As we approach a new major version there will be more and more breaking changes introduced via compile-time flags, and it becomes infeasible to test every combination of those flags. Our CI currently uses -Dstrict_multi_assign unconditionally. We should instead express this in terms of some selected flag combinations:

The strict profile will continue to be the default on CI; for the normal and legacy profiles we add jobs that do something along the lines of make crystal std_spec primitives_spec samples. Note that we don't need to run the compiler specs because every spec's flags come from the spec itself (e.g. as an argument to assert_type) rather than the spec command line.

We have the extra option of exposing these profiles as compile-time options, for example --profile=normal|strict|legacy. In that case we need to be explicit about the applied flags in the compiler or the reference manual, because the profiles are no longer an implementation detail in the Makefile.

straight-shoota commented 2 years ago

This continues part of the discussion in https://forum.crystal-lang.org/t/ensuring-smooth-language-changes-for-2-0/3588

I support the idea. But I think it might need some refinement.

strict and latest are not adequate antonym to each other. Breaking changes usually make things stricter, but not always. Legacy behaviour might actually be more strict than current/next in some cases. That can be a cause for ambiguity. Maybe we just need to find a different word for strict? Or will all changes that are not restrictions be excluded from this profile?

strict has a rolling characteristic. It changes whenever new opt-in flags are introduced. --profile=strict with a 1.3 compiler might mean something different than with a 1.4 compiler. That's probably okay and we can't really do anything about it, but it's clear that specifying the profile is not fully descriptive. It also matters what compiler version you use it with.

That leads to another issue: When a new major version is released, most opt-in and opt-out flags will switch. This means previous strict semantics typically become the new default. And the previous default typically becomes legacy.

Thus, profiles would essentially depend on major version series. They're relative to the majro compiler version. This would be hard to keep track of. For example when a shard is compatible with several major versions and several profiles in these versions.

Maybe indicating a language level support (as outlined in https://forum.crystal-lang.org/t/ensuring-smooth-language-changes-for-2-0/3588#decouple-language-level-from-the-compiler-version-2) would be a better option than just relative profiles.

HertzDevil commented 2 years ago

Yes this issue is essentially a continuation to that thread. I'd like to see those profiles at least in the Makefile because it has no stability guarantees and effectively tracks the nightly releases. We probably don't have to worry about the 2.0 release in a year or so.

straight-shoota commented 2 years ago

We probably don't have to worry about the 2.0 release in a year or so.

True. But we have to worry about how users can effectively apply opt-in (or opt-out) flags. When the number grows, it would be tedious to keep iterating them individually. So having some kind of profiles to combine them would be great for usability. And we add these things so people do use them.

That being said, we can certainly start with profiles in the makefile for stdlib 👍