Skip to content

Commit

Permalink
List patterns: add more tests and fix nullability analysis (#53822)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv authored Oct 11, 2021
1 parent acd9516 commit d7c97c6
Show file tree
Hide file tree
Showing 5 changed files with 2,168 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ private Tests MakeTestsAndBindingsForListPattern(BoundDagTemp input, BoundListPa

if (slice.Pattern is BoundPattern slicePattern)
{
var sliceEvaluation = new BoundDagSliceEvaluation(syntax, slicePattern.InputType, lengthTemp, startIndex: startIndex, endIndex: index, slice.IndexerAccess, slice.SliceMethod, input);
var sliceEvaluation = new BoundDagSliceEvaluation(slicePattern.Syntax, slicePattern.InputType, lengthTemp, startIndex: startIndex, endIndex: index, slice.IndexerAccess, slice.SliceMethod, input);
tests.Add(new Tests.One(sliceEvaluation));
var sliceTemp = new BoundDagTemp(syntax, slicePattern.InputType, sliceEvaluation);
var sliceTemp = new BoundDagTemp(slicePattern.Syntax, slicePattern.InputType, sliceEvaluation);
tests.Add(MakeTestsAndBindings(sliceTemp, slicePattern, bindings));
}

continue;
}

var indexEvaluation = new BoundDagIndexerEvaluation(syntax, subpattern.InputType, lengthTemp, index++, list.IndexerAccess, list.IndexerSymbol, input);
var indexEvaluation = new BoundDagIndexerEvaluation(subpattern.Syntax, subpattern.InputType, lengthTemp, index++, list.IndexerAccess, list.IndexerSymbol, input);
tests.Add(new Tests.One(indexEvaluation));
var indexTemp = new BoundDagTemp(syntax, subpattern.InputType, indexEvaluation);
var indexTemp = new BoundDagTemp(subpattern.Syntax, subpattern.InputType, indexEvaluation);
tests.Add(MakeTestsAndBindings(indexTemp, subpattern, bindings));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,21 @@ private void VisitBinaryOperatorChildren(BoundBinaryOperatorBase node)
return null;
}

public override BoundNode? VisitListPattern(BoundListPattern node)
{
VisitList(node.Subpatterns);
Visit(node.VariableAccess);
// Ignore indexer access (just a node to hold onto some symbols)
return null;
}

public override BoundNode? VisitSlicePattern(BoundSlicePattern node)
{
this.Visit(node.Pattern);
// Ignore indexer access (just a node to hold onto some symbols)
return null;
}

public override BoundNode? VisitSwitchExpressionArm(BoundSwitchExpressionArm node)
{
this.Visit(node.Pattern);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ public PossiblyConditionalState Clone()
var originalInputMap = PooledDictionary<int, BoundExpression>.GetInstance();
originalInputMap.Add(originalInputSlot, expression);

// Note we customize equality in BoundDagTemp
var tempMap = PooledDictionary<BoundDagTemp, (int slot, TypeSymbol type)>.GetInstance();
Debug.Assert(isDerivedType(NominalSlotType(originalInputSlot), expressionType.Type));
tempMap.Add(rootTemp, (originalInputSlot, expressionType.Type));
Expand Down Expand Up @@ -498,11 +499,77 @@ public PossiblyConditionalState Clone()
addTemp(e, e.Property.Type);
break;
case BoundDagIndexerEvaluation e:
addTemp(e, e.IndexerType);
break;
{
Debug.Assert(inputSlot > 0);
TypeWithAnnotations type;
if (e.IndexerType.IsErrorType())
{
type = TypeWithAnnotations.Create(isNullableEnabled: true, e.IndexerType, isAnnotated: false);
}
else if (e.IndexerAccess is not null)
{
// this[Index]
Debug.Assert(e.IndexerSymbol is null && e.Input.Type is not ArrayTypeSymbol);
var indexer = AsMemberOfType(inputType, e.IndexerAccess.Indexer);
type = indexer.GetTypeOrReturnType();
}
else if (e.IndexerSymbol is not null)
{
// this[int]
Debug.Assert(e.Input.Type is not ArrayTypeSymbol);
var indexer = AsMemberOfType(inputType, e.IndexerSymbol);
type = indexer.GetTypeOrReturnType();
}
else
{
// array[int]
var arrayType = (ArrayTypeSymbol)e.Input.Type;
type = arrayType.ElementTypeWithAnnotations;
}

var output = new BoundDagTemp(e.Syntax, type.Type, e);
var outputSlot = makeDagTempSlot(type, output);
Debug.Assert(outputSlot > 0);
addToTempMap(output, outputSlot, type.Type);
break;
}
case BoundDagSliceEvaluation e:
addTemp(e, e.SliceType);
break;
{
Debug.Assert(inputSlot > 0);
TypeWithAnnotations type;

if (e.SliceType.IsErrorType())
{
type = TypeWithAnnotations.Create(isNullableEnabled: true, e.SliceType, isAnnotated: false);
}
else if (e.IndexerAccess is not null)
{
// this[Range]
Debug.Assert(e.SliceMethod is null && e.Input.Type is not ArrayTypeSymbol);
var symbol = AsMemberOfType(inputType, e.IndexerAccess.Indexer);
type = symbol.GetTypeOrReturnType();
}
else if (e.SliceMethod is not null)
{
// Slice(int, int)
Debug.Assert(e.Input.Type is not ArrayTypeSymbol);
var symbol = AsMemberOfType(inputType, e.SliceMethod);
type = symbol.GetTypeOrReturnType();
}
else
{
// RuntimeHelpers.GetSubArray(T[], Range)
var arrayType = e.Input.Type;
Debug.Assert(arrayType is ArrayTypeSymbol);
type = TypeWithAnnotations.Create(isNullableEnabled: true, arrayType, isAnnotated: false);
}

var output = new BoundDagTemp(e.Syntax, type.Type, e);
var outputSlot = makeDagTempSlot(type, output);
Debug.Assert(outputSlot > 0);
addToTempMap(output, outputSlot, type.Type);
break;
}
case BoundDagAssignmentEvaluation e:
break;
default:
Expand Down
5 changes: 0 additions & 5 deletions src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ public int this[int index]
_array[index] = value;
}
}
}
class C
{
Expand All @@ -260,7 +259,6 @@ static void Main(string[] args)
var s = new S(array);
s[^1] += 5;
Console.WriteLine(array[1]);
}
}
";
Expand Down Expand Up @@ -352,7 +350,6 @@ static void Main(string[] args)
var s = new S(array);
s[1..] += 5;
Console.WriteLine(array[1]);
}
}
";
Expand Down Expand Up @@ -441,7 +438,6 @@ public string this[int index]
_array[index] = value;
}
}
}
class C
{
Expand Down Expand Up @@ -3004,7 +3000,6 @@ static Index Create(int x, out int y)
}", options: TestOptions.ReleaseExe), expectedOutput: "YES");
}


private const string PrintIndexesAndRangesCode = @"
partial class Program
{
Expand Down
Loading

0 comments on commit d7c97c6

Please sign in to comment.