Note [exprOkForSpeculation and type classes]
Consider (#22745, #15205) \(d :: C a b). case eq_sel (sc_sel d) of (co :: t1 ~# t2) [Dead] -> blah We know that * eq_sel's argument (sc_sel d) has dictionary type, so it definitely terminates (again Note [NON-BOTTOM-DICTS invariant] in GHC.Core) * eq_sel is simply a superclass selector, and hence is fast * The field that eq_sel picks is of unlifted type, and hence can't be bottom (remember the dictionary argument itself is non-bottom) So we can treat (eq_sel (sc_sel d)) as ok-for-speculation. We must check a) That the function is a class-op, with IdDetails of ClassOpId b) That the result type of the class-op is terminating or unlifted. E.g. for class C a => D a where ... class C a where { op :: a -> a } Since C is represented by a newtype, (sc_sel (d :: D a)) might not be terminating. Rather than repeatedly test if the result of the class-op is a terminating/unlifted type, we cache it as a field of ClassOpId. See GHC.Types.Id.Make.mkDictSelId for where this field is initialised.
References 1
- NON-BOTTOM-DICTS invariant GHC.Core
Referenced by 5
- GHC.Core.Utils call site ×2
- NON-BOTTOM-DICTS invariant GHC.Core
- GHC.Core.Opt.WorkWrap.Utils call site
- GHC.Types.Id.Info call site