Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
3816bf8
Parsing for Parameter Nullchecking (#35826)
fayrose May 30, 2019
650a8d7
Merge master with param-nullchecking (#36070)
fayrose May 31, 2019
1f0d02f
Merge remote-tracking branch 'origin/features/param-nullchecking' int…
JoeRobich Jun 3, 2019
54b6387
Merge pull request #36077 from dotnet/merges/master-to-features/param…
Jun 4, 2019
584982b
Merge pull request #36145 from dotnet/merges/master-to-features/param…
Jun 4, 2019
ca55da0
Features/nullchecking error binding (#36095)
fayrose Jun 4, 2019
c96b016
Merge remote-tracking branch 'origin/features/param-nullchecking' int…
JoeRobich Jun 5, 2019
f8050ff
Merge pull request #36171 from dotnet/merges/master-to-features/param…
Jun 5, 2019
48f005f
Merge pull request #36199 from dotnet/merges/master-to-features/param…
Jun 6, 2019
adb2e77
Merge pull request #36207 from dotnet/merges/master-to-features/param…
Jun 6, 2019
fcde686
Merge pull request #36231 from dotnet/merges/master-to-features/param…
Jun 7, 2019
0d774a5
Merge pull request #36235 from dotnet/merges/master-to-features/param…
Jun 7, 2019
409bb04
Merge pull request #36257 from dotnet/merges/master-to-features/param…
Jun 10, 2019
3754748
Merge remote-tracking branch 'upstream/master' into merges/master-to-…
RikkiGibson Jun 10, 2019
f0a9368
Merge remote-tracking branch 'origin/master' into merges/master-to-fe…
JoeRobich Jun 11, 2019
e9124ed
Merge pull request #36280 from dotnet/merges/master-to-features/param…
Jun 11, 2019
d6b0118
Merge pull request #36303 from dotnet/merges/master-to-features/param…
Jun 11, 2019
3e72bb0
Param nullchecking binding (#36247)
fayrose Jun 11, 2019
0cbdca9
Merge pull request #36325 from dotnet/merges/master-to-features/param…
Jun 11, 2019
d7c97f7
Merge pull request #36343 from dotnet/merges/master-to-features/param…
Jun 12, 2019
2aad1b0
Merge pull request #36363 from dotnet/merges/master-to-features/param…
Jun 12, 2019
8f47426
Merge pull request #36376 from dotnet/merges/master-to-features/param…
Jun 12, 2019
4cc2600
Merge pull request #36394 from dotnet/merges/master-to-features/param…
Jun 13, 2019
a25a2be
Merge pull request #36425 from dotnet/merges/master-to-features/param…
Jun 13, 2019
2f8cef2
Merge pull request #36442 from dotnet/merges/master-to-features/param…
Jun 14, 2019
13ee0f8
Merge pull request #36479 from dotnet/merges/master-to-features/param…
Jun 15, 2019
e74f602
Merge pull request #36490 from dotnet/merges/master-to-features/param…
Jun 15, 2019
32017d1
Merge pull request #36531 from dotnet/merges/master-to-features/param…
Jun 18, 2019
fa959cd
Merge pull request #36558 from dotnet/merges/master-to-features/param…
Jun 19, 2019
2490bf4
Merge pull request #36580 from dotnet/merges/master-to-features/param…
Jun 19, 2019
b3e3292
Merge remote-tracking branch 'origin/features/param-nullchecking' int…
JoeRobich Jun 20, 2019
7ad94b8
Merge pull request #36603 from dotnet/merges/master-to-features/param…
Jun 20, 2019
013bacd
Merge pull request #36639 from dotnet/merges/master-to-features/param…
Jun 21, 2019
5361c72
Merge pull request #36650 from dotnet/merges/master-to-features/param…
Jun 21, 2019
8ea1ba1
Merge pull request #36662 from dotnet/merges/master-to-features/param…
Jun 22, 2019
896ee71
Merge pull request #36688 from dotnet/merges/master-to-features/param…
Jun 22, 2019
f0bb068
Merge pull request #36700 from dotnet/merges/master-to-features/param…
Jun 24, 2019
df49bc1
Merge pull request #36725 from dotnet/merges/master-to-features/param…
Jun 25, 2019
5aae233
Merge pull request #36752 from dotnet/merges/master-to-features/param…
Jun 25, 2019
5e58b2d
Merge pull request #36767 from dotnet/merges/master-to-features/param…
Jun 26, 2019
cf81eb8
Merge pull request #36778 from dotnet/merges/master-to-features/param…
Jun 26, 2019
6e5db2d
Method Declaration and Indexed Variable Lowering/Code Gen (#36471)
fayrose Jun 27, 2019
720e99d
Merge pull request #36809 from dotnet/merges/master-to-features/param…
Jun 27, 2019
2511eaf
Merge pull request #36828 from dotnet/merges/master-to-features/param…
RikkiGibson Jun 27, 2019
619a0c0
Merge pull request #36851 from dotnet/merges/master-to-features/param…
Jun 28, 2019
012ad4a
Merge pull request #36862 from dotnet/merges/master-to-features/param…
Jun 28, 2019
31c2df7
Merge pull request #36888 from dotnet/merges/master-to-features/param…
Jun 29, 2019
37b50ab
Merge pull request #36892 from dotnet/merges/master-to-features/param…
Jun 29, 2019
3d68438
Merge pull request #36923 from dotnet/merges/master-to-features/param…
Jul 2, 2019
45aa5d3
Merge pull request #36929 from dotnet/merges/master-to-features/param…
Jul 2, 2019
3ef7e34
Merge pull request #36944 from dotnet/merges/master-to-features/param…
Jul 3, 2019
bead008
Merge pull request #36955 from dotnet/merges/master-to-features/param…
Jul 3, 2019
7dc8f29
Nullchecked Lambdas and Local Functions + Constructor Tests (#36832)
fayrose Jul 3, 2019
a3d82e7
Merge pull request #36971 from dotnet/merges/master-to-features/param…
Jul 3, 2019
f3c7aef
Merge pull request #36988 from dotnet/merges/master-to-features/param…
Jul 4, 2019
8154730
Merge pull request #37000 from dotnet/merges/master-to-features/param…
Jul 5, 2019
8fe4b45
Merge pull request #37028 from dotnet/merges/master-to-features/param…
RikkiGibson Jul 6, 2019
317c253
Merge pull request #37062 from dotnet/merges/master-to-features/param…
Jul 9, 2019
07eceb5
Merge pull request #37079 from dotnet/merges/master-to-features/param…
Jul 9, 2019
ca6f780
Merge pull request #37094 from dotnet/merges/master-to-features/param…
Jul 10, 2019
8a434f5
Merge pull request #37102 from dotnet/merges/master-to-features/param…
Jul 10, 2019
fb2a494
Merge pull request #37114 from dotnet/merges/master-to-features/param…
Jul 10, 2019
96ad732
Merge pull request #37131 from dotnet/merges/master-to-features/param…
Jul 11, 2019
0b9bda0
Merge pull request #37144 from dotnet/merges/master-to-features/param…
RikkiGibson Jul 14, 2019
57c9d59
Merge branch 'features/param-nullchecking' into merges/master-to-feat…
RikkiGibson Jul 15, 2019
edbbfcc
Merge pull request #37219 from dotnet/merges/master-to-features/param…
Jul 15, 2019
be9ae33
Nullchecked Iterators + Error Messages (#36979)
fayrose Jul 17, 2019
0f11715
CFG for Parameter Nullchecking (#37381)
fayrose Jul 30, 2019
1d0776f
Added language check to null-checked parameters in parsing (#37585)
fayrose Jul 31, 2019
97d61b2
Merge remote-tracking branch 'remote/master' into merges/master-to-fe…
Jul 31, 2019
8a42a42
Merge pull request #37257 from dotnet/merges/master-to-features/param…
Jul 31, 2019
803a8bb
Merge pull request #37644 from dotnet/merges/master-to-features/param…
Aug 2, 2019
fe50866
Merge pull request #37671 from dotnet/merges/master-to-features/param…
Aug 2, 2019
c9feca0
Merge pull request #37688 from dotnet/merges/master-to-features/param…
Aug 3, 2019
da993e4
Merge pull request #37702 from dotnet/merges/master-to-features/param…
Aug 3, 2019
460b38d
Merge pull request #37736 from dotnet/merges/master-to-features/param…
Aug 5, 2019
401bd1c
Merge pull request #37746 from dotnet/merges/master-to-features/param…
Aug 6, 2019
2ca0209
Merge pull request #37776 from dotnet/merges/master-to-features/param…
Aug 7, 2019
19c19ec
Merge remote-tracking branch 'origin/master' into m
jaredpar Jul 16, 2020
2cf8ba0
Merge remote-tracking branch 'upstream/master' into features/pnc-upda…
Jul 28, 2020
eda615d
Merge pull request #46388 from kevinsun-dev/features/pnc-update-r3
jaredpar Jul 28, 2020
3f382cb
Bring features/param-nullchecking up to date (#46398)
Jul 31, 2020
3b0b5e1
[features/param-nullchecking] The BangBang Update (#46520)
Aug 11, 2020
5f0a324
Merge remote-tracking branch 'upstream/main' into merge-main-with-con…
RikkiGibson Oct 20, 2021
f5b488c
Merge main to features/param-nullchecking with conflicts (#57278)
RikkiGibson Oct 20, 2021
f907633
Merge pull request #57280 from RikkiGibson/resolve-conflicts
RikkiGibson Oct 20, 2021
6ba3dea
Fix param-nullchecking build/test failures (#57375)
RikkiGibson Nov 1, 2021
67eaccd
Merge remote-tracking branch 'upstream/main' into merges/main-to-feat…
RikkiGibson Nov 1, 2021
38e86e0
Merge pull request #57512 from dotnet/merges/main-to-features/param-n…
Nov 2, 2021
cabcb95
Use helpers in param-nullchecking emit (#57615)
RikkiGibson Nov 18, 2021
4e7c469
Merge branch 'main' of github.com:dotnet/roslyn into merges/main-to-f…
RikkiGibson Nov 18, 2021
7854604
Merge pull request #57866 from RikkiGibson/merges/main-to-features/pa…
Nov 19, 2021
ed3de52
Merge pull request #57934 from RikkiGibson/pnc-refactoring
RikkiGibson Dec 8, 2021
96698d9
Merge remote-tracking branch 'upstream/main' into merges/main-to-feat…
RikkiGibson Dec 13, 2021
4bbf0c0
Merge pull request #58183 from dotnet/merges/main-to-features/param-n…
RikkiGibson Dec 13, 2021
81e44e1
Address various minor param-nullchecking issues (#58321)
RikkiGibson Dec 15, 2021
897223b
Resolve PROTOTYPE comments in param null checking (#58324)
jaredpar Dec 15, 2021
e9c4789
Change PROTOTYPE to issue reference (#58336)
RikkiGibson Dec 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public QueryUnboundLambdaState(Binder binder, RangeVariableMap rangeVariableMap,

public override string ParameterName(int index) { return _parameters[index].Name; }
public override bool ParameterIsDiscard(int index) { return false; }
public override bool ParameterIsNullChecked(int index) { return false; }
public override SyntaxList<AttributeListSyntax> ParameterAttributes(int index) => default;
public override bool HasNames { get { return true; } }
public override bool HasSignature { get { return true; } }
Expand Down
18 changes: 17 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private UnboundLambda AnalyzeAnonymousFunction(

ImmutableArray<string> names = default;
ImmutableArray<RefKind> refKinds = default;
ImmutableArray<bool> nullCheckedOpt = default;
ImmutableArray<TypeWithAnnotations> types = default;
RefKind returnRefKind = RefKind.None;
TypeWithAnnotations returnType = default;
Expand All @@ -63,6 +64,10 @@ private UnboundLambda AnalyzeAnonymousFunction(
hasSignature = true;
var simple = (SimpleLambdaExpressionSyntax)syntax;
namesBuilder.Add(simple.Parameter.Identifier.ValueText);
if (isNullChecked(simple.Parameter))
{
nullCheckedOpt = ImmutableArray.Create(true);
}
break;
case SyntaxKind.ParenthesizedLambdaExpression:
// (T x, U y) => ...
Expand Down Expand Up @@ -98,6 +103,7 @@ private UnboundLambda AnalyzeAnonymousFunction(

var typesBuilder = ArrayBuilder<TypeWithAnnotations>.GetInstance();
var refKindsBuilder = ArrayBuilder<RefKind>.GetInstance();
var nullCheckedBuilder = ArrayBuilder<bool>.GetInstance();
var attributesBuilder = ArrayBuilder<SyntaxList<AttributeListSyntax>>.GetInstance();

// In the batch compiler case we probably should have given a syntax error if the
Expand Down Expand Up @@ -176,6 +182,7 @@ private UnboundLambda AnalyzeAnonymousFunction(
namesBuilder.Add(p.Identifier.ValueText);
typesBuilder.Add(type);
refKindsBuilder.Add(refKind);
nullCheckedBuilder.Add(isNullChecked(p));
attributesBuilder.Add(syntax.Kind() == SyntaxKind.ParenthesizedLambdaExpression ? p.AttributeLists : default);
}

Expand All @@ -191,13 +198,19 @@ private UnboundLambda AnalyzeAnonymousFunction(
refKinds = refKindsBuilder.ToImmutable();
}

if (nullCheckedBuilder.Contains(true))
{
nullCheckedOpt = nullCheckedBuilder.ToImmutable();
}

if (attributesBuilder.Any(a => a.Count > 0))
{
parameterAttributes = attributesBuilder.ToImmutable();
}

typesBuilder.Free();
refKindsBuilder.Free();
nullCheckedBuilder.Free();
attributesBuilder.Free();
}

Expand All @@ -208,7 +221,10 @@ private UnboundLambda AnalyzeAnonymousFunction(

namesBuilder.Free();

return UnboundLambda.Create(syntax, this, diagnostics.AccumulatesDependencies, returnRefKind, returnType, parameterAttributes, refKinds, types, names, discardsOpt, isAsync, isStatic);
return UnboundLambda.Create(syntax, this, diagnostics.AccumulatesDependencies, returnRefKind, returnType, parameterAttributes, refKinds, types, names, discardsOpt, nullCheckedOpt, isAsync, isStatic);

static bool isNullChecked(ParameterSyntax parameter)
=> parameter.ExclamationExclamationToken.IsKind(SyntaxKind.ExclamationExclamationToken);

static ImmutableArray<bool> computeDiscards(SeparatedSyntaxList<ParameterSyntax> parameters, int underscoresCount)
{
Expand Down
15 changes: 13 additions & 2 deletions src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ public static UnboundLambda Create(
ImmutableArray<TypeWithAnnotations> types,
ImmutableArray<string> names,
ImmutableArray<bool> discardsOpt,
ImmutableArray<bool> nullCheckedOpt,
bool isAsync,
bool isStatic)
{
Expand All @@ -391,7 +392,7 @@ public static UnboundLambda Create(
bool hasErrors = !types.IsDefault && types.Any(t => t.Type?.Kind == SymbolKind.ErrorType);

var functionType = FunctionTypeSymbol.CreateIfFeatureEnabled(syntax, binder, static (binder, expr) => ((UnboundLambda)expr).Data.InferDelegateType());
var data = new PlainUnboundLambdaState(binder, returnRefKind, returnType, parameterAttributes, names, discardsOpt, types, refKinds, isAsync, isStatic, includeCache: true);
var data = new PlainUnboundLambdaState(binder, returnRefKind, returnType, parameterAttributes, names, discardsOpt, nullCheckedOpt, types, refKinds, isAsync, isStatic, includeCache: true);
var lambda = new UnboundLambda(syntax, data, functionType, withDependencies, hasErrors: hasErrors);
data.SetUnboundLambda(lambda);
functionType?.SetExpression(lambda.WithNoCache());
Expand Down Expand Up @@ -458,6 +459,7 @@ public TypeWithAnnotations InferReturnType(ConversionsBase conversions, NamedTyp
public Location ParameterLocation(int index) { return Data.ParameterLocation(index); }
public string ParameterName(int index) { return Data.ParameterName(index); }
public bool ParameterIsDiscard(int index) { return Data.ParameterIsDiscard(index); }
public bool ParameterIsNullChecked(int index) { return Data.ParameterIsNullChecked(index); }
}

internal abstract class UnboundLambdaState
Expand Down Expand Up @@ -517,6 +519,7 @@ internal UnboundLambdaState WithCaching(bool includeCache)
public abstract MessageID MessageID { get; }
public abstract string ParameterName(int index);
public abstract bool ParameterIsDiscard(int index);
public abstract bool ParameterIsNullChecked(int index);
public abstract SyntaxList<AttributeListSyntax> ParameterAttributes(int index);
public abstract bool HasSignature { get; }
public abstract bool HasExplicitReturnType(out RefKind refKind, out TypeWithAnnotations returnType);
Expand Down Expand Up @@ -1321,6 +1324,7 @@ internal sealed class PlainUnboundLambdaState : UnboundLambdaState
private readonly ImmutableArray<SyntaxList<AttributeListSyntax>> _parameterAttributes;
private readonly ImmutableArray<string> _parameterNames;
private readonly ImmutableArray<bool> _parameterIsDiscardOpt;
private readonly ImmutableArray<bool> _parameterIsNullCheckedOpt;
private readonly ImmutableArray<TypeWithAnnotations> _parameterTypesWithAnnotations;
private readonly ImmutableArray<RefKind> _parameterRefKinds;
private readonly bool _isAsync;
Expand All @@ -1333,6 +1337,7 @@ internal PlainUnboundLambdaState(
ImmutableArray<SyntaxList<AttributeListSyntax>> parameterAttributes,
ImmutableArray<string> parameterNames,
ImmutableArray<bool> parameterIsDiscardOpt,
ImmutableArray<bool> parameterIsNullCheckedOpt,
ImmutableArray<TypeWithAnnotations> parameterTypesWithAnnotations,
ImmutableArray<RefKind> parameterRefKinds,
bool isAsync,
Expand All @@ -1345,6 +1350,7 @@ internal PlainUnboundLambdaState(
_parameterAttributes = parameterAttributes;
_parameterNames = parameterNames;
_parameterIsDiscardOpt = parameterIsDiscardOpt;
_parameterIsNullCheckedOpt = parameterIsNullCheckedOpt;
_parameterTypesWithAnnotations = parameterTypesWithAnnotations;
_parameterRefKinds = parameterRefKinds;
_isAsync = isAsync;
Expand Down Expand Up @@ -1414,6 +1420,11 @@ public override bool ParameterIsDiscard(int index)
return _parameterIsDiscardOpt.IsDefault ? false : _parameterIsDiscardOpt[index];
}

public override bool ParameterIsNullChecked(int index)
{
return _parameterIsNullCheckedOpt.IsDefault ? false : _parameterIsNullCheckedOpt[index];
}

public override RefKind RefKind(int index)
{
Debug.Assert(0 <= index && index < _parameterTypesWithAnnotations.Length);
Expand All @@ -1429,7 +1440,7 @@ public override TypeWithAnnotations ParameterTypeWithAnnotations(int index)

protected override UnboundLambdaState WithCachingCore(bool includeCache)
{
return new PlainUnboundLambdaState(Binder, _returnRefKind, _returnType, _parameterAttributes, _parameterNames, _parameterIsDiscardOpt, _parameterTypesWithAnnotations, _parameterRefKinds, _isAsync, _isStatic, includeCache);
return new PlainUnboundLambdaState(Binder, _returnRefKind, _returnType, _parameterAttributes, _parameterNames, _parameterIsDiscardOpt, _parameterIsNullCheckedOpt, _parameterTypesWithAnnotations, _parameterRefKinds, _isAsync, _isStatic, includeCache);
}

protected override BoundExpression? GetLambdaExpressionBody(BoundBlock body)
Expand Down
27 changes: 27 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@
<data name="IDS_FeatureTypeVariance" xml:space="preserve">
<value>type variance</value>
</data>
<data name="IDS_ParameterNullChecking" xml:space="preserve">
<value>parameter null-checking</value>
</data>
<data name="IDS_Parameter" xml:space="preserve">
<value>parameter</value>
</data>
Expand Down Expand Up @@ -6166,6 +6169,30 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_DuplicateNullSuppression" xml:space="preserve">
<value>Duplicate null suppression operator ('!')</value>
</data>
<data name="ERR_IncorrectNullCheckSyntax" xml:space="preserve">
<value>Incorrect parameter null checking syntax. Should be '!!'.</value>
</data>
<data name="ERR_MustNullCheckInImplementation" xml:space="preserve">
<value>Parameter '{0}' can only have exclamation-point null checking in implementation methods.</value>
</data>
<data name="ERR_NonNullableValueTypeIsNullChecked" xml:space="preserve">
<value>Parameter '{0}' is a non-nullable value type and cannot be null-checked.</value>
</data>
<data name="WRN_NullCheckedHasDefaultNull" xml:space="preserve">
<value>Parameter '{0}' is null-checked but is null by default.</value>
</data>
<data name="WRN_NullCheckedHasDefaultNull_Title" xml:space="preserve">
<value>Parameter is null-checked but is null by default.</value>
</data>
<data name="ERR_NullCheckingOnByRefParameter" xml:space="preserve">
<value>By-reference parameter '{0}' cannot be null-checked.</value>
</data>
<data name="WRN_NullCheckingOnNullableType" xml:space="preserve">
<value>Nullable type '{0}' is null-checked and will throw if null.</value>
</data>
<data name="WRN_NullCheckingOnNullableType_Title" xml:space="preserve">
<value>Nullable type is null-checked and will throw if null.</value>
</data>
<data name="ERR_ReAbstractionInNoPIAType" xml:space="preserve">
<value>Type '{0}' cannot be embedded because it has a re-abstraction of a member from base interface. Consider setting the 'Embed Interop Types' property to false.</value>
</data>
Expand Down
25 changes: 21 additions & 4 deletions src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&

hasErrors = hasErrors || (hasBody && loweredBodyOpt.HasErrors) || diagsForCurrentMethod.HasAnyErrors();
SetGlobalErrorIfTrue(hasErrors);

CSharpSyntaxNode syntax = methodSymbol.GetNonNullSyntaxNode();
// don't emit if the resulting method would contain initializers with errors
if (!hasErrors && (hasBody || includeNonEmptyInitializersInBody))
{
Expand Down Expand Up @@ -1290,12 +1290,29 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
{
boundStatements = boundStatements.Concat(ImmutableArray.Create(loweredBodyOpt));
}
}

var factory = new SyntheticBoundNodeFactory(methodSymbol, syntax, compilationState, diagsForCurrentMethod);

// Iterators handled in IteratorRewriter.cs
if (!methodSymbol.IsIterator)
{
var boundStatementsWithNullCheck = LocalRewriter.TryConstructNullCheckedStatementList(methodSymbol.Parameters, boundStatements, factory);

if (!boundStatementsWithNullCheck.IsDefault)
{
boundStatements = boundStatementsWithNullCheck;
hasErrors = boundStatementsWithNullCheck.HasErrors() || diagsForCurrentMethod.HasAnyErrors();
SetGlobalErrorIfTrue(hasErrors);
if (hasErrors)
{
_diagnostics.AddRange(diagsForCurrentMethod);
return;
}
}
}
}
if (_emitMethodBodies && (!(methodSymbol is SynthesizedStaticConstructor cctor) || cctor.ShouldEmit(processedInitializers.BoundInitializers)))
{
CSharpSyntaxNode syntax = methodSymbol.GetNonNullSyntaxNode();

var boundBody = BoundStatementList.Synthesized(syntax, boundStatements);

var emittedBody = GenerateMethodBody(
Expand Down
39 changes: 37 additions & 2 deletions src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,18 +1289,19 @@ internal Cci.IMethodReference Translate(
}
}

#nullable enable
private Cci.IMethodReference Translate(
MethodSymbol methodSymbol,
SyntaxNode syntaxNodeOpt,
DiagnosticBag diagnostics,
bool needDeclaration)
{
object reference;
object? reference;
Cci.IMethodReference methodRef;
NamedTypeSymbol container = methodSymbol.ContainingType;

// Method of anonymous type being translated
if (container.IsAnonymousType)
if (container?.IsAnonymousType == true)
{
Debug.Assert(!needDeclaration);
methodSymbol = AnonymousTypeManager.TranslateAnonymousTypeMethodSymbol(methodSymbol);
Expand Down Expand Up @@ -1363,6 +1364,7 @@ private Cci.IMethodReference Translate(

return methodSymbol.GetCciAdapter();
}
#nullable disable

internal Cci.IMethodReference TranslateOverriddenMethodReference(
MethodSymbol methodSymbol,
Expand Down Expand Up @@ -1777,6 +1779,39 @@ internal void EnsureNativeIntegerAttributeExists()
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute);
}

#nullable enable
/// <summary>
/// Creates the ThrowIfNull and Throw helpers if needed.
/// </summary>
/// <remarks>
/// The ThrowIfNull and Throw helpers are modeled off of the helpers on ArgumentNullException.
/// https://github.com/dotnet/runtime/blob/22663769611ba89cd92d14cfcb76e287f8af2335/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs#L56-L69
/// </remarks>
internal MethodSymbol EnsureThrowIfNullFunctionExists(SyntaxNode syntaxNode, SyntheticBoundNodeFactory factory, DiagnosticBag? diagnostics)
{
var privateImplClass = GetPrivateImplClass(syntaxNode, diagnostics);
var throwIfNullAdapter = privateImplClass.GetMethod(PrivateImplementationDetails.SynthesizedThrowIfNullFunctionName);
if (throwIfNullAdapter is null)
{
TypeSymbol returnType = factory.SpecialType(SpecialType.System_Void);
TypeSymbol argumentType = factory.SpecialType(SpecialType.System_Object);
TypeSymbol paramNameType = factory.SpecialType(SpecialType.System_String);
var sourceModule = SourceModule;

// use add-then-get pattern to ensure the symbol exists, and then ensure we use the single "canonical" instance added by whichever thread won the race.
privateImplClass.TryAddSynthesizedMethod(new SynthesizedThrowMethod(sourceModule, privateImplClass, returnType, paramNameType).GetCciAdapter());
var actuallyAddedThrowMethod = (SynthesizedThrowMethod)privateImplClass.GetMethod(PrivateImplementationDetails.SynthesizedThrowFunctionName)!.GetInternalSymbol()!;
privateImplClass.TryAddSynthesizedMethod(new SynthesizedThrowIfNullMethod(sourceModule, privateImplClass, actuallyAddedThrowMethod, returnType, argumentType, paramNameType).GetCciAdapter());
throwIfNullAdapter = privateImplClass.GetMethod(PrivateImplementationDetails.SynthesizedThrowIfNullFunctionName)!;
}

var internalSymbol = (SynthesizedThrowIfNullMethod)throwIfNullAdapter.GetInternalSymbol()!;
// the ThrowMethod referenced by the ThrowIfNullMethod must be the same instance as the ThrowMethod contained in the PrivateImplementationDetails
Debug.Assert((object?)privateImplClass.GetMethod(PrivateImplementationDetails.SynthesizedThrowFunctionName)!.GetInternalSymbol() == internalSymbol.ThrowMethod);
return internalSymbol;
}
#nullable disable

public override IEnumerable<Cci.INamespaceTypeDefinition> GetAdditionalTopLevelTypeDefinitions(EmitContext context)
{
return GetAdditionalTopLevelTypes()
Expand Down
7 changes: 7 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,13 @@ internal enum ErrorCode
// at runtime.
ERR_CannotUseRefInUnmanagedCallersOnly = 8977,

ERR_IncorrectNullCheckSyntax = 8990,
ERR_MustNullCheckInImplementation = 8991,
ERR_NonNullableValueTypeIsNullChecked = 8992,
WRN_NullCheckedHasDefaultNull = 8993,
ERR_NullCheckingOnByRefParameter = 8994,
WRN_NullCheckingOnNullableType = 8995,

#endregion

#region diagnostics introduced for C# 11.0
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_UndecoratedCancellationTokenParameter:
case ErrorCode.WRN_NullabilityMismatchInTypeParameterNotNullConstraint:
case ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment:
case ErrorCode.WRN_NullCheckedHasDefaultNull:
case ErrorCode.WRN_NullCheckingOnNullableType:
case ErrorCode.WRN_ParameterConditionallyDisallowsNull:
case ErrorCode.WRN_NullReferenceInitializer:
case ErrorCode.WRN_ShouldNotReturn:
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ internal enum MessageID

IDS_FeatureNewLinesInInterpolations = MessageBase + 12813,
IDS_FeatureListPattern = MessageBase + 12814,
IDS_ParameterNullChecking = MessageBase + 12815,
}

// Message IDs may refer to strings that need to be localized.
Expand Down Expand Up @@ -353,6 +354,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
case MessageID.IDS_FeatureGenericAttributes: // semantic check
case MessageID.IDS_FeatureNewLinesInInterpolations: // semantic check
case MessageID.IDS_FeatureListPattern: // semantic check
case MessageID.IDS_ParameterNullChecking: // syntax check
return LanguageVersion.Preview;

// C# 10.0 features.
Expand Down
Loading