Skip to content

Commit

Permalink
Merge pull request #57224 from dotnet/merges/main-to-main-vs-deps
Browse files Browse the repository at this point in the history
Merge main to main-vs-deps
  • Loading branch information
RikkiGibson authored Oct 19, 2021
2 parents 3e2946e + 09836c2 commit b1c1f6e
Show file tree
Hide file tree
Showing 29 changed files with 486 additions and 101 deletions.
3 changes: 2 additions & 1 deletion docs/Language Feature Status.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ efforts behind them.
| [Top Level statement attribute specifiers](https://github.com/dotnet/csharplang/issues/5045) | [main-attributes](https://github.com/dotnet/roslyn/tree/features/features/main-attributes) | [In Progress](https://github.com/dotnet/roslyn/issues/57047) | [chsienki](https://github.com/chsienki) | TBD | [jaredpar](https://github.com/jaredpar) |
| [Primary Constructors](https://github.com/dotnet/csharplang/issues/2691) | [primary-constructors](https://github.com/dotnet/roslyn/tree/features/features/primary-constructors) | [In Progress](https://github.com/dotnet/roslyn/issues/57048) | TBD | TBD | [MadsTorgersen](https://github.com/MadsTorgersen) |
| [Params Span<T> + Stackalloc any array type](https://github.com/dotnet/csharplang/issues/1757) | [params-span](https://github.com/dotnet/roslyn/tree/features/features/params-span) | [In Progress](https://github.com/dotnet/roslyn/issues/57049) | [cston](https://github.com/cston) | TBD | [jaredpar](https://github.com/jaredpar) |

| [Newlines in interpolations](https://github.com/dotnet/csharplang/issues/4935) | main | [In Progress](https://github.com/dotnet/roslyn/issues/57154) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [jcouv](https://github.com/jcouv), TBD | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) |

# C# 10.0

| Feature | Branch | State | Developer | Reviewer | LDM Champ |
Expand Down
5 changes: 3 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -629,10 +629,11 @@ private Tests MakeTestsAndBindingsForRelationalPattern(
BoundRelationalPattern rel,
out BoundDagTemp output)
{
Debug.Assert(rel.Value.Type is not null);
// check if the test is always true or always false
var tests = ArrayBuilder<Tests>.GetInstance(2);
output = MakeConvertToType(input, rel.Syntax, rel.Value.Type!, isExplicitTest: false, tests);
var fac = ValueSetFactory.ForType(input.Type);
output = MakeConvertToType(input, rel.Syntax, rel.Value.Type, isExplicitTest: false, tests);
var fac = ValueSetFactory.ForType(rel.Value.Type);
var values = fac?.Related(rel.Relation.Operator(), rel.ConstantValue);
if (values?.IsEmpty == true)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ int getExtendedPropertySlot(BoundPropertySubpatternMember member, int inputSlot)
protected override LocalState VisitSwitchStatementDispatch(BoundSwitchStatement node)
{
// first, learn from any null tests in the patterns
int slot = node.Expression.IsSuppressed ? GetOrCreatePlaceholderSlot(node.Expression) : MakeSlot(node.Expression);
int slot = GetSlotForSwitchInputValue(node.Expression);
if (slot > 0)
{
var originalInputType = node.Expression.Type;
Expand Down Expand Up @@ -330,7 +330,7 @@ public PossiblyConditionalState Clone()
// to evaluate the patterns. In this way we infer non-nullability of the original element's parts.
// We do not extend such courtesy to nested tuple literals.
var originalInputElementSlots = expression is BoundTupleExpression tuple
? tuple.Arguments.SelectAsArray(static (a, w) => w.MakeSlot(a), this)
? tuple.Arguments.SelectAsArray(static (a, w) => w.GetSlotForSwitchInputValue(a), this)
: default;
var originalInputMap = PooledDictionary<int, BoundExpression>.GetInstance();
originalInputMap.Add(originalInputSlot, expression);
Expand Down Expand Up @@ -512,6 +512,7 @@ public PossiblyConditionalState Clone()
break;
case BoundDagNonNullTest t:
var inputMaybeNull = this.StateWhenTrue[inputSlot].MayBeNull();

if (inputSlot > 0)
{
MarkDependentSlotsNotNull(inputSlot, inputType, ref this.StateWhenFalse);
Expand Down Expand Up @@ -758,7 +759,7 @@ public override BoundNode VisitUnconvertedSwitchExpression(BoundUnconvertedSwitc
private void VisitSwitchExpressionCore(BoundSwitchExpression node, bool inferType)
{
// first, learn from any null tests in the patterns
int slot = node.Expression.IsSuppressed ? GetOrCreatePlaceholderSlot(node.Expression) : MakeSlot(node.Expression);
int slot = GetSlotForSwitchInputValue(node.Expression);
if (slot > 0)
{
var originalInputType = node.Expression.Type;
Expand All @@ -774,7 +775,8 @@ private void VisitSwitchExpressionCore(BoundSwitchExpression node, bool inferTyp
var endState = UnreachableState();

if (!node.ReportedNotExhaustive && node.DefaultLabel != null &&
labelStateMap.TryGetValue(node.DefaultLabel, out var defaultLabelState) && defaultLabelState.believedReachable)
labelStateMap.TryGetValue(node.DefaultLabel, out var defaultLabelState) &&
defaultLabelState.believedReachable)
{
SetState(defaultLabelState.state);
var nodes = node.DecisionDag.TopologicallySortedNodes;
Expand Down Expand Up @@ -873,6 +875,11 @@ LocalState getStateForArm(BoundSwitchExpressionArm arm)
=> !arm.Pattern.HasErrors && labelStateMap.TryGetValue(arm.Label, out var labelState) ? labelState.state : UnreachableState();
}

private int GetSlotForSwitchInputValue(BoundExpression node)
{
return node.IsSuppressed ? GetOrCreatePlaceholderSlot(node) : MakeSlot(node);
}

public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node)
{
Debug.Assert(!IsConditionalState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149906,13 +149906,13 @@ public void SuppressSwitchExpressionInput()
var source =
@"#nullable enable
public class C {
public int M0(C a) => a switch { C _ => 0 }; // ok
public int M1(C? a) => a switch { C _ => 0 }; // warns
public int M2(C? a) => a! switch { C _ => 0 }; // ok
public int M0(C a) => a switch { C _ => 0 };
public int M1(C? a) => a switch { C _ => 0 }; // 1
public int M2(C? a) => a! switch { C _ => 0 };

public int M3(C a) => (1, a) switch { (_, C _) => 0 }; // ok
public int M4(C? a) => (1, a) switch { (_, C _) => 0 }; // warns
public int M5(C? a) => (1, a!) switch { (_, C _) => 0 }; // warns
public int M3(C a) => (1, a) switch { (_, C _) => 0 };
public int M4(C? a) => (1, a) switch { (_, C _) => 0 }; // 2
public int M5(C? a) => (1, a!) switch { (_, C _) => 0 };

public void M6(C? a, bool b)
{
Expand All @@ -149939,23 +149939,20 @@ public void M7(C? a, bool b)
break;
}

a.ToString(); // warns
a.ToString(); // 3
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (4,30): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern 'null' is not covered.
// public int M1(C? a) => a switch { C _ => 0 }; // warns
// public int M1(C? a) => a switch { C _ => 0 }; // 1
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("null").WithLocation(4, 30),
// (8,35): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, null)' is not covered.
// public int M4(C? a) => (1, a) switch { (_, C _) => 0 }; // warns
// public int M4(C? a) => (1, a) switch { (_, C _) => 0 }; // 2
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, null)").WithLocation(8, 35),
// (9,36): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, null)' is not covered.
// public int M5(C? a) => (1, a!) switch { (_, C _) => 0 }; // warns
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, null)").WithLocation(9, 36),
// (36,9): warning CS8602: Dereference of a possibly null reference.
// a.ToString(); // warns
// a.ToString(); // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(36, 9)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2621,5 +2621,130 @@ class A { public static implicit operator C?(A a) => null; }

comp.VerifyDiagnostics();
}

[Fact, WorkItem(51904, "https://github.com/dotnet/roslyn/issues/51904")]
public void TupleSwitchWithSuppression()
{
// When an input value is suppressed, it will get a dedicated
// slot during DAG analysis, instead of re-using the slot we might
// get from the expression

var comp = CreateCompilation(@"
#nullable enable
public class C
{
public string M1(C? a)
=> a! switch
{
C => a.ToString() // 1
};
public string M11(C? a)
=> a! switch
{
null => string.Empty,
C => a.ToString() // 2
};
public string M111(C? a)
=> a! switch
{
null => string.Empty,
_ => a.ToString() // 3
};
public string M2(C? a)
=> (1, a!) switch
{
(_, C) => a.ToString() // 4
};
public string M22(C? a)
=> (1, a!) switch
{
(_, null) => string.Empty,
(_, C) => a.ToString() // 5
};
public string M222(C? a)
=> (1, a!) switch
{
(_, null) => string.Empty,
(_, _) => a.ToString() // 6
};
public int M2222(C? a)
=> (1, a!) switch
{
(_, null) => 0,
(_, _) => 1
};
public string M3(C? a)
=> (1, a)! switch // 7
{
(_, C) => a.ToString()
};
public string M4(C? a)
=> (1, (1, a!)) switch
{
(_, (_, C)) => a.ToString() // 8
};
public string M5(C? a)
=> (1, (1, a)!) switch // 9
{
(_, (_, C)) => a.ToString() // 10
};
public string M6(C? a)
=> (1, (1, a))! switch // 11
{
(_, (_, C)) => a.ToString() // 12
};
}
");

comp.VerifyDiagnostics(
// (9,18): warning CS8602: Dereference of a possibly null reference.
// C => a.ToString() // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(9, 18),
// (16,18): warning CS8602: Dereference of a possibly null reference.
// C => a.ToString() // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(16, 18),
// (23,18): warning CS8602: Dereference of a possibly null reference.
// _ => a.ToString() // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(23, 18),
// (29,23): warning CS8602: Dereference of a possibly null reference.
// (_, C) => a.ToString() // 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(29, 23),
// (36,23): warning CS8602: Dereference of a possibly null reference.
// (_, C) => a.ToString() // 5
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(36, 23),
// (43,23): warning CS8602: Dereference of a possibly null reference.
// (_, _) => a.ToString() // 6
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(43, 23),
// (54,20): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, null)' is not covered.
// => (1, a)! switch // 7
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, null)").WithLocation(54, 20),
// (62,28): warning CS8602: Dereference of a possibly null reference.
// (_, (_, C)) => a.ToString() // 8
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(62, 28),
// (66,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, (_, null))' is not covered.
// => (1, (1, a)!) switch // 9
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, (_, null))").WithLocation(66, 25),
// (68,28): warning CS8602: Dereference of a possibly null reference.
// (_, (_, C)) => a.ToString() // 10
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(68, 28),
// (72,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, (_, null))' is not covered.
// => (1, (1, a))! switch // 11
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, (_, null))").WithLocation(72, 25),
// (74,28): warning CS8602: Dereference of a possibly null reference.
// (_, (_, C)) => a.ToString() // 12
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(74, 28)
);
}
}
}
105 changes: 105 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3565,5 +3565,110 @@ public class Wrap

CompileAndVerify(source, expectedOutput: "128");
}

[Theory, WorkItem(57148, "https://github.com/dotnet/roslyn/issues/57148")]
[InlineData("(short)0", "True")]
[InlineData("short.MinValue", "True")]
[InlineData("short.MaxValue", "True")]
[InlineData("-1", "False")]
[InlineData("(object)null", "False")]
[InlineData("string.Empty", "False")]
public void ObviousTestAfterTypeTest(string value, string expected)
{
var source = $@"
System.Console.Write(Extenders.F({value}));
static class Extenders
{{
public const short MaxValue = 0x7FFF;
public static bool F<T>(T value)
=> value switch
{{
<= MaxValue => true,
_ => false
}};
}}";
CompileAndVerify(source, expectedOutput: expected).VerifyDiagnostics();
}

[Theory, WorkItem(57148, "https://github.com/dotnet/roslyn/issues/57148")]
[InlineData("(int)0", "1")]
[InlineData("(int)255", "1")]
[InlineData("int.MinValue", "1")]
[InlineData("int.MaxValue", "4")]
[InlineData("(short)0", "2")]
[InlineData("(short)255", "2")]
[InlineData("short.MinValue", "2")]
[InlineData("short.MaxValue", "2")]
[InlineData("(uint)0", "8")]
public void ObviousTestAfterTypeTest2(string value, string expected)
{
var source = $@"
System.Console.Write(Extenders.F({value}));
public static class Extenders
{{
public static int F<T>(this T value) where T : struct
{{
int elementSize = value switch
{{
<= 255 => 1,
<= short.MaxValue => 2,
<= int.MaxValue => 4,
_ => 8
}};
return elementSize;
}}
}}";
var comp = CreateCompilationWithSpan(source);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: expected);
}

[Theory, WorkItem(57148, "https://github.com/dotnet/roslyn/issues/57148")]
[InlineData("(uint)0", "0")]
[InlineData("uint.MaxValue", "0")]
[InlineData("-1", "1")]
[InlineData("(object)null", "1")]
[InlineData("string.Empty", "1")]
public void ObviousTestAfterTypeTest_UnsignedIntegerNonNegative(string value, string expected)
{
var source = $@"
System.Console.Write(M({value}));
int M<T>(T o)
{{
return o switch
{{
>= (uint)0 => 0,
_ => 1
}};
}}";
CompileAndVerify(source, expectedOutput: expected).VerifyDiagnostics();
}

[Fact, WorkItem(57148, "https://github.com/dotnet/roslyn/issues/57148")]
public void ObviousTestAfterTypeTest_UnsignedIntegerNegative()
{
var source = @"
public class C
{
public void M<T>(T o)
{
_ = o switch
{
< (uint)0 => 0,
_ => 2
};
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (8,12): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
// < (uint)0 => 0,
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "< (uint)0").WithLocation(8, 12)
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<Compile Include="..\Core.Wpf\ExternalAccess\VSTypeScript\**\*.cs" LinkBase="ExternalAccess\VSTypeScript" />
<Compile Include="..\Core.Wpf\InlineRename\**\*.cs" Exclude="..\Core.Wpf\InlineRename\Dashboard\**\*.cs" LinkBase="InlineRename" />
<Compile Include="..\Core.Wpf\Classification\**\*.cs" LinkBase="Classification" />
<Compile Include="..\Core.Wpf\Diagnostics\**\*.cs" LinkBase="Diagnostics" />
<Compile Include="..\Core.Wpf\NavigableSymbols\**\*.cs" LinkBase="NavigableSymbols" />
<Compile Include="..\Core.Wpf\SignatureHelp\**\*.cs" LinkBase="SignatureHelp" />
<Compile Include="..\Core.Wpf\Suggestions\**\*.cs" LinkBase="Suggestions" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
Expand Down Expand Up @@ -76,9 +77,9 @@ protected override ITaggerEventSource CreateEventSource(
TaggerEventSources.OnTextChanged(subjectBuffer));
}

protected override async Task ProduceTagsAsync(TaggerContext<LineSeparatorTag> context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition)
protected override async Task ProduceTagsAsync(
TaggerContext<LineSeparatorTag> context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition, CancellationToken cancellationToken)
{
var cancellationToken = context.CancellationToken;
var document = documentSnapshotSpan.Document;
if (document == null)
{
Expand Down
Loading

0 comments on commit b1c1f6e

Please sign in to comment.