Skip to content

Compiler allows non-functions to be bound to active pattern names #17190

@brianrourkeboll

Description

@brianrourkeboll

There are a couple of ways in which it is possible to define "active patterns" that are (from the F# perspective) values, not functions. While the tooling treats them as active patterns, it is impossible to actually use them as patterns in any pattern-matching position.

Expected behavior

The compiler disallows defining a multi-case active pattern that is not a function:

let (|P|Q|) = Choice<unit, unit>.Choice1Of2 ()
// error FS1209: Active pattern '|P|Q|' is not a function

I would expect the same for single-case and partial active patterns.

Actual behavior

(|P|)

A value bound to what looks like a single-case active pattern name is actually compiled as a property with a getter (when a module-bound value):

let (|P|) = 3
// val (|P|) : int = 3

image

(|P|_|)

An option or value option value bound to a partial active pattern name is compiled to the exact same .NET method as it would be if it were defined as a function, but from the F# perspective it is a value (or a type function, even though you cannot give it explicit type arguments), not a function, although the tooling again treats it as an active pattern.

let (|P|_|) = None
// val (|P|_|) : 'a option

image

let (|P|_|) = ValueNone
// val (|P|_|) : 'a voption

image

Unfortunately, updating the compiler to disallow these scenarios would be a breaking change — someone could be passing values so defined around qua values (f (|P|), let r = (|P|) + (|Q|), etc.) — although I doubt anyone actually intentionally binds values to active pattern names like this in normal code.

Metadata

Metadata

Assignees

Labels

Area-Compiler-CheckingType checking, attributes and all aspects of logic checkingArea-Compiler-PatternMatchingpattern compilation, active patterns, performance, codegenBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.help wanted

Type

No fields configured for Bug.

Projects

Status

New

Relationships

None yet

Development

No branches or pull requests

Issue actions