Change:
// Check the qualifs of the value of `const` items. if let Some(ct) = constant.literal.const_for_ty() { if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) = ct.val { <del> assert!(promoted.is_none()); </del> <ins> // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible // only for `NeedsNonConstDrop` with precise drop checking. This is the only const // check performed after the promotion. Verify that with an assertion. assert!(promoted.is_none() || Q::ALLOW_PROMOTED); </ins> // Don't peek inside trait associated constants. <del> if cx.tcx.trait_of_item(def.did).is_none() { </del> <ins> if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() { </ins> let qualifs = if let Some((did, param_did)) = def.as_const_arg() { cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did)) } else {

Discussion:
This only occur in . <!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. -- <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
ok yea, I can totally see how we got here. Const checking used to happen before promotion, but constpreciselivedrops is happening after, but re-uses const checking machinery. I think we can safely change to return if , as the promoted can't possibly have any of the three qualifs that exist. My reasoning for that is that in order for a promoted to have been created, it must already be free of things that drop, or things that can be mutated and it can't be part of a pattern either, so we don't care about non-derived PartialEq impls. cc
Is this also true for promoteds inside const/static bodies, which can call arbitrary const fn?
hmm good point, there may be a non-const drop value in a promoted there. But... using may be a breaking change. I guess we need to recurse into the MIR of the promoted.
The promoted is a though... so I think there can be const drops (even const drops that panic), but no non-const drops?
Vec::new is const fn and not const drop
But AFAIK it is also not promoted even in const/static bodies?
Sorry, I misread your comment. You were saying this specific issue is for a promoted in a . We need to check whether, with precise drops, we can end up with promoteds that are problematic, as we delayed some of the drop checks. I don't think we delay the drop checks for promotion, so we should be good on that end. All other const checks are guaranteed to happen before promotion, so we can ignore them here. If we want to make this all explicit, we could add an in_promoted function to Qualif and have all other qualifs keep panicking.

Wait, we are promoting things and then checking if that was a good idea? That doesn't work, as it could lead to compile errors in code that would have been fine had we not promoted.
We aren't. Or... we shouldn't. But we need to make sure before we can enable precise drops
That sounds good to me. We can also fallback to type-based reasoning, after all promoted are references, so they don't need drop.
Ralf is right, we should never have to look into promoteds, they must be correctly constructed or not at all. So we don't need an per se, we can just add an associated constant and panic if it is not set and return false otherwise
FWIW, that's how I understood your earlier proposal, with returning false and panicking everywhere else.
Yea, either const or fn is fine, it just seems like a function sends the wrong message, as it could mean you could actually add logic in it