Chained pattern matching not eliminating str/arr bounds check
@EgorBo is already working on this.
Since Sep 10, 2025.
Assessment
This issue has not been assessed yet.
Description
The pattern str is { Length: 1 } && str[0] is 'x' or 'y' does not eliminate bounds checks when accessing the first char of the string (or array).
Adding extra indirection with && (sdr[0] is char c) && c is 'x' or 'y' does.
If there is only a single match in the indexer call, e.g. str[0] is 'z' the range check is properly eliminated.
Reproduces on older versions of .NET as well.
class Program
{
// range check
public static bool IsFlagsFormat(string? format) => format is { Length: 1 } && format[0] is 'f' or 'F';
public static bool IsFlagsFormat(char[]? format) => format is { Length: 1 } && format[0] is 'f' or 'F';
// no range check
public static bool IsFlagsFormat2(string? format) => format is { Length: 1 } && (format[0] is char c) && (c is 'f' or 'F');
public static bool IsFlagsFormat2(char[]? format) => format is { Length: 1 } && (format[0] is char c) && (c is 'f' or 'F');
}
https://godbolt.org/z/rKfbffMqE
Program:IsFlagsFormat(System.String):bool (FullOpts):
push rbp
mov rbp, rsp
test rdi, rdi
je SHORT G_M36473_IG04
xor eax, eax
cmp dword ptr [rdi+0x08], 1
sete al
jmp SHORT G_M36473_IG05
G_M36473_IG04: ;; offset=0x0014
xor eax, eax
G_M36473_IG05: ;; offset=0x0016
movzx rax, al
test eax, eax
je SHORT G_M36473_IG09
cmp dword ptr [rdi+0x08], 0
jbe SHORT G_M36473_IG10
movzx rax, word ptr [rdi+0x0C]
cmp eax, 70
je SHORT G_M36473_IG07
cmp eax, 102
jne SHORT G_M36473_IG08
G_M36473_IG07: ;; offset=0x0031
mov eax, 1
jmp SHORT G_M36473_IG09
G_M36473_IG08: ;; offset=0x0038
xor eax, eax
G_M36473_IG09: ;; offset=0x003A
pop rbp
ret
G_M36473_IG10: ;; offset=0x003C
call CORINFO_HELP_RNGCHKFAIL
int3
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dotnet/runtime
-
agentic-workflows untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
area-System.Reflection blocking-clean-ci-optional Known Build Error os-mac-os-x untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
area-CodeGen-coreclr untriaged
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
agentic-workflows untriaged
Difficulty 1/5 Under an hour Newbie friendliness 78/100
-
area-VM-meta-mono untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
:watch: Not Triaged 11.0 fundamentals/subsvc
Difficulty 2/5 1-3 hours Newbie friendliness 92/100
dotnet/AspNetCore.Docs#37699 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SubtitleEdit/subtitleedit#15108 · 1 comment ·
-
area/docs-content Bug pulumi/docs
Difficulty 1/5 1-3 hours Newbie friendliness 94/100
-
Create parent directories only after the containment check in InstallHelper.TryExtractToDirectory Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
PowerShell/PSResourceGet#2056 ·