|
|
@@ -0,0 +1,316 @@
|
|
|
+# 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.
|