mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
This proposal specifies how unused pattern bindings are written in the Carbon programming language. This is a more general problem statement of "how do users specify unused function parameters" as function parameter declarations are a more specific form of pattern Related issue #1996 Co-authored-by: Geoff Romer <gromer@google.com> Co-authored-by: Richard Smith <richard@metafoo.co.uk>
317 lines
11 KiB
Markdown
317 lines
11 KiB
Markdown
# Unused Pattern Bindings (Unused Function Parameters)
|
|
|
|
<!--
|
|
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
Exceptions. See /LICENSE for license information.
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
-->
|
|
|
|
[Pull request](https://github.com/carbon-language/carbon-lang/pull/2022
|
|
|
|
<!-- toc -->
|
|
|
|
## Table of contents
|
|
|
|
- [Abstract](#abstract)
|
|
- [Problem](#problem)
|
|
- [Background](#background)
|
|
- [Proposal](#proposal)
|
|
- [Details](#details)
|
|
- [The behavior of `unused` name bindings](#the-behavior-of-unused-name-bindings)
|
|
- [Examples](#examples)
|
|
- [Rationale](#rationale)
|
|
- [Alternatives considered](#alternatives-considered)
|
|
- [Commented names](#commented-names)
|
|
- [Only short form support with `_`](#only-short-form-support-with-_)
|
|
- [Named identifiers prefixed with `_`](#named-identifiers-prefixed-with-_)
|
|
- [Anonymous, named identifiers](#anonymous-named-identifiers)
|
|
- [Attributes](#attributes)
|
|
|
|
<!-- tocstop -->
|
|
|
|
## Abstract
|
|
|
|
This proposal specifies how unused pattern bindings are written in the Carbon
|
|
programming language. This is a more general problem statement of "how do users
|
|
specify unused function parameters" as function parameter declarations are a
|
|
more specific form of pattern.
|
|
|
|
Related issue:
|
|
[#1996](https://github.com/carbon-language/carbon-lang/issues/1996).
|
|
|
|
## Problem
|
|
|
|
"How does a user of Carbon declare an unused pattern binding?"
|
|
|
|
Given that function parameters are a specific type of pattern binding, a more
|
|
specific question that will have the same answer is "How does a user of Carbon
|
|
declare an unused function parameter?"
|
|
|
|
Bindings that can be specified as unused makes code explicit and unambiguous.
|
|
Authors of code can clearly state that a value is not intended to be used. Tools
|
|
such as compilers or linters can explicitly handle a parameter that is specified
|
|
as unused, but later used, or a parameter that is unused despite not being
|
|
specified as unused.
|
|
|
|
## Background
|
|
|
|
See
|
|
[the overall design](https://github.com/carbon-language/carbon-lang/blob/09e4417431b77c05ceb2a98dd38833276514a1ff/docs/design/README.md#binding-patterns)
|
|
for the current state of things with regards to name bindings and the underscore
|
|
character, `_`.
|
|
|
|
See
|
|
[issue #476: Optional argument names (unused arguments)](https://github.com/carbon-language/carbon-lang/issues/476)
|
|
for the previous conversation on this topic.
|
|
|
|
Note: These are not exhaustive lists and not intended to be thoroughly
|
|
investigated, rather a brief overview of some prior art.
|
|
|
|
C and C++ style guides, linters, and other tools have addressed unused function
|
|
parameters specifically with varying levels of clarity for readers.
|
|
|
|
- [Standard C++ Foundation's guidelines on unused parameters](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-unused)
|
|
- [Google's C++ style guide recommendations on unused parameters](https://google.github.io/styleguide/cppguide.html#Function_Declarations_and_Definitions)
|
|
- [C++ `maybe_unused` attribute](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused)
|
|
- [GCC C `unused` attribute](https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html#index-g_t_0040code_007bunused_007d-attribute_002e-2640)
|
|
|
|
More generally, various languages use the underscore character (`_`) to signal
|
|
an unused binding or pattern.
|
|
|
|
- [Rust `_` Patterns](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#ignoring-values-in-a-pattern)
|
|
- [Golang Blank Identifiers](https://go.dev/ref/spec#Blank_identifier)
|
|
- [PyLint allows parameters starting with `_`, `ignored_`, or `unused_` to be unused](https://pylint.pycqa.org/en/latest/user_guide/configuration/all-options.html#ignored-argument-names)
|
|
- [Scala Wildcard Patterns](https://www.scala-lang.org/files/archive/spec/2.11/10-pattern-matching.html#variable-patterns)
|
|
- [Crystal `_` Cases](https://crystal-lang.org/reference/1.5/syntax_and_semantics/case.html#underscore-allowed)
|
|
|
|
## Proposal
|
|
|
|
Users can explicitly declare a value in a pattern as unused in two forms:
|
|
|
|
- `_: i32` : Using the underscore token, `_`, in place of a name.
|
|
|
|
- `unused size: i32` : Using the leading `unused` keyword followed by the
|
|
name.
|
|
|
|
## Details
|
|
|
|
Introducing two syntaxes satisfies the desire to have a terse way to discard
|
|
values, but still provides authors with a more verbose, explicit syntax that
|
|
preserves the name.
|
|
|
|
Both approaches are unambiguous -- to human readers and authors as well as
|
|
programmatic interpretations. The inclusion of an explicit `unused` keyword
|
|
allows authors to preserve the name of a value for documentation purposes, while
|
|
still explicitly marking the value as discarded in an interpretable way to
|
|
humans and programs alike.
|
|
|
|
The `unused` keyword would be a new keyword in Carbon. This keyword would only
|
|
be valid when preceding a name in a pattern binding and the keyword would
|
|
tightly bind to the following name, disallowing specifying an entire sub-pattern
|
|
as `unused`.
|
|
|
|
### The behavior of `unused` name bindings
|
|
|
|
Names that are qualified with the `unused` keyword are visible for name lookup
|
|
but uses are invalid, including when they cause ambiguous name lookup errors. If
|
|
attempted to be used, a compiler error will be shown to the user, instructing
|
|
them to either remove the `unused` qualifier or remove the use.
|
|
|
|
The inverse, where a name is not qualified by the `unused` qualifier, but never
|
|
used, will cause the compiler to emit a warning diagnostic, informing the user
|
|
that a given name was not used and suggesting to either remove the binding or
|
|
mark it as unused.
|
|
|
|
### Examples
|
|
|
|
Examples with an unused function parameter
|
|
|
|
```carbon
|
|
// Function declaration (may be in API file)
|
|
fn Sum(x: List(i32), size: i32) -> i32;
|
|
|
|
// Implementation that doesn't use the size parameter
|
|
fn Sum(x: List(i32), _: i32) -> i32 { ... }
|
|
// or:
|
|
fn Sum(x: List(i32), unused size: i32) -> i32 { ... }
|
|
```
|
|
|
|
Examples with an unused variable
|
|
|
|
```carbon
|
|
fn Bar() -> (i32, i32);
|
|
fn Foo() -> i32 {
|
|
var (x: i32, _: i32) = Bar();
|
|
// or:
|
|
var (x: i32, unused y: i32) = Bar();
|
|
|
|
return x;
|
|
}
|
|
```
|
|
|
|
Examples with an unused case binding
|
|
|
|
```carbon
|
|
fn Bar() -> (i32, i32);
|
|
fn Foo() -> i32 {
|
|
match (Bar()) {
|
|
case (42, y: i32) => {
|
|
return y;
|
|
}
|
|
case (x: i32, _: i32) => {
|
|
return x;
|
|
}
|
|
// or:
|
|
case (x: i32, unused y: i32) => {
|
|
return x;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Rationale
|
|
|
|
- This proposal supports the Carbon goal of having
|
|
[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)
|
|
- Carbon should not use symbols that are difficult to type, see, or
|
|
differentiate from similar symbols in commonly used contexts.
|
|
- Syntax should be easily parsed and scanned by any human in any
|
|
development environment, not just a machine or a human aided by semantic
|
|
hints from an IDE.
|
|
- Explicitness must be balanced against conciseness, as verbosity and
|
|
ceremony add cognitive overhead for the reader, while explicitness
|
|
reduces the amount of outside context the reader must have or assume.
|
|
|
|
This proposal uses the underscore, `_`, character to denote an unused value, a
|
|
meaning used across various other programming languages. A lone underscore
|
|
character only has a single meaning in Carbon and will be unambiguous across
|
|
contexts.
|
|
|
|
Both syntaxes are easily read by humans, either by seeing the `_` character
|
|
alone, or by introducing a keyword that allows code to read naturally such as
|
|
`unused size : i32`.
|
|
|
|
The inclusion of two syntaxes allows authors to decide when they will favor
|
|
conciseness or explicitness.
|
|
|
|
## Alternatives considered
|
|
|
|
### Commented names
|
|
|
|
C++ allows function parameters to be unnamed, allowing function declarations
|
|
such as
|
|
|
|
```
|
|
int Foo(int) { ... }
|
|
int Foo(int /*unused_name*/) { ... }
|
|
```
|
|
|
|
Advantages:
|
|
|
|
- Consistency with C++
|
|
|
|
Disadvantages:
|
|
|
|
- Carbon does not intend to support `/* */` comments, so this option is
|
|
effectively a non-starter
|
|
|
|
### Only short form support with `_`
|
|
|
|
Carbon could provide only a single way to discard a value with the underscore,
|
|
`_`, token
|
|
|
|
```
|
|
// Function declaration (may be in API file)
|
|
fn Sum(x: List(i32), size: i32) -> i32;
|
|
|
|
// Implementation that doesn't use the size parameter
|
|
fn Sum(x: List(i32), _: i32) -> i32 { ... }
|
|
```
|
|
|
|
Advantages:
|
|
|
|
- A smaller language, one less keyword, and a single way to write code
|
|
|
|
Disadvantages:
|
|
|
|
- Less expressiveness, less documentation through names
|
|
|
|
### Named identifiers prefixed with `_`
|
|
|
|
Carbon could treat identifiers prefixed with `_` as unused identifiers and
|
|
discard their names.
|
|
|
|
```
|
|
// Function declaration (may be in API file)
|
|
fn Sum(x: List(i32), size: i32) -> i32;
|
|
|
|
// Implementation that doesn't use the size parameter
|
|
fn Sum(x: List(i32), _size: i32) -> i32 { ... }
|
|
```
|
|
|
|
Advantages:
|
|
|
|
- Reuse of the underscore character in both short and long form bindings
|
|
- Functionally similar to commented names in C++
|
|
|
|
Disadvantages:
|
|
|
|
- Tying the semantics of a name being unused to the particular spelling of the
|
|
identifier (starting with a `_` character), even while it remains an
|
|
identifier seems more subtle and indirect than necessary.
|
|
- We shouldn't use identifier spellings as a side-channel for semantic
|
|
information.
|
|
- Semantics, including used versus unused, should be conveyed in an
|
|
orthogonal manner to the name rather than tying them together.
|
|
- Would require the name to change when shifting between being used or unused,
|
|
which could undermine some of its utility such as remaining for annotations,
|
|
metaprogramming, or diagnostics.
|
|
|
|
### Anonymous, named identifiers
|
|
|
|
A potential syntax for naming unused bindings while retaining the underscore,
|
|
`_`, token is an optional name suffix following the underscore token.
|
|
|
|
```
|
|
// Function declaration (may be in API file)
|
|
fn Sum(x: List(i32), size: i32) -> i32;
|
|
|
|
// Implementation that doesn't use the size parameter
|
|
fn Sum(x: List(i32), _ size: i32) -> i32 { ... }
|
|
```
|
|
|
|
Advantages:
|
|
|
|
- Reuse of the underscore token in both short and long form bindings
|
|
|
|
Disadvantages:
|
|
|
|
- The underscore token, while consistent, may be less human readable than a
|
|
dedicated keyword such as `unused`
|
|
|
|
### Attributes
|
|
|
|
While attributes aren't designed yet, there's a possibility that in the future,
|
|
the Carbon language will have some mechanism to attach metadata to parts of
|
|
source code to inform readers, compilers, and other tools. Its conceivable that
|
|
there could be an `unused` attribute which could be use to implement similar
|
|
semantics as the proposed `unused` keyword.
|
|
|
|
Advantages:
|
|
|
|
- Opens the inspection and subsequent actions taken to whatever ecosystem and
|
|
programmatic support is introduced by attributes.
|
|
- Solves a specific problem with a generic approach
|
|
- Removes the introduction of a new keyword
|
|
|
|
Disadvantages:
|
|
|
|
- Given the current proposal where `unused` bindings specify unambiguous,
|
|
absolute behavior for the compiler's handling of names, similar to the
|
|
`private` keyword, using attributes as the transport for this semantic
|
|
information is indirect.
|
|
|
|
Given that attributes are not designed and may go in a number of unknown
|
|
directions, it might be worth revisiting this option once attributes are fully
|
|
designed.
|