private BoundExpression VisitExpressionImpl(BoundExpression node) { ConstantValue constantValue = node.ConstantValue; if (constantValue != null) { TypeSymbol type = node.Type; if (type?.IsNullableType() != true) { return(MakeLiteral(node.Syntax, constantValue, type)); } } var visited = VisitExpressionWithStackGuard(node); // If you *really* need to change the type, consider using an indirect method // like compound assignment does (extra flag only passed when it is an expression // statement means that this constraint is not violated). // Dynamic type will be erased in emit phase. It is considered equivalent to Object in lowered bound trees. // Unused deconstructions are lowered to produce a return value that isn't a tuple type. #if XSHARP Debug.Assert(visited == null || visited.HasErrors || ReferenceEquals(visited.Type, node.Type) || visited.Type.Equals(node.Type, TypeCompareKind.IgnoreDynamicAndTupleNames) || IsUnusedDeconstruction(node) || (_compilation.Options.HasRuntime && node?.Type == _compilation.UsualType())); #else Debug.Assert(visited == null || visited.HasErrors || ReferenceEquals(visited.Type, node.Type) || visited.Type.Equals(node.Type, TypeCompareKind.IgnoreDynamicAndTupleNames) || IsUnusedDeconstruction(node)); #endif if (visited != null && visited != node) { if (!CanBePassedByReference(node) && CanBePassedByReference(visited)) { visited = RefAccessMustMakeCopy(visited); } } return(visited); }