From 1885b7d82ed6723fd677ad3e758dc81cb0a16239 Mon Sep 17 00:00:00 2001 From: Evan Hauck Date: Wed, 11 May 2016 14:55:54 -0700 Subject: [PATCH] Check if dynamic property is set-only when dotting off it --- .../Portable/Binder/Binder_Expressions.cs | 6 +++++ .../Test/Semantic/Semantics/DynamicTests.cs | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 439c91ace9f42..fcf0eaa289e94 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -4510,6 +4510,12 @@ private bool IsUsingAliasInScope(string name) if ((object)leftType != null && leftType.IsDynamic()) { + // There are some sources of a `dynamic` typed value that can be known before runtime + // to be invalid. For example, accessing a set-only property whose type is dynamic: + // dynamic Foo { set; } + // If Foo itself is a dynamic thing (e.g. in `x.Foo.Bar`, `x` is dynamic, and we're + // currently checking Bar), then CheckValue will do nothing. + boundLeft = CheckValue(boundLeft, BindValueKind.RValue, diagnostics); return BindDynamicMemberAccess(node, boundLeft, right, invoked, indexed, diagnostics); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs index bc43a0e747a65..02bdc7bcd3e3d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/DynamicTests.cs @@ -3434,6 +3434,33 @@ static void Main() CompileAndVerify(compilation2, expectedOutput: @"4"); } + [Fact, WorkItem(9945, "https://github.com/dotnet/roslyn/issues/9945")] + public void DynamicGetOnlyProperty() + { + string source = @" +class Program +{ + static void Main() + { + I i = null; + System.Type t = i.d.GetType(); + } + + interface I + { + dynamic d { set; } + } +} +"; + var compilation = CreateCompilationWithMscorlib(source, new[] { CSharpRef, SystemCoreRef }, options: TestOptions.DebugDll); + // crash happens during emit if not detected, so VerifyDiagnostics (no Emit) doesn't catch the crash. + compilation.VerifyEmitDiagnostics( + // (7,25): error CS0154: The property or indexer 'Program.I.d' cannot be used in this context because it lacks the get accessor + // System.Type t = i.d.GetType(); + Diagnostic(ErrorCode.ERR_PropertyLacksGet, "i.d").WithArguments("Program.I.d").WithLocation(7, 25) + ); + } + [ClrOnlyFact(ClrOnlyReason.Ilasm)] public void IncorrectArrayLength() {