提交 0fe53eb3 编写于 作者: A AlekseyTs

Suppress dynamic access to instance indexers off of types.

Fixes some of the scenarios for https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=204561&_a=edit.
上级 62243e23
......@@ -6041,9 +6041,13 @@ private BoundExpression BindIndexedPropertyAccess(CSharpSyntaxNode syntax, Bound
if (analyzedArguments.HasDynamicArgument && overloadResolutionResult.HasAnyApplicableMember)
{
var result = BindDynamicIndexer(syntax, receiverOpt, analyzedArguments, overloadResolutionResult.GetAllApplicableMembers(), diagnostics);
// Note that the runtime binder may consider candidates that haven't passed compile-time final validation
// and an ambiguity error may be reported. Also additional checks are performed in runtime final validation
// that are not performed at compile-time.
// Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime.
var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, overloadResolutionResult, receiverOpt, default(ImmutableArray<TypeSymbol>), diagnostics);
overloadResolutionResult.Free();
return result;
return BindDynamicIndexer(syntax, receiverOpt, analyzedArguments, finalApplicableCandidates, diagnostics);
}
if (!overloadResolutionResult.Succeeded)
......
......@@ -542,7 +542,10 @@ private static bool HasApplicableConditionalMethod(OverloadResolutionResult<Meth
// and an ambiguity error may be reported. Also additional checks are performed in runtime final validation
// that are not performed at compile-time.
// Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime.
var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, resolution.OverloadResolutionResult, methodGroup, diagnostics);
var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, resolution.OverloadResolutionResult,
methodGroup.ReceiverOpt,
methodGroup.TypeArgumentsOpt,
diagnostics);
if (finalApplicableCandidates.Length > 0)
{
result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates, diagnostics, queryClause);
......@@ -569,11 +572,16 @@ private static bool HasApplicableConditionalMethod(OverloadResolutionResult<Meth
return result;
}
private ImmutableArray<MethodSymbol> GetCandidatesPassingFinalValidation(CSharpSyntaxNode syntax, OverloadResolutionResult<MethodSymbol> overloadResolutionResult, BoundMethodGroup methodGroup, DiagnosticBag diagnostics)
private ImmutableArray<TMethodOrPropertySymbol> GetCandidatesPassingFinalValidation<TMethodOrPropertySymbol>(
CSharpSyntaxNode syntax,
OverloadResolutionResult<TMethodOrPropertySymbol> overloadResolutionResult,
BoundExpression receiverOpt,
ImmutableArray<TypeSymbol> typeArgumentsOpt,
DiagnosticBag diagnostics) where TMethodOrPropertySymbol : Symbol
{
Debug.Assert(overloadResolutionResult.HasAnyApplicableMember);
var finalCandidates = ArrayBuilder<MethodSymbol>.GetInstance();
var finalCandidates = ArrayBuilder<TMethodOrPropertySymbol>.GetInstance();
DiagnosticBag firstFailed = null;
DiagnosticBag candidateDiagnostics = DiagnosticBag.GetInstance();
......@@ -590,8 +598,8 @@ private ImmutableArray<MethodSymbol> GetCandidatesPassingFinalValidation(CSharpS
// * If F is an instance method, the method group must have resulted from a simple-name, a member-access through a variable or value,
// or a member-access whose receiver can't be classified as a type or value until after overload resolution (see §7.6.4.1).
if (!MemberGroupFinalValidationAccessibilityChecks(methodGroup.ReceiverOpt, result.Member, syntax, candidateDiagnostics, invokedAsExtensionMethod: false) &&
(methodGroup.TypeArgumentsOpt.IsDefault || result.Member.CheckConstraints(this.Conversions, syntax, this.Compilation, candidateDiagnostics)))
if (!MemberGroupFinalValidationAccessibilityChecks(receiverOpt, result.Member, syntax, candidateDiagnostics, invokedAsExtensionMethod: false) &&
(typeArgumentsOpt.IsDefault || ((MethodSymbol)(object)result.Member).CheckConstraints(this.Conversions, syntax, this.Compilation, candidateDiagnostics)))
{
finalCandidates.Add(result.Member);
continue;
......
......@@ -3550,5 +3550,260 @@ .maxstack 8
Assert.Equal(typeGConstructed, typeD.GetMember<FieldSymbol>("ExtraTrue").Type);
Assert.Equal(typeGConstructed, typeD.GetMember<FieldSymbol>("ExtraFalse").Type);
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
[WorkItem(204561, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=204561&_a=edit")]
public void SuppressDynamicIndexerAccessOffOfType_01()
{
var iLSource = @"
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly Microsoft.Office.Interop.Excel
{
.custom instance void [mscorlib]System.Runtime.InteropServices.ImportedFromTypeLibAttribute::.ctor(string) = ( 01 00 05 45 78 63 65 6C 00 00 ) // ...Excel..
.custom instance void [mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32,
int32) = ( 01 00 01 00 00 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 30 30 30 32 30 38 31 33 2D 30 30 30 30 // ..$00020813-0000
2D 30 30 30 30 2D 63 30 30 30 2D 30 30 30 30 30 // -0000-c000-00000
30 30 30 30 30 34 36 00 00 ) // 0000046..
.custom instance void [mscorlib]System.Runtime.InteropServices.TypeLibVersionAttribute::.ctor(int32,
int32) = ( 01 00 01 00 00 00 08 00 00 00 00 00 )
.hash algorithm 0x00008004
.ver 15:0:0:0
}
.module Excel.dll
// MVID: {C7C599B3-5C80-48BC-9637-7CADFEF6DEB8}
.imagebase 0x00400000
.file alignment 0x00001000
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000009 // ILONLY
// Image base: 0x050E0000
.class interface public abstract auto ansi import Microsoft.Office.Interop.Excel.Worksheet
implements Microsoft.Office.Interop.Excel._Worksheet
{
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 30 30 30 32 30 38 44 38 2D 30 30 30 30 // ..$000208D8-0000
2D 30 30 30 30 2D 43 30 30 30 2D 30 30 30 30 30 // -0000-C000-00000
30 30 30 30 30 34 36 00 00 ) // 0000046..
} // end of class Microsoft.Office.Interop.Excel.Worksheet
.class interface public abstract auto ansi import Microsoft.Office.Interop.Excel._Worksheet
{
.custom instance void [mscorlib]System.Runtime.InteropServices.TypeLibTypeAttribute::.ctor(int16) = ( 01 00 C0 10 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 30 30 30 32 30 38 44 38 2D 30 30 30 30 // ..$000208D8-0000
2D 30 30 30 30 2D 43 30 30 30 2D 30 30 30 30 30 // -0000-C000-00000
30 30 30 30 30 34 36 00 00 ) // 0000046..
.method public hidebysig newslot specialname abstract virtual
instance class Microsoft.Office.Interop.Excel.Range
marshal( interface )
get_Range([in] object marshal( struct) Cell1,
[in][opt] object marshal( struct) Cell2) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 C5 00 00 00 00 00 )
} // end of method _Worksheet::get_Range
.property class Microsoft.Office.Interop.Excel.Range
Range(object,
object)
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 C5 00 00 00 00 00 )
.get instance class Microsoft.Office.Interop.Excel.Range Microsoft.Office.Interop.Excel._Worksheet::get_Range(object,
object)
} // end of property _Worksheet::Range
.method public hidebysig newslot specialname abstract virtual
instance class Microsoft.Office.Interop.Excel.Range
marshal( interface )
MRange([in] object marshal( struct) Cell1,
[in][opt] object marshal( struct) Cell2) runtime managed internalcall
{
.custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 C5 00 00 00 00 00 )
} // end of method _Worksheet::get_Range
}
.class interface public abstract auto ansi import Microsoft.Office.Interop.Excel.Range
implements [mscorlib]System.Collections.IEnumerable
{
.custom instance void [mscorlib]System.Runtime.InteropServices.InterfaceTypeAttribute::.ctor(int16) = ( 01 00 02 00 00 00 )
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 08 5F 44 65 66 61 75 6C 74 00 00 ) // ..._Default..
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 30 30 30 32 30 38 34 36 2D 30 30 30 30 // ..$00020846-0000
2D 30 30 30 30 2D 43 30 30 30 2D 30 30 30 30 30 // -0000-C000-00000
30 30 30 30 30 34 36 00 00 ) // 0000046..
.custom instance void [mscorlib]System.Runtime.InteropServices.TypeLibTypeAttribute::.ctor(int16) = ( 01 00 00 10 00 00 )
}
";
MetadataReference reference = CompileIL(iLSource, appendDefaultHeader: false, embedInteropTypes: false);
string consumer1 = @"
using Microsoft.Office.Interop.Excel;
class Test
{
public static void Main()
{
dynamic x = 1;
dynamic y = 1;
var z2 = Worksheet.MRange(x, y);
}
}
";
var compilation1 = CreateCompilationWithMscorlib(consumer1, options: TestOptions.ReleaseExe,
references: new MetadataReference[] { reference, CSharpRef, SystemCoreRef });
compilation1.VerifyDiagnostics(
// (11,18): error CS0120: An object reference is required for the non-static field, method, or property '_Worksheet.MRange(object, object)'
// var z2 = Worksheet.MRange(x, y);
Diagnostic(ErrorCode.ERR_ObjectRequired, "Worksheet.MRange(x, y)").WithArguments("Microsoft.Office.Interop.Excel._Worksheet.MRange(object, object)").WithLocation(11, 18)
);
string consumer2 = @"
using Microsoft.Office.Interop.Excel;
class Test
{
public static void Main()
{
dynamic x = 1;
dynamic y = 1;
var z1 = Worksheet.Range[x, y];
}
}
";
var compilation2 = CreateCompilationWithMscorlib(consumer2, options: TestOptions.ReleaseExe,
references: new MetadataReference[] { reference, CSharpRef, SystemCoreRef });
compilation2.VerifyDiagnostics(
// (10,18): error CS0120: An object reference is required for the non-static field, method, or property '_Worksheet.Range[object, object]'
// var z1 = Worksheet.Range[x, y];
Diagnostic(ErrorCode.ERR_ObjectRequired, "Worksheet.Range[x, y]").WithArguments("Microsoft.Office.Interop.Excel._Worksheet.Range[object, object]").WithLocation(10, 18)
);
}
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
[WorkItem(204561, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=204561&_a=edit")]
public void SuppressDynamicIndexerAccessOffOfType_02()
{
var iLSource = @"
.class public auto ansi WithIndexer
extends [mscorlib]System.Object
{
.method public specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method WithIndexer::.ctor
.method public specialname static object
get_Indexer(object x,
object y) cil managed
{
// Code size 18 (0x12)
.maxstack 1
.locals init (object V_0)
IL_0000: nop
IL_0001: ldstr ""Indexer""
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldnull
IL_000d: stloc.0
IL_000e: br.s IL_0010
IL_0010: ldloc.0
IL_0011: ret
} // end of method WithIndexer::get_Indexer
.method public specialname static void
set_Indexer(object x,
object y,
object 'value') cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method WithIndexer::set_Indexer
.method public static object MIndexer(object x,
object y) cil managed
{
// Code size 18 (0x12)
.maxstack 1
.locals init (object V_0)
IL_0000: nop
IL_0001: ldstr ""MIndexer""
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldnull
IL_000d: stloc.0
IL_000e: br.s IL_0010
IL_0010: ldloc.0
IL_0011: ret
} // end of method WithIndexer::MIndexer
.property object Indexer(object,
object)
{
.get object WithIndexer::get_Indexer(object,
object)
.set void WithIndexer::set_Indexer(object,
object,
object)
} // end of property WithIndexer::Indexer
} // end of class WithIndexer
";
MetadataReference reference = CompileIL(iLSource, appendDefaultHeader: true, embedInteropTypes: false);
string consumer1 = @"
class Test
{
public static void Main()
{
dynamic x = 1;
dynamic y = 1;
var z2 = WithIndexer.MIndexer(x, y);
}
}";
var compilation1 = CreateCompilationWithMscorlib(consumer1, options: TestOptions.ReleaseExe,
references: new MetadataReference[] { reference, CSharpRef, SystemCoreRef });
CompileAndVerify(compilation1, expectedOutput: "MIndexer").VerifyDiagnostics();
string consumer2 = @"
class Test
{
public static void Main()
{
dynamic x = 1;
dynamic y = 1;
var z1 = WithIndexer.Indexer[x, y];
}
}";
var compilation2 = CreateCompilationWithMscorlib(consumer2, options: TestOptions.ReleaseExe,
references: new MetadataReference[] { reference, CSharpRef, SystemCoreRef });
compilation2.VerifyDiagnostics(
// (8,30): error CS1545: Property, indexer, or event 'WithIndexer.Indexer[object, object]' is not supported by the language; try directly calling accessor methods 'WithIndexer.get_Indexer(object, object)' or 'WithIndexer.set_Indexer(object, object, object)'
// var z1 = WithIndexer.Indexer[x, y];
Diagnostic(ErrorCode.ERR_BindToBogusProp2, "Indexer").WithArguments("WithIndexer.Indexer[object, object]", "WithIndexer.get_Indexer(object, object)", "WithIndexer.set_Indexer(object, object, object)").WithLocation(8, 30)
);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册