Make const eval return normalized ty - #160526
Conversation
|
Some changes occurred in cc @BoxyUwU Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor |
|
I am very dicy around the old solver changes: 0d49779 |
This comment has been minimized.
This comment has been minimized.
|
neat, looks good to me! one mostly style comment I had is that the evaluate machinery is getting really annoyingly tangly and layered and messy, and this is just more layers of wonkiness on top, haha. I wonder if instead of having a double-wrapped Result like you do with this change, instead:
anyway, just kind of spitballing here, totally up to you on whether you try to clean this up, it's also fine as-is (I'll probably try to clean it up post-merge though if you leave it as-is) |
I will do the clean up and let you know. Thanks for the review 😄 |
|
I would also try not being generic over normalization routine. I don't think it's important to have old solver support here |
54cfaab to
3f3b1cf
Compare
|
Ripped out all old solver patches, changes should be eye pleasing now 😄 |
|
r? @khyperia |
| |v| Ok::<_, !>(v.skip_norm_wip()), | ||
| ) { | ||
| Ok(val) => Ok(val), | ||
| Err(e) => Err(e), |
There was a problem hiding this comment.
this isn't your PR, but lmao, what are we doing with this match statement 💀 can just remove the match and use try_evaluate_const directly I think, but also ok to leave it
There was a problem hiding this comment.
😆 This is so funny. Collapsed it.
| Self::FailedNormalization(_) => f.write_str("FailedNormalization(..)"), | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
I have a vague preference to keep #[derive(Debug)] and add E: Debug to evaluate_const<E: Debug> and try_evaluate_const<E: Debug> (i.e. add E: Debug wherever the compiler errors at you)
There was a problem hiding this comment.
I had this before, but then changed it to explicit debug. I have reverted it back now.
| self.normalize(GoalSource::Misc, param_env, ty) | ||
| }) { | ||
| Ok(ct) => Ok(ct), | ||
| Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Ok(None), |
There was a problem hiding this comment.
I'm vaguely sus of this. Should this really return Ok(None) instead of Err?
Admittedly I need more coffee and time to think through this. Some potential wonky interactions with feature(checked_type_aliases) and whatnot that's too big-brained for me right now. If you're confident this should be Ok(None), great, if not, maybe we could chat on zulip a bit about this and figure it out together? At the very least, I think a comment explaining why it should/shouldn't return Ok(None) vs Err would be good here.
There was a problem hiding this comment.
Now that you mention it, I think what I did here is wrong, or atleast incomplete. Originally, this method's Err was just the rerun signal (RerunNonErased) from the erased-mode guard, while Ok(None) meant "too generic, treat as ambiguity". Normalizing the value's type adds another possible failure (NoSolutionOrRerunNonErased from self.normalize). I don't think those should be conflated. So a NoSolution here should be considered as a failure?. normalize_free_alias also propagates normalization failures with ?, so treating it as ambiguity here seems inconsistent. So I am leaning towards returning Result<Option<Const>, NoSolutionOrRerunNonErased> and letting callers ? it. The main thing I am unsure about is whether we can even hit NoSolution here. The const is fully concrete by the time we evaluate it, so its type's projections should also resolve?
There was a problem hiding this comment.
Yeah, the next morning's coffee in hand with a proper sleep, I think I agree, on a theoretical level a type normalization failure here should be an error, not treated as ambiguous (or, under full GCA, as rigid). I think the None case ought to only come from CTFE needing concrete types to compute values, but types ought to always be "evaluable" (even if just to some rigid version of themselves if generics are involved).
On a concrete technical level, both callers already return Result<_, NoSolutionOrRerunNonErased> (well, spelled QueryResultOrRerunNonErased<I> but whatever, same thing) and both already do ?, so on a mechanical level it's straightforward. I think the match statement here would also just go away, return self.delegate.evaluate_const directly~
Unfortunately I'm also unsure of whether it's even possible to reach this point. I spent a bit trying to manually fuzz my way into hitting it and was unable to. I'll poke in zulip to see if people who know more than I do know what's up :3
edit: after thinking some more (see zulip thread), I thiiiiink this is unreachable (I think), so maybe we should assert/ICE here, instead of propagating Err(NoSolution). It's next-solver anyway, so can't break stable with an ICE, and then we get a nice lil bug report if it does turn out to be reachable~
closes: rust-lang/trait-system-refactor-initiative#286
closes: #156294
r? @lcnr