dotnet/roslyn
Vedi su GitHubThere are some unnecessary defensive copies for deconstructors, implicit index & range, and foreach with explicit implementation
Open
#72.008 aperta il 8 feb 2024
Area-CompilersBughelp wanted
Metriche repository
- Star
- (20.414 star)
- Metriche merge PR
- (Merge medio 6g 17h) (256 PR mergiate in 30 g)
Descrizione
When a member is marked as readonly, a defensive copy need not be made, since the member will not mutate the struct. These are some instances of where we could avoid more defensive copies.
Version Used:
Sharplab.io Also reproduces with compiler included in .NET 8.0.100 SDK.
Steps to Reproduce:
using System;
using System.Collections;
using System.Collections.Generic;
public class C
{
public void M1(ref S1 value1, ref S2 value2)
{
int a, b;
(a, b) = value1; //defensive copy (unnecessary, since value1 is mutable?)
a = value1[^3]; //no defensive copy
_ = value1[3..4]; //no defensive copy
foreach (var x in value1) { } //no defensive copy
(a, b) = value2; //defensive copy (unnecessary)
a = value2[^3]; //no defensive copy
_ = value2[3..4]; //no defensive copy
foreach (var x in value2) { } //no defensive copy
}
public void M2(in S1 value1, in S2 value2)
{
int a, b;
(a, b) = value1; //defensive copy
a = value1[^3]; //defensive copy
_ = value1[3..4]; //defensive copy
foreach (var x in value1) { } //defensive copy
(a, b) = value2; //defensive copy (unnecessary)
a = value2[^3]; //defensive copy (unnecessary)
_ = value2[3..4]; //defensive copy (unnecessary)
foreach (var x in value2) { } //defensive copy (unnecessary)
}
}
public struct S1 : IEnumerable<int>
{
public void Deconstruct(out int a, out int b) => (a, b) = (1, 2);
public int Length => 0;
public int this[int a] => 0;
public S1 Slice(int start, int length) => this;
IEnumerator IEnumerable.GetEnumerator() => null!;
IEnumerator<int> IEnumerable<int>.GetEnumerator() => null!;
}
public struct S2 : IEnumerable<int>
{
public readonly void Deconstruct(out int a, out int b) => (a, b) = (1, 2);
public readonly int Length => 0;
public readonly int this[int a] => 0;
public readonly S2 Slice(int start, int length) => this;
readonly IEnumerator IEnumerable.GetEnumerator() => null!;
readonly IEnumerator<int> IEnumerable<int>.GetEnumerator() => null!;
}
Expected Behavior:
Members marked as "defensive copy (unnecessary)" do not emit a defensive copy.
Actual Behavior:
Members marked as "defensive copy (unnecessary)" do emit a defensive copy. The rest are correct.