[bug] InvalidProgramException when having TryCatch + Default in Catch
kicsiede opened this issue · 5 comments
Hello,
I have an expression where using a deep accessor i try to determine whether a certain member is accessible (or it has a null value in the chain), however CompileFast compiles an invalid program. (running 32/64bit .net framework 4.7+) Here is a simplified version of the expression, I wasn't able to narrow down the root cause anymore:
var pEntity = Expression.Parameter(typeof(Tuple<object>));
var lastInstanceAccessor = Expression.PropertyOrField(pEntity, "Item1");
var expr = Expression.Lambda<Func<Tuple<object>, bool>>(Expression.Equal(Expression.Constant(null),
Expression.TryCatch(lastInstanceAccessor, [Expression.Catch(typeof(NullReferenceException), Expression.Default(lastInstanceAccessor.Type))])), pEntity);
var shouldReturnTrue = expr.Compile().Invoke(null); // Works
var shouldReturnTrueButInvalidProgram = expr.CompileFast().Invoke(null); // Throws
Thanks for finding. I will check.
FYI I tried working around the problem by abandoning the try-catch approach, and testing each member against null, and early returning in an Expression.IfThen + Expression.Return, but I get InvalidProgramException again for this totally different structure, so I would guess the problem may lie in returning values from block-like expressions, or how these expressions interact with the outer expression. (for example if you remove the outer Equal in the example above, it seems to work - I mean it's neither Equal nor TryCatch causing the problem alone, but when they are composed) Just a hint though, I haven't tracked down this second error.
I want to add that I've run into a situation, where there is no InvalidProgramException thrown, but the compiled program is simply wrong. Although this is also related to the above scenario but with more nesting. I am setting the (sub)properties of an object with deep accessors, where I check for null values with the technique above, and ignore those properties that i cannot reach. Maybe the extra depth makes the return point valid, but still incorrect.