Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More tests and suggestions on default literal #18604

Merged
merged 14 commits into from
Apr 14, 2017

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Apr 11, 2017

@cston I'll stop by to discuss

";

var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics(); // Should give an error. Follow-up issue: https://github.com/dotnet/roslyn/issues/18609
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using (null) { } and using (default(System.IDisposable)) { } do not generate errors.

// F(async () => await default);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("C.F<T>(System.Threading.Tasks.Task<T>)").WithLocation(8, 9)
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider testing:

using System.Threading.Tasks;
class C
{
    static async Task<T> F<T>()
    {
        await Task.Delay(0);
        return default;
    }
}

@cston
Copy link
Member

cston commented Apr 12, 2017

LGTM

@jcouv
Copy link
Member Author

jcouv commented Apr 12, 2017

@dotnet/roslyn-compiler for review. This is mostly adding tests from discussion with Chuck so that I can merge "default" back into master.

@jcouv jcouv assigned gafter and unassigned gafter Apr 12, 2017
";
var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "reached");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add Console.WriteLine to operator==.

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of issues noted in this review:

// (14,17): error CS1031: Type expected
// default();
Diagnostic(ErrorCode.ERR_TypeExpected, ")").WithLocation(14, 17),
// (6,17): error CS8119: The switch expression must be a value; found default.
Copy link
Member

@gafter gafter Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the word default in this diagnostic should have some kind of quotes around it. It isn't a word of the sentence, it is referring to syntax in the source. #Resolved

// (16,19): error CS1059: The operand of an increment or decrement operator must be a variable, property or indexer
// int i = ++default;
Diagnostic(ErrorCode.ERR_IncrementLvalueExpected, "default"),
// (17,26): error CS0828: Cannot assign default to anonymous type property
Copy link
Member

@gafter gafter Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too. #Resolved

";
var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics(
// (11,13): error CS0023: Operator '!' cannot be applied to operand of type 'default'
Copy link
Member

@gafter gafter Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the specification, this is incorrect:

For an operation of the form !x, unary operator overload resolution (§13.4.4) is applied to select a specific operator implementation. The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. Only one predefined logical negation operator exists:

bool operator !(bool x);

This operator computes the logical negation of the operand: If the operand is true, the result is false. If the operand is false, the result is true.

Lifted (§13.4.8) forms of the unlifted predefined logical negation operator defined above are also predefined.
#Resolved

{
M();
}
static void M(System.Threading.CancellationToken x = default)
Copy link
Member

@gafter gafter Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES! #Resolved

@gafter gafter removed their assignment Apr 13, 2017
@jcouv
Copy link
Member Author

jcouv commented Apr 13, 2017

@cston This is ready for review.
Fixed EE scenario, added some tests, fixed unary operator case. It turns out the problem with default in interpolated strings and in using also repro'es with null (tracked by follow-up issue).

@@ -2180,7 +2180,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper
{
UnaryOperatorKind kind = SyntaxKindToUnaryOperatorKind(node.Kind());

bool isOperandTypeNull = (object)operand.Type == null;
bool isOperandTypeNull = operand.IsLiteralNull();
if (isOperandTypeNull)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we reporting an error for an operand with no type, for instance BoundMethodGroup?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, added test for method group and null.

Assert.Equal(default(DkmEvaluationResultCategory), resultProperties.Category); // Not Data
Assert.Equal(default(DkmEvaluationResultAccessType), resultProperties.AccessType); // Not Public
Assert.Equal(default(DkmEvaluationResultStorageType), resultProperties.StorageType);
Assert.Equal(default(DkmEvaluationResultTypeModifierFlags), resultProperties.ModifierFlags); // Not Virtual
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please call VerifyIL().


var testData3 = new CompilationTestData();
context.CompileExpression("default", DkmEvaluationFlags.None, ImmutableArray<Alias>.Empty, out error, testData3);
Assert.Null(error);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the target type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's object.
The reason is that the EE adds a conversion:

        private static BoundStatement BindExpression(Binder binder, ExpressionSyntax syntax, DiagnosticBag diagnostics, out ResultProperties resultProperties)
        {
           ...
            var expressionType = expression.Type;
            if ((object)expressionType == null)
            {
                expression = binder.CreateReturnConversion(
                    syntax,
                    diagnostics,
                    expression,
                    RefKind.None,
                    binder.Compilation.GetSpecialType(SpecialType.System_Object));
                if (diagnostics.HasAnyErrors())
                {
                    resultProperties = default(ResultProperties);
                    return null;
                }
            }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Consider adding Assert.Equal(SpecialType.Object, method.ReturnType.SpecialType); here in that case.

@@ -3766,6 +3766,65 @@ static void Main()
});
}

[Fact]
public void AssignDefaultToLocal()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving to ExpressionCompilerTests. LocalsTests was, at least initially, intended for testing CompileGetLocals.

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@gafter gafter removed their assignment Apr 14, 2017
@@ -210,7 +210,7 @@ private static InternalSyntax.ExpressionSyntax ParseDebuggerExpressionInternal(S
private static StatementSyntax ParseDebuggerStatement(string text)
{
var source = SourceText.From(text);
using (var lexer = new InternalSyntax.Lexer(source, CSharpParseOptions.Default))
using (var lexer = new InternalSyntax.Lexer(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a helper method for ParseOptions.

}");

testData = new CompilationTestData();
context.CompileExpression("a = default;", DkmEvaluationFlags.None, ImmutableArray<Alias>.Empty, out error, testData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider testing a non-expression statement (perhaps "int b = default;") to avoid having these succeed by falling back to expression parsing.

@@ -194,9 +194,11 @@ private static ExpressionSyntax ParseDebuggerExpression(string text, bool consum
return expression.MakeDebuggerExpression(source);
}

static CSharpParseOptions GetCSharpParseOptions() => CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this a static readonly field.

@cston
Copy link
Member

cston commented Apr 14, 2017

LGTM

@jcouv jcouv merged commit 3f19fb5 into dotnet:features/default Apr 14, 2017
@jcouv jcouv deleted the default-tests branch April 14, 2017 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants