cc @eddyb @RalfJung
Let's figure out what exactly we need, because I'm very confused about it.
So, currently const qualification is doing a few things at once:
- figure out all the feature gates and forbid things not allowed in constants/statics/const_fn at all or without the feature gates
- figure out what things are promotable by ruling out values containing
Drop or UnsafeCell types (None is always ok, even if Some(value) would not be due to the type, even if Option<T> would technically propagate said type.
- In order to guarantee this for promotion we also check the bodies of
const fn and const for Drop and UnsafeCell value creations, even if it is ignored for the constant itself and only checked when the constant is used in a value checked for promotion
Why I want to stop looking at bodies, and instead just check the final value of constants:
- This analysis is imperfect. E.g.
(UnsafeCell::new(42), 42).1 is treated as if you end up with an UnsafeCell value
- If we keep looking at the body, we're essentially saying that a
const fn's body is not allowed to change, even for changes which would not change the final value for any input, because such a change might subtly lead to the analysis suddenly thinking there's an UnsafeCell in the final value
Why we cannot just look at the final value right now:
- when promoting associated constants inside a generic function we might not have enough information to actually compute the final value. We'd need to wait for monomorphization to tell us whether the value is problematic. This is obviously not something we want. All the analyses should run before monomophization
Solution brainstorm:
- don't promote calls to
const fn if its return type may contain UnsafeCell or Drop. So Option::<String> is not promoted, even if the actual value is None. (not a breaking change, since there are no stable const fn for which this could break any code)
- Always assume the worst with associated constants (already the case https://play.rust-lang.org/?gist=36546b7a589178413e28ba09f1cd0201&version=stable&mode=debug&edition=2015 ) So we don't promote associated constant uses unless monomorphized.
cc @eddyb @RalfJung
Let's figure out what exactly we need, because I'm very confused about it.
So, currently const qualification is doing a few things at once:
DroporUnsafeCelltypes (Noneis always ok, even ifSome(value)would not be due to the type, even ifOption<T>would technically propagate said type.const fnandconstforDropandUnsafeCellvalue creations, even if it is ignored for the constant itself and only checked when the constant is used in a value checked for promotionWhy I want to stop looking at bodies, and instead just check the final value of constants:
(UnsafeCell::new(42), 42).1is treated as if you end up with anUnsafeCellvalueconst fn's body is not allowed to change, even for changes which would not change the final value for any input, because such a change might subtly lead to the analysis suddenly thinking there's anUnsafeCellin the final valueWhy we cannot just look at the final value right now:
Solution brainstorm:
const fnif its return type may containUnsafeCellorDrop. SoOption::<String>is not promoted, even if the actual value isNone. (not a breaking change, since there are no stable const fn for which this could break any code)