提交 35cef3c1 编写于 作者: A AlekseyTs

C# MethodTypeInferrer.Fix: Do not consider dynamic type convertible to any...

C# MethodTypeInferrer.Fix: Do not consider dynamic type convertible to any other type in order to duplicate native compiler behavior.
***NO_CI***
 (changeset 1389606)
上级 5526b991
......@@ -2270,7 +2270,7 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
// Make a copy; don't modify the collection as we're iterating it.
foreach (var candidate in initialCandidates)
{
if (bound != candidate && !this.conversions.ClassifyImplicitConversion(bound, candidate, ref useSiteDiagnostics).Exists)
if (bound != candidate && !ImplicitConversionExists(bound, candidate, ref useSiteDiagnostics))
{
candidates.Remove(candidate);
}
......@@ -2287,7 +2287,7 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
foreach (var candidate in initialCandidates)
{
if (bound != candidate && !this.conversions.ClassifyImplicitConversion(candidate, bound, ref useSiteDiagnostics).Exists)
if (bound != candidate && !ImplicitConversionExists(candidate, bound, ref useSiteDiagnostics))
{
candidates.Remove(candidate);
}
......@@ -2299,25 +2299,31 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
// SPEC: which there is an implicit conversion from all the other candidate
// SPEC: types, then the parameter is fixed to V.
// SPEC: 4.7 The Dynamic Type
// Type inference (7.5.2) will prefer dynamic over object if both are candidates.
// This rule doesn't have to be implemented explicitly due to special handling of
// conversions from dynamic in ImplicitConversionExists helper.
TypeSymbol best = null;
foreach (var candidate in candidates)
{
foreach (var candidate2 in candidates)
{
if (candidate != candidate2 && !this.conversions.ClassifyImplicitConversion(candidate2, candidate, ref useSiteDiagnostics).Exists)
if (candidate != candidate2 && !ImplicitConversionExists(candidate2, candidate, ref useSiteDiagnostics))
{
goto OuterBreak;
}
}
// SPEC: 4.7 The Dynamic Type
// Type inference (7.5.2) will prefer dynamic over object if both are candidates.
if ((object)best == null || (best.IsObjectType() && candidate.IsDynamic()))
if ((object)best == null)
{
best = candidate;
}
else if (!(best.IsDynamic() && candidate.IsObjectType()))
{
Debug.Assert(!(best.IsObjectType() && candidate.IsDynamic()));
Debug.Assert(!(best.IsDynamic() && candidate.IsObjectType()));
// best candidate is not unique
return false;
}
......@@ -2337,6 +2343,16 @@ private bool Fix(int iParam, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
return true;
}
private bool ImplicitConversionExists(TypeSymbol source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
// SPEC VIOLATION: For the purpose of algorithm in Fix method, dynamic type is not considered convertible to any other type, including object.
if (source.IsDynamic() && !destination.IsDynamic())
{
return false;
}
return this.conversions.ClassifyImplicitConversion(source, destination, ref useSiteDiagnostics).Exists;
}
////////////////////////////////////////////////////////////////////////////////
//
......
......@@ -3285,5 +3285,110 @@ static void Foo<T>(Action<T> action, IEnumerable<T> source)
var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(n => n.Identifier.ValueText == "Foo").Single();
Assert.Equal("void Test.Foo<dynamic>(System.Action<dynamic> action, System.Collections.Generic.IEnumerable<dynamic> source)", model.GetSymbolInfo(node).Symbol.ToTestDisplayString());
}
[Fact, WorkItem(875140, "DevDiv")]
public void Bug875140_01()
{
string source = @"
using System;
using System.Reflection;
class Program
{
unsafe static void Main()
{
Action<dynamic, object> action = delegate { };
void* p = Pointer.Unbox(Foo(action));
}
static T Foo<T>(Action<T, T> x) { throw null; }
}
";
var verifier = CompileAndVerify(source, options: TestOptions.DebugDll.WithAllowUnsafe(true)).VerifyDiagnostics();
var tree = verifier.Compilation.SyntaxTrees.Single();
var model = verifier.Compilation.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(n => n.Identifier.ValueText == "Foo").Single();
Assert.Equal("System.Object Program.Foo<System.Object>(System.Action<System.Object, System.Object> x)", model.GetSymbolInfo(node).Symbol.ToTestDisplayString());
}
[Fact, WorkItem(875140, "DevDiv")]
public void Bug875140_02()
{
string source = @"
using System;
using System.Reflection;
class Program
{
unsafe static void Main()
{
Action<object, dynamic> action = delegate { };
void* p = Pointer.Unbox(Foo(action));
}
static T Foo<T>(Action<T, T> x) { throw null; }
}
";
var verifier = CompileAndVerify(source, options: TestOptions.DebugDll.WithAllowUnsafe(true)).VerifyDiagnostics();
var tree = verifier.Compilation.SyntaxTrees.Single();
var model = verifier.Compilation.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(n => n.Identifier.ValueText == "Foo").Single();
Assert.Equal("System.Object Program.Foo<System.Object>(System.Action<System.Object, System.Object> x)", model.GetSymbolInfo(node).Symbol.ToTestDisplayString());
}
[Fact, WorkItem(875140, "DevDiv")]
public void Bug875140_03()
{
string source = @"
using System;
using System.Reflection;
class Program
{
unsafe static void Main()
{
Func<object, dynamic> action = null;
void* p = Pointer.Unbox(Foo(action));
}
static T Foo<T>(Func<T, T> x) { throw null; }
}
";
CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll.WithAllowUnsafe(true)).VerifyDiagnostics(
// (10,33): error CS0411: The type arguments for method 'Program.Foo<T>(Func<T, T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// void* p = Pointer.Unbox(Foo(action));
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Foo").WithArguments("Program.Foo<T>(System.Func<T, T>)").WithLocation(10, 33)
);
}
[Fact, WorkItem(875140, "DevDiv")]
public void Bug875140_04()
{
string source = @"
using System;
class Program
{
static void Main()
{
Func<dynamic, object> action = null;
Foo(action).M1();
}
static T Foo<T>(Func<T, T> x) { throw null; }
}
";
var verifier = CompileAndVerify(source, new[] { CSharpRef, SystemCoreRef }, options: TestOptions.DebugDll).VerifyDiagnostics();
var tree = verifier.Compilation.SyntaxTrees.Single();
var model = verifier.Compilation.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(n => n.Identifier.ValueText == "Foo").Single();
Assert.Equal("dynamic Program.Foo<dynamic>(System.Func<dynamic, dynamic> x)", model.GetSymbolInfo(node).Symbol.ToTestDisplayString());
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册