提交 b3c30d9c 编写于 作者: E Evan Hauck

Fix type parameter name conflict diagnostic

上级 ead6aec7
......@@ -381,28 +381,23 @@ private bool ReportConflictWithLocal(Symbol local, Symbol newSymbol, string name
if (newSymbolKind == SymbolKind.ErrorType) return true;
if (newSymbolKind == SymbolKind.Local)
{
if (this.Locals.Contains((LocalSymbol)newSymbol) && newLocation.SourceSpan.Start >= local.Locations[0].SourceSpan.Start)
{
// A local variable named '{0}' is already defined in this scope
diagnostics.Add(ErrorCode.ERR_LocalDuplicate, newLocation, name);
return true;
}
}
var declaredInThisScope = false;
declaredInThisScope |= newSymbolKind == SymbolKind.Local && this.Locals.Contains((LocalSymbol)newSymbol);
declaredInThisScope |= newSymbolKind == SymbolKind.Method && this.LocalFunctions.Contains((LocalFunctionSymbol)newSymbol);
if (newSymbolKind == SymbolKind.Method)
if (declaredInThisScope && newLocation.SourceSpan.Start >= local.Locations[0].SourceSpan.Start)
{
if (this.LocalFunctions.Contains((LocalFunctionSymbol)newSymbol) && newLocation.SourceSpan.Start >= local.Locations[0].SourceSpan.Start)
{
// A local variable named '{0}' is already defined in this scope
diagnostics.Add(ErrorCode.ERR_LocalDuplicate, newLocation, name);
return true;
}
// TODO: Message should change to something like "A {0} named '{1}' is already defined in this scope"
// A local variable named '{0}' is already defined in this scope
diagnostics.Add(ErrorCode.ERR_LocalDuplicate, newLocation, name);
return true;
}
if (newSymbolKind == SymbolKind.Local || newSymbolKind == SymbolKind.Parameter || newSymbolKind == SymbolKind.Method)
if (newSymbolKind == SymbolKind.Local || newSymbolKind == SymbolKind.Parameter || newSymbolKind == SymbolKind.Method || newSymbolKind == SymbolKind.TypeParameter)
{
// TODO: Fix up the message for local functions and type parameters. Maybe like the above todo - $"A {newSymbolKind.Localize()} named '{name}' cannot ..."
// A local or parameter named '{0}' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
diagnostics.Add(ErrorCode.ERR_LocalIllegallyOverrides, newLocation, name);
return true;
......@@ -422,30 +417,24 @@ private bool ReportConflictWithLocal(Symbol local, Symbol newSymbol, string name
internal virtual bool EnsureSingleDefinition(Symbol symbol, string name, Location location, DiagnosticBag diagnostics)
{
LocalSymbol existingLocal;
var localsMap = this.LocalsMap;
if (localsMap != null && localsMap.TryGetValue(name, out existingLocal))
{
if (symbol == existingLocal)
{
// reference to same symbol, by far the most common case.
return false;
}
LocalSymbol existingLocal = null;
LocalFunctionSymbol existingLocalFunction = null;
return ReportConflictWithLocal(existingLocal, symbol, name, location, diagnostics);
}
LocalFunctionSymbol existingLocalFunction;
var localsMap = this.LocalsMap;
var localFunctionsMap = this.LocalFunctionsMap;
if (localFunctionsMap != null && localFunctionsMap.TryGetValue(name, out existingLocalFunction))
// TODO: Handle case where 'name' exists in both localsMap and localFunctionsMap. Right now locals are preferred over local functions.
if ((localsMap != null && localsMap.TryGetValue(name, out existingLocal)) ||
(localFunctionsMap != null && localFunctionsMap.TryGetValue(name, out existingLocalFunction)))
{
if (symbol == existingLocalFunction)
var existingSymbol = (Symbol)existingLocal ?? existingLocalFunction;
if (symbol == existingSymbol)
{
// reference to same symbol, by far the most common case.
return false;
}
return ReportConflictWithLocal(existingLocalFunction, symbol, name, location, diagnostics);
return ReportConflictWithLocal(existingSymbol, symbol, name, location, diagnostics);
}
return false;
......
......@@ -418,12 +418,15 @@ void M2()
int c = b;
void M3()
{
Print(c);
c = 2;
}
Print(b);
M3();
Print(c);
b = 2;
}
Print(a);
M2();
Print(b);
a = 2;
......@@ -442,11 +445,13 @@ void M2()
{
void M3()
{
Print(b);
b = 2;
}
M3();
Print(b);
}
Print(a);
M2();
Print(b);
a = 2;
......@@ -465,8 +470,10 @@ void M2()
int c = a;
void M3()
{
Print(c);
c = 2;
}
Print(a);
M3();
Print(c);
a = 2;
......@@ -488,8 +495,10 @@ void M2()
int c = b;
void M3()
{
Print(c);
c = 2;
}
Print(b);
M3();
Print(c);
b = 2;
......@@ -509,6 +518,7 @@ void M2()
{
void M3()
{
Print(a);
a = 2;
}
M3();
......@@ -530,6 +540,7 @@ void M2()
{
void M3()
{
Print(b);
b = 2;
}
M3();
......@@ -550,6 +561,7 @@ void M2()
int c = 0;
void M3()
{
Print(c);
c = 2;
}
M3();
......@@ -581,13 +593,13 @@ static void Main(string[] args)
";
var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions);
var verify = CompileAndVerify(comp, expectedOutput: @"
2 2 2
2 2 2
2 2 2
2 2
2 2 2
2 2
2
0 0 0 2 2 2
0 0 2 2 2
0 0 2 2 2
0 0 2 2
0 2 2 2
0 2 2
0 2
");
}
......@@ -1743,6 +1755,45 @@ void Local2()
);
}
[Fact]
public void NameConflict()
{
var source = @"
class Program
{
static void Main(string[] args)
{
void Duplicate() { }
void Duplicate() { }
int T;
void Param(int T) { }
void Generic<T>() { }
int Conflict;
void Conflict() { }
void Conflict2() { }
int Conflict2;
}
}
";
CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe.WithWarningLevel(0), parseOptions: _parseOptions).VerifyDiagnostics(
// (7,14): error CS0128: A local variable named 'Duplicate' is already defined in this scope
// void Duplicate() { }
Diagnostic(ErrorCode.ERR_LocalDuplicate, "Duplicate").WithArguments("Duplicate").WithLocation(7, 14),
// (9,24): error CS0136: A local or parameter named 'T' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// void Param(int T) { }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "T").WithArguments("T").WithLocation(9, 24),
// (10,22): error CS0136: A local or parameter named 'T' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// void Generic<T>() { }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "T").WithArguments("T").WithLocation(10, 22),
// (12,14): error CS0128: A local variable named 'Conflict' is already defined in this scope
// void Conflict() { }
Diagnostic(ErrorCode.ERR_LocalDuplicate, "Conflict").WithArguments("Conflict").WithLocation(12, 14),
// (13,14): error CS0136: A local or parameter named 'Conflict2' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// void Conflict2() { }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "Conflict2").WithArguments("Conflict2").WithLocation(13, 14)
);
}
[Fact]
public void Unsafe()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册