aaronpuchert added inline comments.

================
Comment at: clang/lib/AST/ASTContext.cpp:12367
+  case Type::Class:                                                            
\
+    llvm_unreachable("Unexpected " Kind ": " #Class);
+
----------------
mizvekov wrote:
> aaronpuchert wrote:
> > mizvekov wrote:
> > > davrec wrote:
> > > > mizvekov wrote:
> > > > > davrec wrote:
> > > > > > mizvekov wrote:
> > > > > > > davrec wrote:
> > > > > > > > Could we just return `X` here? Would that just default to the 
> > > > > > > > old behavior instead of crashing whenever unforeseen cases 
> > > > > > > > arise?  
> > > > > > > No, I think we should enforce the invariants and make sure we are 
> > > > > > > handling everything that can be handled.
> > > > > > > 
> > > > > > > Classing `TemplateTypeParm`  as sugar-free was what was wrong and 
> > > > > > > we missed this on the review.
> > > > > > There might always going to be a few rare corner cases vulnerable 
> > > > > > to this though, particularly as more types are added and the people 
> > > > > > adding them don't pay strict attention to how to incorporate them 
> > > > > > here, and don't write the requisite tests (which seem very 
> > > > > > difficult to foresee and produce).  When those cases arise we will 
> > > > > > be crashing even though we could produce a perfectly good program 
> > > > > > with the intended semantics; the only thing that would suffer for 
> > > > > > most users is slightly less clear diagnostic messages for those 
> > > > > > rare cases.  I think it would be better to let those cases 
> > > > > > gradually percolate to our attention via bug reports concerning 
> > > > > > those diagnostics, rather than inconveniencing the user and 
> > > > > > demanding immediate attention via crashes.  Or am I missing 
> > > > > > something?
> > > > > I could on the same argument remove all asserts here and just let the 
> > > > > program not crash on unforeseen circumstances.
> > > > > 
> > > > > On the other hand, having these asserts here helps us catch bugs not 
> > > > > only here, but in other parts of the code. For example uniquing / 
> > > > > canonicalization bugs.
> > > > > 
> > > > > If someone changes the properties of a type so that the assumptions 
> > > > > here are not valid anymore, it's helpful to have that pointed out 
> > > > > soon.
> > > > > 
> > > > > Going for as an example this specific bug, if there werent those 
> > > > > asserts / unreachables in place and we had weakened the validation 
> > > > > here, it would take a very long time for us to figure out we were 
> > > > > making the wrong assumption with regards to TemplateTypeParmType.
> > > > > 
> > > > > I'd rather figure that out sooner on CI / internal testing rather 
> > > > > than have a bug created by a user two years from now.
> > > > Yes its nicer to developers to get stack traces and reproductions 
> > > > whenever something goes wrong, and crashing is a good way to get those, 
> > > > but users probably won't be so thrilled about it.  Especially given 
> > > > that the main selling point of this patch is that it makes diagnostics 
> > > > nicer for users: isn't it a bit absurd to crash whenever we can't 
> > > > guarantee our diagnostics will be perfect?
> > > > 
> > > > And again the real problem is future types not being properly 
> > > > incorporated here and properly tested: i.e. the worry is that this will 
> > > > be a continuing source of crashes, even if we handle all the present 
> > > > types properly.
> > > > 
> > > > How about we leave it as an unreachable for now, to help ensure all the 
> > > > present types are handled, but if months or years from now there 
> > > > continue to be crashes due to this, then just return X (while maybe 
> > > > write something to llvm::errs() to encourage users to report it), so we 
> > > > don't make the perfect the enemy of the good.
> > > It's not about crashing when it won't be perfect. We already do these 
> > > kinds of things, see the FIXMEs around the TemplateArgument and 
> > > NestedNameSpecifier, where we just return something worse than we wish 
> > > to, just because we don't have time to implement it now.
> > > 
> > > These unreachables and asserts here are about testing / documenting our 
> > > knowledge of the system and making it easier to find problems. These 
> > > should be impossible to happen in correct code, and if they do happen 
> > > because of mistakes, fixing them sooner is just going to save us 
> > > resources.
> > > 
> > > `llvm::errs` suggestion I perceive as out of line with current practice 
> > > in LLVM, we don't and have a system for producing diagnostics for results 
> > > possibly affected by FIXME and TODO situations and the like, as far as I 
> > > know, and I am not aware of any discussions in that direction. I expect a 
> > > lot of complexity and noise if we went this way.
> > > And I think this would have even less chance of working out if we started 
> > > to incorporate the reporting of violation of invariants into that.
> > > 
> > > I think even just using raw `llvm::errs` on clang would be incorrect per 
> > > design, and could likely break users that parse our output.
> > > 
> > > I think if months and years from now, if someone stumbled upon an assert 
> > > firing here and, instead of understanding what is happening and then 
> > > fixing the code, just removed / weakened the assert, that would simply 
> > > not be good and I hope a reviewer would stop that from happening :)
> > I tend to agree that an assertion is appropriate for this. But you could 
> > turn this into
> > ```
> > assert(false && "...");
> > return X;
> > ```
> > which would still assert, but fall back to something "reasonable" in builds 
> > without assertions. The issue with `llvm_unreachable` is that it translates 
> > to `__builtin_unreachable()` in builds without assertions, and the 
> > optimizer takes advantage of that quite heavily. That's why 
> > `llvm_unreachable` is better left to places where we're pretty sure they're 
> > unreachable unless something went horribly wrong, such as after switches 
> > that handle all enumeration values.
> I see, that is reasonable.
> 
> But grepping for `assert(false` in the code base, I see that they are pretty 
> rare, accounting for a bit less than 0.5% in `clang/` and 0.3% in `llvm/`, 
> compared to the total number of asserts. They occur fifty times less than 
> plain llvm_unreachables. I don't remember ever seeing them in practice, so I 
> was not aware this was something we would do.
> 
> I feel like in these cases where we are using llvm_unreachable in this patch, 
> I am 100% sure they are really unreachable, unless something went horribly 
> wrong. But I mean I could be completely wrong as well, I must admit, so maybe 
> in those cases that is what went horribly wrong? (Me being wrong I mean)
It depends on how likely you think it is that someone inadvertently violates 
the invariant without noticing (even after running the tests). For internal 
invariants or things unlikely to miss in a test, `llvm_unreachable` should be 
fine. The less certain you are that mistakes would be hard to make or easy to 
find, the more preferable would be a fallback. If you think this was a one-off 
blunder and is unlikely to reoccur, you can also stick to `llvm_unreachable`. 
So this was just a suggestion, and since I merely skimmed over the code I'm not 
the best to judge.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D111283/new/

https://reviews.llvm.org/D111283

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to