Skip to content

Commit

Permalink
Avoid resolving parameter.Type in ReportParameterErrors() (#63142)
Browse files Browse the repository at this point in the history
  • Loading branch information
cston authored Aug 9, 2022
1 parent 5dcb44d commit 35e54c1
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ private static void ReportParameterErrors(
int firstDefault,
BindingDiagnosticBag diagnostics)
{
// This method may be called early, before parameter.Type has been resolved,
// so code below should use parameter.TypeWithAnnotations instead if unsure.

int parameterIndex = parameter.Ordinal;
bool isDefault = parameterSyntax is ParameterSyntax { Default: { } };

Expand Down Expand Up @@ -648,7 +651,7 @@ private static void ReportParameterErrors(
diagnostics.Add(ErrorCode.ERR_MethodArgCantBeRefAny, parameterSyntax.Location, parameter.Type);
}

if (parameter.DeclaredScope == DeclarationScope.ValueScoped && !parameter.Type.IsErrorTypeOrRefLikeType())
if (parameter.DeclaredScope == DeclarationScope.ValueScoped && !parameter.TypeWithAnnotations.IsRefLikeType())
{
diagnostics.Add(ErrorCode.ERR_ScopedRefAndRefStructOnly, parameterSyntax.Location);
}
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ public bool IsVoidType() =>
_extensions.IsVoid(DefaultType);
public bool IsSZArray() =>
_extensions.IsSZArray(DefaultType);
public bool IsRefLikeType() =>
_extensions.IsRefLikeType(DefaultType);
public bool IsStatic =>
_extensions.IsStatic(DefaultType);
public bool IsRestrictedType(bool ignoreSpanLikeTypes = false) =>
Expand Down Expand Up @@ -840,6 +842,7 @@ internal static Extensions CreateLazy(CSharpCompilation compilation, TypeWithAnn
internal abstract bool IsStatic(TypeSymbol typeSymbol);
internal abstract bool IsVoid(TypeSymbol typeSymbol);
internal abstract bool IsSZArray(TypeSymbol typeSymbol);
internal abstract bool IsRefLikeType(TypeSymbol typeSymbol);

internal abstract TypeWithAnnotations WithTypeAndModifiers(TypeWithAnnotations type, TypeSymbol typeSymbol, ImmutableArray<CustomModifier> customModifiers);

Expand Down Expand Up @@ -869,6 +872,7 @@ public NonLazyType(ImmutableArray<CustomModifier> customModifiers)
internal override bool IsStatic(TypeSymbol typeSymbol) => typeSymbol.IsStatic;
internal override bool IsVoid(TypeSymbol typeSymbol) => typeSymbol.IsVoidType();
internal override bool IsSZArray(TypeSymbol typeSymbol) => typeSymbol.IsSZArray();
internal override bool IsRefLikeType(TypeSymbol typeSymbol) => typeSymbol.IsRefLikeType;

internal override TypeSymbol GetNullableUnderlyingTypeOrSelf(TypeSymbol typeSymbol) => typeSymbol.StrippedType();

Expand Down Expand Up @@ -936,6 +940,7 @@ public LazyNullableTypeParameter(CSharpCompilation compilation, TypeWithAnnotati

internal override bool IsVoid(TypeSymbol typeSymbol) => false;
internal override bool IsSZArray(TypeSymbol typeSymbol) => false;
internal override bool IsRefLikeType(TypeSymbol typeSymbol) => false;
internal override bool IsStatic(TypeSymbol typeSymbol) => false;

private TypeSymbol GetResolvedType()
Expand Down
36 changes: 36 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9295,6 +9295,9 @@ static void F1(scoped Unknown x, scoped R<Unknown> y)
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (4,20): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only.
// static void F1(scoped Unknown x, scoped R<Unknown> y)
Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped Unknown x").WithLocation(4, 20),
// (4,27): error CS0246: The type or namespace name 'Unknown' could not be found (are you missing a using directive or an assembly reference?)
// static void F1(scoped Unknown x, scoped R<Unknown> y)
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unknown").WithArguments("Unknown").WithLocation(4, 27),
Expand Down Expand Up @@ -10903,6 +10906,39 @@ static void M(R<T> r) { }
Diagnostic(ErrorCode.WRN_UnreferencedField, "F").WithArguments("R<T>.F").WithLocation(4, 19));
}

[WorkItem(63140, "https://github.com/dotnet/roslyn/issues/63140")]
[Fact]
public void Scoped_Cycle()
{
var source =
@"interface I
{
void M<T>(T s);
}

class C : I
{
void I.M<T>(scoped T? s) {}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (6,11): error CS0535: 'C' does not implement interface member 'I.M<T>(T)'
// class C : I
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("C", "I.M<T>(T)").WithLocation(6, 11),
// (8,12): error CS0539: 'C.M<T>(T?)' in explicit interface declaration is not found among members of the interface that can be implemented
// void I.M<T>(scoped T? s) {}
Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M").WithArguments("C.M<T>(T?)").WithLocation(8, 12),
// (8,17): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only.
// void I.M<T>(scoped T? s) {}
Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped T? s").WithLocation(8, 17),
// (8,25): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// void I.M<T>(scoped T? s) {}
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(8, 25),
// (8,27): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>'
// void I.M<T>(scoped T? s) {}
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "s").WithArguments("System.Nullable<T>", "T", "T").WithLocation(8, 27));
}

[Fact]
public void NestedScope()
{
Expand Down

0 comments on commit 35e54c1

Please sign in to comment.