├── uv.lock.license ├── themes └── fls │ ├── static │ ├── fonts │ │ ├── raleway-400.ttf │ │ ├── raleway-700.ttf │ │ ├── raleway-400.woff2 │ │ ├── raleway-700.woff2 │ │ ├── roboto-mono-400.ttf │ │ ├── roboto-mono-700.ttf │ │ ├── raleway-400-italic.ttf │ │ ├── raleway-700-italic.ttf │ │ ├── roboto-mono-400.ttf.license │ │ ├── roboto-mono-400.woff2 │ │ ├── roboto-mono-400.woff2.license │ │ ├── roboto-mono-700.ttf.license │ │ ├── roboto-mono-700.woff2 │ │ ├── roboto-mono-700.woff2.license │ │ ├── raleway-400-italic.woff2 │ │ ├── raleway-700-italic.woff2 │ │ ├── roboto-mono-400-italic.ttf.license │ │ ├── roboto-mono-400-italic.woff2.license │ │ ├── roboto-mono-700-italic.ttf.license │ │ ├── roboto-mono-700-italic.woff2.license │ │ ├── roboto-mono-400-italic.ttf │ │ ├── roboto-mono-400-italic.woff2 │ │ ├── roboto-mono-700-italic.ttf │ │ ├── roboto-mono-700-italic.woff2 │ │ ├── raleway-400.ttf.license │ │ ├── raleway-700.ttf.license │ │ ├── raleway-400.woff2.license │ │ ├── raleway-700.woff2.license │ │ ├── raleway-400-italic.ttf.license │ │ ├── raleway-400-italic.woff2.license │ │ ├── raleway-700-italic.ttf.license │ │ └── raleway-700-italic.woff2.license │ ├── rust-lang.svg │ └── favicon.svg │ ├── theme.toml │ ├── __init__.py │ ├── search.html │ ├── fontawesome.html │ └── layout.html ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── change.yml └── workflows │ └── ci.yml ├── version.rst ├── .gitattributes ├── .flake8 ├── .gitignore ├── pyproject.toml ├── src ├── undefined-behavior.rst ├── index.rst ├── items.rst ├── unsafety.rst ├── conf.py ├── exceptions-and-errors.rst ├── background.rst ├── concurrency.rst ├── statements.rst ├── associated-items.rst ├── functions.rst ├── program-structure-and-compilation.rst ├── ffi.rst ├── implementations.rst ├── values.rst ├── general.rst └── licenses.rst ├── generate-random-ids.py ├── triagebot.toml ├── exts ├── ferrocene_spec │ ├── std_role.py │ ├── utils.py │ ├── definitions │ │ ├── terms.py │ │ ├── syntax.py │ │ ├── code_terms.py │ │ ├── paragraphs.py │ │ └── __init__.py │ ├── sphinx_fixes.py │ ├── __init__.py │ ├── informational.py │ ├── paragraph_ids.py │ ├── items_with_rubric.py │ ├── README.rst │ └── syntax_directive.py ├── ferrocene_spec_lints │ ├── __init__.py │ ├── alphabetical_section_titles.py │ └── require_paragraph_ids.py └── ferrocene_toctrees.py ├── LICENSES ├── MIT.txt ├── OFL-1.1.txt └── Apache-2.0.txt ├── CONTRIBUTING.rst ├── README.rst └── make.py /uv.lock.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-400.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-700.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-400.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-700.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-400.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-700.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-400-italic.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-700-italic.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-400.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-700.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-400-italic.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/raleway-700-italic.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400-italic.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400-italic.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700-italic.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700-italic.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | SPDX-FileCopyrightText: Christian Robertson 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-400-italic.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-400-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-400-italic.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-700-italic.ttf -------------------------------------------------------------------------------- /themes/fls/static/fonts/roboto-mono-700-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-lang/fls/HEAD/themes/fls/static/fonts/roboto-mono-700-italic.woff2 -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400-italic.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-400-italic.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700-italic.ttf.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /themes/fls/static/fonts/raleway-700-italic.woff2.license: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: OFL-1.1 2 | SPDX-FileCopyrightText: The Raleway Project Authors (impallari@gmail.com) 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Rust Project Developers 3 | 4 | blank_issues_enabled: true 5 | -------------------------------------------------------------------------------- /version.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | SPDX-FileCopyrightText: The Rust Project Developers 4 | .. |spec_version| replace:: 1.90.0 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Rust Project Developers 3 | 4 | # Instruct linguist not to ignore the main content 5 | # https://github.com/github-linguist/linguist/blob/master/docs/overrides.md 6 | src/*.rst text linguist-detectable 7 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | # Configuration recommended by Black 5 | # https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#flake8 6 | 7 | [flake8] 8 | max-line-length = 88 9 | extend-ignore = E203 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | # Sphinx ignored files 5 | /build 6 | /.venv 7 | 8 | # Python ignored files 9 | __pycache__ 10 | *.py[co] 11 | 12 | # Linkchecker ignored files 13 | /.linkchecker 14 | 15 | # Mac OS ignored files 16 | .DS_Store 17 | -------------------------------------------------------------------------------- /themes/fls/theme.toml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | # SPDX-FileCopyrightText: The Rust Project Developers 4 | 5 | [theme] 6 | inherit = "basic" 7 | stylesheets = ["fls.css"] 8 | 9 | [options] 10 | license = "" 11 | commit = "" 12 | include_in_header = "" 13 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | # SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | [project] 6 | name = "fls" 7 | version = "0.0.0" 8 | 9 | requires-python = ">= 3.10" 10 | dependencies = [ 11 | "sphinx ~= 8.0", 12 | "sphinx-autobuild >= 0", # Doesn't use semver. 13 | ] 14 | -------------------------------------------------------------------------------- /themes/fls/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from pathlib import Path 5 | 6 | 7 | def setup(app): 8 | app.add_html_theme("ferrocene", Path(__file__).resolve().parent) 9 | 10 | return { 11 | "version": "0", 12 | "parallel_read_safe": True, 13 | "parallel_write_safe": True, 14 | } 15 | -------------------------------------------------------------------------------- /src/undefined-behavior.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | .. default-domain:: spec 6 | .. informational-page:: 7 | 8 | .. _fls_EBwqH60SUHiN: 9 | 10 | List of undefined behavior 11 | ========================== 12 | 13 | :dp:`fls_f9mkI99mzPxY` 14 | The following sections of the FLS document undefined behavior: 15 | 16 | .. items-with-rubric:: Undefined Behavior 17 | -------------------------------------------------------------------------------- /themes/fls/search.html: -------------------------------------------------------------------------------- 1 | {# SPDX-License-Identifier: MIT OR Apache-2.0 #} 2 | {# SPDX-FileCopyrightText: The Ferrocene Developers #} 3 | 4 | {% extends "basic/search.html" %} 5 | 6 | {% block body %} 7 | 13 |
14 | 15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /generate-random-ids.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S uv run 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # SPDX-FileCopyrightText: The Ferrocene Developers 4 | 5 | # Convenience script to generate a list of random paragraph IDs, ready to be 6 | # copy-pasted as you write new paragraphs. 7 | 8 | import string 9 | import random 10 | 11 | CHARS = string.ascii_letters + string.digits 12 | LENGTH = 12 13 | GENERATE = 10 14 | 15 | for _ in range(GENERATE): 16 | id = "".join(random.choice(CHARS) for _ in range(LENGTH)) 17 | print(f":dp:`fls_{id}`") 18 | -------------------------------------------------------------------------------- /triagebot.toml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Rust Project Contributors 3 | 4 | # Ease review after a rebase be ensuring no other changes occurred. 5 | # https://forge.rust-lang.org/triagebot/range-diff.html 6 | [range-diff] 7 | 8 | # Canonicalize issue mentions (change "fixes #1234" to "fixes rust-lang/fls#1234"), 9 | # to avoid wrong mentions where this repo (rust-lang/fls) is a subtree to another repo. 10 | # https://forge.rust-lang.org/triagebot/issue-links.html 11 | [issue-links] 12 | check-commits = false 13 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/std_role.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | from sphinx.roles import SphinxRole 6 | from urllib.parse import quote 7 | from .definitions import parse_target_from_text 8 | 9 | 10 | class StdRefRole(SphinxRole): 11 | def run(self): 12 | text, target = parse_target_from_text(self.text) 13 | url = f"{self.env.config.spec_std_docs_url}/?search={quote(target)}" 14 | 15 | node = nodes.reference(internal=False, refuri=url) 16 | node += nodes.literal("", text) 17 | 18 | return [node], [] 19 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/utils.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | 6 | 7 | def section_id_and_anchor(section): 8 | if "names" in section: 9 | try: 10 | id = [name for name in section["names"] if name.startswith("fls_")][0] 11 | except IndexError: 12 | raise NoSectionIdError() 13 | else: 14 | raise NoSectionIdError() 15 | 16 | if section.parent is not None and isinstance(section.parent, nodes.document): 17 | anchor = "" 18 | else: 19 | anchor = "#" + section["ids"][0] 20 | 21 | return id, anchor 22 | 23 | 24 | class NoSectionIdError(RuntimeError): 25 | pass 26 | -------------------------------------------------------------------------------- /exts/ferrocene_spec_lints/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | import sphinx 5 | import typing 6 | from . import alphabetical_section_titles, require_paragraph_ids 7 | 8 | 9 | def run_lints(app, env): 10 | alphabetical_section_titles.check(app, raise_error) 11 | require_paragraph_ids.check(app, raise_error) 12 | 13 | 14 | def raise_error(message, *, location=None): 15 | logger = sphinx.util.logging.getLogger(__name__) 16 | logger.warning(message, location=location) 17 | 18 | 19 | def setup(app): 20 | app.connect("env-check-consistency", run_lints) 21 | 22 | app.add_config_value("lint_alphabetical_section_titles", [], "", typing.List[str]) 23 | app.add_config_value("lint_no_paragraph_ids", [], "", typing.List[str]) 24 | 25 | return { 26 | "version": "0", 27 | "parallel_read_safe": True, 28 | "parallel_write_safe": True, 29 | } 30 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/definitions/terms.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | 6 | 7 | ROLE = "term" 8 | NAME = "term" 9 | PRETTY_NAME = "term" 10 | 11 | 12 | class Term: 13 | def __init__(self, id, document): 14 | self.id = id 15 | self.document = document 16 | 17 | def anchor(self): 18 | return f"term_{self.id}" 19 | 20 | def include_in_search(self): 21 | return True 22 | 23 | def display_name(self, env): 24 | return self.id 25 | 26 | 27 | def collect_items_in_document(app, nodes): 28 | for node in nodes: 29 | yield Term(node["def_id"], app.env.docname) 30 | 31 | 32 | def replace_id_node(app, node, term): 33 | new = nodes.emphasis("", node["def_text"]) 34 | new["ids"].append(term.anchor()) 35 | node.replace_self(new) 36 | 37 | 38 | def create_ref_node(env, text, item): 39 | return nodes.Text(text) 40 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/definitions/syntax.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | 6 | 7 | ROLE = "syntax" 8 | NAME = "syntaxes" 9 | PRETTY_NAME = "syntactic category" 10 | 11 | 12 | class Syntax: 13 | def __init__(self, id, document): 14 | self.id = id 15 | self.document = document 16 | 17 | def anchor(self): 18 | return f"syntax_{self.id}" 19 | 20 | def include_in_search(self): 21 | return True 22 | 23 | def display_name(self, env): 24 | return self.id 25 | 26 | 27 | def collect_items_in_document(app, nodes): 28 | for node in nodes: 29 | yield Syntax(node["def_id"], app.env.docname) 30 | 31 | 32 | def replace_id_node(app, node, syntax): 33 | new = nodes.literal("", node["def_text"]) 34 | new["ids"].append(syntax.anchor()) 35 | node.replace_self(new) 36 | 37 | 38 | def create_ref_node(env, text, item): 39 | return nodes.literal("", text) 40 | -------------------------------------------------------------------------------- /src/index.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | FLS 6 | === 7 | 8 | .. toctree:: 9 | :numbered: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | general 14 | lexical-elements 15 | items 16 | types-and-traits 17 | patterns 18 | expressions 19 | values 20 | statements 21 | functions 22 | associated-items 23 | implementations 24 | generics 25 | attributes 26 | entities-and-resolution 27 | ownership-and-deconstruction 28 | exceptions-and-errors 29 | concurrency 30 | program-structure-and-compilation 31 | unsafety 32 | macros 33 | ffi 34 | inline-assembly 35 | 36 | .. appendices:: 37 | :numbered: 38 | :maxdepth: 1 39 | :caption: Appendices: 40 | 41 | licenses 42 | glossary 43 | undefined-behavior 44 | changelog 45 | background 46 | 47 | Indices and tables 48 | ------------------ 49 | 50 | * :ref:`search` 51 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/definitions/code_terms.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | 6 | 7 | ROLE = "codeterm" 8 | NAME = "code_terms" 9 | PRETTY_NAME = "programmatic construct" 10 | 11 | 12 | class CodeTerm: 13 | def __init__(self, id, document): 14 | self.id = id 15 | self.document = document 16 | 17 | def anchor(self): 18 | return f"codeterm_{self.id}" 19 | 20 | def include_in_search(self): 21 | return True 22 | 23 | def display_name(self, env): 24 | return self.id 25 | 26 | 27 | def collect_items_in_document(app, nodes): 28 | for node in nodes: 29 | yield CodeTerm(node["def_id"], app.env.docname) 30 | 31 | 32 | def replace_id_node(app, node, term): 33 | new = nodes.emphasis("", "") 34 | new["ids"].append(term.anchor()) 35 | new += nodes.literal("", node["def_text"]) 36 | node.replace_self(new) 37 | 38 | 39 | def create_ref_node(env, text, item): 40 | return nodes.literal("", text) 41 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /exts/ferrocene_spec_lints/alphabetical_section_titles.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | import re 5 | from docutils import nodes 6 | 7 | 8 | SPLIT_NUMBERS = re.compile(r"([0-9]+)") 9 | 10 | 11 | def check(app, raise_error): 12 | for docname in app.config.lint_alphabetical_section_titles: 13 | recursive_check(app.env.get_doctree(docname), raise_error) 14 | 15 | 16 | def recursive_check(node, raise_error): 17 | prev_title = None 18 | 19 | for child in node.children: 20 | recursive_check(child, raise_error) 21 | 22 | if nodes.section is type(child): 23 | title_node = next(child.findall(nodes.title)) 24 | title = title_node.astext() 25 | if prev_title is not None and not compare_titles(prev_title, title): 26 | raise_error( 27 | f"unordered sections: '{title}' should be before '{prev_title}'", 28 | location=title_node, 29 | ) 30 | prev_title = title 31 | 32 | 33 | def compare_titles(prev, next): 34 | def key(k): 35 | return [(int(c) if c.isdigit() else c.lower()) for c in SPLIT_NUMBERS.split(k)] 36 | 37 | return key(prev) < key(next) 38 | -------------------------------------------------------------------------------- /themes/fls/fontawesome.html: -------------------------------------------------------------------------------- 1 | {# SPDX-License-Identifier: CC-BY-4.0 #} 2 | {# SPDX-FileCopyrightText: Fonticons, Inc #} 3 | 4 | {# To use Font Awesome icons in our templates, we define a macro with the icon 5 | name and inline the SVG in it. This way the SVG won't be loaded with a 6 | separate request, and it'll be possible to style the icon through CSS. #} 7 | 8 | {# Please ensure the SVG you download has "Font Awesome Free" in the comment, 9 | not "Font Awesome Pro", otherwise the icon is subject to a proprietary 10 | license. If the download from the website is marked as pro, download the SVG 11 | from the GitHub repository instead. #} 12 | 13 | {% macro icon_search() %} 14 | 15 | 16 | 17 | 18 | {% endmacro %} 19 | -------------------------------------------------------------------------------- /src/items.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_wb86edg02t6a: 7 | 8 | Items 9 | ===== 10 | 11 | .. rubric:: Syntax 12 | 13 | .. syntax:: 14 | 15 | Item ::= 16 | OuterAttributeOrDoc* (ItemWithVisibility | MacroItem) 17 | 18 | ItemWithVisibility ::= 19 | VisibilityModifier? ( 20 | ConstantDeclaration 21 | | EnumDeclaration 22 | | ExternalBlock 23 | | ExternalCrateImport 24 | | FunctionDeclaration 25 | | Implementation 26 | | ModuleDeclaration 27 | | StaticDeclaration 28 | | StructDeclaration 29 | | TraitDeclaration 30 | | TypeAliasDeclaration 31 | | UnionDeclaration 32 | | UseImport 33 | ) 34 | 35 | MacroItem ::= 36 | MacroRulesDeclaration 37 | | TerminatedMacroInvocation 38 | 39 | ItemSafety ::= 40 | $$unsafe$$ 41 | | $$safe$$ 42 | 43 | .. rubric:: Legality Rules 44 | 45 | :dp:`fls_s3b1cba9lfj5` 46 | The :t:`macro expansion` of a :t:`terminated macro invocation` is treated as 47 | zero or more :t:`[item]s` if the :t:`terminated macro invocation` appears as 48 | an :t:`item`. 49 | 50 | .. rubric:: Dynamic Semantics 51 | 52 | :dp:`fls_hil5f7y4xdhe` 53 | :t:`Elaboration` is the process by which a :t:`declaration` achieves its runtime 54 | effects. 55 | 56 | -------------------------------------------------------------------------------- /src/unsafety.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_jep7p27kaqlp: 7 | 8 | Unsafety 9 | ======== 10 | 11 | .. rubric:: Legality Rules 12 | 13 | :dp:`fls_8kqo952gjhaf` 14 | :t:`Unsafety` is the presence of :t:`[unsafe operation]s` and :t:`[unsafe trait 15 | implementation]s` in program text. 16 | 17 | :dp:`fls_ovn9czwnwxue` 18 | An :t:`unsafe operation` is an operation that may result in 19 | :t:`undefined behavior` that is not diagnosed as a static error. 20 | :t:`[Unsafe operation]s` are referred to as :t:`unsafe Rust`. 21 | 22 | :dp:`fls_pfhmcafsjyf7` 23 | The :t:`[unsafe operation]s` are: 24 | 25 | * :dp:`fls_jd1inwz7ulyw` 26 | Dereferencing a :t:`value` of a :t:`raw pointer type`. 27 | 28 | * :dp:`fls_3ra8s1v1vbek` 29 | Reading or writing an :t:`external static`. 30 | 31 | * :dp:`fls_6ipl0xo5qjyl` 32 | Reading or writing a :t:`mutable static`. 33 | 34 | * :dp:`fls_ucghxcnpaq2t` 35 | Accessing a :t:`field` of a :t:`union`, other than to assign to it. 36 | 37 | * :dp:`fls_ljocmnaz2m49` 38 | Calling an :t:`unsafe function`. 39 | 40 | * :dp:`fls_s5nfhBFOk8Bu` 41 | Calling :t:`macro` :std:`core::arch::asm`. 42 | 43 | :dp:`fls_jb6krd90tjmc` 44 | An :t:`unsafe context` is either an :t:`unsafe block` or an 45 | :t:`unsafe function`. 46 | 47 | :dp:`fls_ybnpe7ppq1vh` 48 | An :t:`unsafe operation` shall be used only within an :t:`unsafe context`. 49 | 50 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | --- 5 | 6 | name: CI 7 | on: 8 | pull_request: 9 | merge_group: 10 | 11 | # Defined at the job level. 12 | permissions: {} 13 | 14 | jobs: 15 | build: 16 | name: Build the documentation 17 | runs-on: ubuntu-latest 18 | permissions: 19 | contents: read 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Setup uv 24 | uses: astral-sh/setup-uv@v6 25 | 26 | - name: Build documentation and check links 27 | run: ./make.py --check-links 28 | 29 | - name: Verify licensing metadata 30 | run: uvx reuse lint 31 | 32 | - name: Verify Python code formatting 33 | run: uvx black . --check --diff --color 34 | 35 | - name: Lint Python code with flake8 36 | run: uvx flake8 . --exclude .venv 37 | 38 | - name: Upload pages artifact 39 | uses: actions/upload-pages-artifact@v3 40 | with: 41 | path: build/html 42 | 43 | deploy: 44 | name: Deploy to GitHub Pages 45 | runs-on: ubuntu-latest 46 | needs: [ build ] 47 | if: github.event_name == 'merge_group' 48 | permissions: 49 | pages: write 50 | id-token: write 51 | environment: 52 | name: github-pages 53 | url: ${{ steps.deployment.outputs.page_url }} 54 | steps: 55 | - name: Deploy to GitHub Pages 56 | uses: actions/deploy-pages@v4 57 | id: deployment 58 | 59 | finished: 60 | name: CI finished 61 | runs-on: ubuntu-latest 62 | needs: [ build, deploy ] 63 | if: "${{ !cancelled() }}" 64 | env: 65 | NEEDS: "${{ toJson(needs) }}" 66 | steps: 67 | - name: Check if all jobs were successful or skipped 68 | run: echo "${NEEDS}" | jq --exit-status 'all(.result == "success" or .result == "skipped")' 69 | -------------------------------------------------------------------------------- /src/conf.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | # SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | # -- Path setup -------------------------------------------------------------- 6 | 7 | import os 8 | import sys 9 | 10 | sys.path.append(os.path.abspath("../exts")) 11 | 12 | 13 | # -- Project information ----------------------------------------------------- 14 | 15 | project = "FLS" 16 | copyright = "The Ferrocene Developers and The Rust Project Contributors" 17 | author = "The Ferrocene Developers and The Rust Project Contributors" 18 | 19 | 20 | # -- General configuration --------------------------------------------------- 21 | 22 | rst_prolog = ".. include:: ../version.rst" 23 | 24 | # Add any Sphinx extension module names here, as strings. They can be 25 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 26 | # ones. 27 | extensions = [ 28 | "ferrocene_spec", 29 | "ferrocene_spec_lints", 30 | "ferrocene_toctrees", 31 | ] 32 | 33 | # Add any paths that contain templates here, relative to this directory. 34 | templates_path = [] 35 | 36 | # List of patterns, relative to source directory, that match files and 37 | # directories to ignore when looking for source files. 38 | # This pattern also affects html_static_path and html_extra_path. 39 | exclude_patterns = [] 40 | 41 | # -- Options for HTML output ------------------------------------------------- 42 | 43 | # The theme to use for HTML and HTML Help pages. See the documentation for 44 | # a list of builtin themes. 45 | # 46 | 47 | html_theme = "fls" 48 | html_theme_path = ["../themes"] 49 | 50 | html_theme_options = { 51 | "license": "MIT or Apache 2.0", 52 | } 53 | 54 | html_title = "FLS" 55 | html_short_title = "FLS" 56 | 57 | # -- Options for linting ----------------------------------------------------- 58 | 59 | lint_alphabetical_section_titles = ["glossary"] 60 | 61 | lint_no_paragraph_ids = ["index", "changelog"] 62 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/sphinx_fixes.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | from sphinx.transforms import SphinxTransform, SortIds 6 | 7 | 8 | # Sphinx by default sorts all ids of the form `id[0-9]+` to the end. 9 | # Our IDs are section name and fls_ id pairs, so in some cases this transform 10 | # will instead sort the section name to the back, but not always! 11 | # So we overwrite the transform instead so that our fls ids are sorted to the back. 12 | # In addition to that we normalize them, as sphinx turns the `_` in `fls_{id}` 13 | # into `fls-{id}` which can break the link check from working correctly. 14 | class FerroceneSortIds(SphinxTransform): 15 | # Run this step after sphinx sorted. 16 | default_priority = SortIds.default_priority + 1 17 | 18 | def apply(self): 19 | for node in self.document.findall(nodes.section): 20 | for n, id in enumerate(node["ids"]): 21 | node["ids"][n] = normalize_fls_id(id) 22 | # sort the fls id to the back 23 | if len(node["ids"]) > 1 and node["ids"][0].startswith("fls_"): 24 | node["ids"] = node["ids"][1:] + [node["ids"][0]] 25 | 26 | 27 | class NormalizeFlsReferences(SphinxTransform): 28 | default_priority = 500 29 | 30 | def apply(self): 31 | for reference in self.document.findall(nodes.reference): 32 | if "internal" not in reference or not reference["internal"]: 33 | continue 34 | if "refuri" not in reference or "#" not in reference["refuri"]: 35 | continue 36 | path, hash = reference["refuri"].rsplit("#", 1) 37 | reference["refuri"] = f"{path}#{normalize_fls_id(hash)}" 38 | 39 | 40 | def normalize_fls_id(id): 41 | if id.startswith("fls-"): 42 | return id.replace("fls-", "fls_", 1) 43 | else: 44 | return id 45 | 46 | 47 | def setup(app): 48 | app.add_transform(FerroceneSortIds) 49 | app.add_post_transform(NormalizeFlsReferences) 50 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from . import definitions, informational, syntax_directive, std_role, paragraph_ids 5 | from . import items_with_rubric, sphinx_fixes 6 | from sphinx.domains import Domain 7 | 8 | 9 | class SpecDomain(Domain): 10 | name = "spec" 11 | label = "Specification" 12 | roles = { 13 | **definitions.get_roles(), 14 | "std": std_role.StdRefRole(), 15 | } 16 | directives = { 17 | "syntax": syntax_directive.SyntaxDirective, 18 | "informational-page": informational.build_directive("page"), 19 | "informational-section": informational.build_directive("section"), 20 | "items-with-rubric": items_with_rubric.ItemsWithRubricDirective, 21 | } 22 | object_types = definitions.get_object_types() 23 | indices = {} 24 | 25 | def get_objects(self): 26 | return definitions.get_objects(self.env) 27 | 28 | def merge_domaindata(self, docnames, other): 29 | def is_empty(data): 30 | return not data or list(data.keys()) == ["version"] 31 | 32 | if not is_empty(self.data) or not is_empty(other): 33 | raise NotImplementedError( 34 | "there is data in the domain, merge_domaindata should be implemented" 35 | ) 36 | 37 | 38 | def setup(app): 39 | app.add_domain(SpecDomain) 40 | definitions.setup(app) 41 | paragraph_ids.setup(app) 42 | informational.setup(app) 43 | items_with_rubric.setup(app) 44 | sphinx_fixes.setup(app) 45 | 46 | app.add_config_value( 47 | name="spec_std_docs_url", 48 | default="https://doc.rust-lang.org/stable/std", 49 | rebuild="env", # Rebuild the environment when this changes 50 | types=[str], 51 | ) 52 | 53 | return { 54 | "version": "0", 55 | "parallel_read_safe": True, 56 | "parallel_write_safe": True, 57 | # The version needs to be updated whenever there is a breaking change 58 | # in the data stored in the environment. Bumping the version number 59 | # will ensure Sphinx will do a clean build. 60 | # 61 | # Version history: 62 | # - 0: initial implementation 63 | # - 1: changed how informational sections and pages are stored 64 | "env_version": "1", 65 | } 66 | -------------------------------------------------------------------------------- /themes/fls/layout.html: -------------------------------------------------------------------------------- 1 | {# SPDX-License-Identifier: MIT OR Apache-2.0 #} 2 | {# SPDX-FileCopyrightText: The Ferrocene Developers #} 3 | {# SPDX-FileCopyrightText: The Rust Project Developers #} 4 | 5 | {% extends "basic/layout.html" %} 6 | {% from "fontawesome.html" import icon_search %} 7 | 8 | {% block extrahead %} 9 | {{ super() }} 10 | 11 | {% endblock %} 12 | 13 | {% block content %} 14 | {% if theme_include_in_header %} 15 | {% include theme_include_in_header %} 16 | {% endif %} 17 |
18 | 37 |
38 |
39 | {% block body %}{% endblock %} 40 |
41 |
42 |

43 | Copyright © {{ copyright }}. 44 | {% if theme_license %} 45 | Contents released under the {{ theme_license }} license. 46 | {% endif %} 47 |

48 | {% if document_id %} 49 |

Document ID: {{ document_id }}

50 | {% endif %} 51 | {% if theme_commit %} 52 |

Built from commit: {{ theme_commit }}

53 | {% endif %} 54 |
55 |
56 |
57 | {% endblock %} 58 | 59 | {# The blocks below, defined in the basic layout, are effectively removed from 60 | the template as we replace their contents with an empty string. #} 61 | {% block relbar1 %}{% endblock %} 62 | {% block relbar2 %}{% endblock %} 63 | {% block footer %}{% endblock %} 64 | -------------------------------------------------------------------------------- /src/exceptions-and-errors.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_dzq9cdz4ibsz: 7 | 8 | Exceptions and Errors 9 | ===================== 10 | 11 | .. rubric:: Legality Rules 12 | 13 | :dp:`fls_vsk4vhnuiyyz` 14 | The Rust programming language lacks exceptions and exception handlers. Instead, 15 | the language uses the following tiered error handling scheme: 16 | 17 | * :dp:`fls_ebangxc36t74` 18 | A possibly absent :t:`value` is usually represented using :t:`enum` 19 | :std:`core::option::Option`. 20 | 21 | * :dp:`fls_ckeitwiv326r` 22 | The result of a possibly erroneous computation is usually represented using 23 | :t:`enum` :std:`core::result::Result`. 24 | 25 | * :dp:`fls_eg0orgibg98m` 26 | Erroneous behavior is signaled using :t:`macro` :std:`core::panic`. 27 | 28 | :dp:`fls_ko1x0gp9e7y3` 29 | :t:`Enum` :std:`core::option::Option` indicates whether a :t:`value` is 30 | either present using :std:`core::option::Option::Some` or absent using 31 | :std:`core::option::Option::None`. 32 | 33 | :dp:`fls_gwu4cn4ziabe` 34 | :t:`Enum` :std:`core::result::Result` indicates whether a computation completed 35 | successfully and produced a :t:`value` using :std:`core::result::Result::Ok` or 36 | the computation failed with an error using :std:`core::result::Result::Err`. 37 | 38 | .. _fls_k02nt1m5fq1z: 39 | 40 | Panic 41 | ----- 42 | 43 | .. rubric:: Legality Rules 44 | 45 | :dp:`fls_a554v4n0khye` 46 | A :t:`panic` is an abnormal program state caused by invoking :t:`macro` 47 | :std:`core::panic`. 48 | 49 | .. rubric:: Dynamic Semantics 50 | 51 | :dp:`fls_i9njhpte5l0t` 52 | Invoking :t:`macro` :std:`core::panic` has the following runtime effects: 53 | 54 | #. :dp:`fls_n6q7bksyn1m` 55 | Control flow halts the execution of the current thread. 56 | 57 | #. :dp:`fls_xmtt04lw517w` 58 | Control flow of the current thread resumes execution by invoking the 59 | :t:`function` subject to :t:`attribute` :c:`panic_handler`. 60 | 61 | .. rubric:: Examples 62 | 63 | .. code-block:: rust 64 | 65 | panic!("This was a terrible mistake!"); 66 | 67 | .. _fls_hi1iz0gbnksi: 68 | 69 | Abort 70 | ----- 71 | 72 | .. rubric:: Legality Rules 73 | 74 | :dp:`fls_9a1izu3omkbn` 75 | :t:`Abort` is the immediate termination of a program. 76 | 77 | .. rubric:: Dynamic Semantics 78 | 79 | :dp:`fls_iq6olct3rw4u` 80 | :t:`Abort` has the following runtime effects: 81 | 82 | #. :dp:`fls_wd2q6ft9yzrg` 83 | Control flow halts the execution of all threads. 84 | 85 | #. :dp:`fls_7bnrbjb0pq5n` 86 | The program terminates. 87 | 88 | -------------------------------------------------------------------------------- /exts/ferrocene_spec_lints/require_paragraph_ids.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | from ferrocene_spec.definitions import DefIdNode 6 | 7 | 8 | def check(app, raise_error): 9 | for document in app.env.found_docs: 10 | doctree = app.env.get_doctree(document) 11 | if document in app.config.lint_no_paragraph_ids: 12 | check_does_not_have_ids(doctree, raise_error) 13 | else: 14 | check_has_ids(doctree, raise_error) 15 | 16 | 17 | def check_has_ids(node, raise_error): 18 | is_paragraph = nodes.paragraph is type(node) 19 | 20 | if is_paragraph and nodes.section is type(node.parent): 21 | should_have_id(node, "paragraph", raise_error) 22 | elif is_paragraph and nodes.list_item is type(node.parent): 23 | should_have_id(node, "list item", raise_error) 24 | elif is_paragraph and nodes.entry is type(node.parent): 25 | if node.parent.parent.index(node.parent) == 0: 26 | should_have_id(node, "first cell of a table row", raise_error) 27 | else: 28 | should_not_have_id( 29 | node, 30 | "second or later cell of a table row", 31 | raise_error, 32 | ) 33 | elif nodes.section is type(node): 34 | if not any(name.startswith("fls_") for name in node["names"]): 35 | raise_error("section should have an id", location=node) 36 | else: 37 | should_not_have_id(node, type(node).__name__, raise_error) 38 | 39 | for child in node.children: 40 | check_has_ids(child, raise_error) 41 | 42 | 43 | def check_does_not_have_ids(node, raise_error): 44 | if nodes.section is type(node): 45 | if any(name.startswith("fls_") for name in node["names"]): 46 | raise_error("section should not have an id", location=node) 47 | else: 48 | should_not_have_id(node, type(node).__name__, raise_error) 49 | 50 | for child in node.children: 51 | check_does_not_have_ids(child, raise_error) 52 | 53 | 54 | def should_have_id(node, what, raise_error): 55 | if any(is_definition(child) for child in node.children[1:]): 56 | raise_error(f"id in {what} is not the first element", location=node) 57 | elif not len(node.children) or not is_definition(node.children[0]): 58 | raise_error(f"{what} should have an id", location=node) 59 | 60 | 61 | def should_not_have_id(node, what, raise_error): 62 | if any(is_definition(child) for child in node.children): 63 | raise_error(f"{what} should not have an id", location=node) 64 | 65 | 66 | def is_definition(node): 67 | return ( 68 | DefIdNode is type(node) 69 | and node["def_kind"] == "paragraph" 70 | and node["def_id"].startswith("fls_") 71 | ) 72 | -------------------------------------------------------------------------------- /src/background.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Rust Project Contributors 3 | 4 | .. default-domain:: spec 5 | 6 | .. informational-page:: 7 | 8 | .. _fls_mLo6B3EWF50J: 9 | 10 | FLS Background 11 | ============== 12 | 13 | :dp:`fls_p7Jiyppmg0FU` The FLS is a document describing aspects of the Rust 14 | language for Rust toolchain qualification purposes. 15 | 16 | :dp:`fls_Uvf5tHsKSV19` It was created by Ferrous Systems, in an original joint 17 | effort with AdaCore, as one of the prerequisites for qualifying `Ferrocene`_, a 18 | Rust toolchain qualified for safety-critical environments. The FLS is compiled 19 | of existing Rust documentation, but presented with a rigorous structure in order 20 | to meet the requirements of qualification. 21 | 22 | :dp:`fls_J7ZI7mBXffzZ` The FLS is not intended to be used as *the* normative 23 | specification of the Rust language (see the `Rust Reference`_), nor is it meant 24 | to replace the decision-making processes of the Rust project. Any difference 25 | between the FLS and the behavior of the Rust compiler is considered an error on 26 | our part and the FLS will be updated accordingly. 27 | 28 | :dp:`fls_ffv8XSbBOMkR` The FLS text is licensed under either the ``MIT`` or 29 | ``Apache-2.0`` licenses, at your option. Individual files might have different 30 | licensing. Licensing metadata is present in each file, and the full licenses 31 | text is present in the ``LICENSES/`` directory. 32 | 33 | .. _Ferrocene: https://ferrocene.dev 34 | .. _Rust Reference: https://doc.rust-lang.org/reference/ 35 | 36 | .. _fls_UMsvnuLqzd99: 37 | 38 | Acknowledging Ferrous Systems 39 | ----------------------------- 40 | 41 | :dp:`fls_lmlLUAdtfCo5` The Rust Project would like to thank `Ferrous Systems`_ 42 | for `donating`_ the FLS (formerly the Ferrocene Language Specification) to the 43 | Rust Project for its continued maintenance and development. 44 | 45 | :dp:`fls_FZRrMT5AYsAQ` As a brief history, the FLS is a description of the Rust 46 | programming language, developed by Ferrous Systems and `AdaCore`_ in July 2022 47 | as part of Ferrocene, a Rust compiler and toolchain designed for safety-critical 48 | and regulated industries. The FLS provides a structured and detailed reference 49 | for Rust's syntax, semantics, and behavior, serving as a foundation for 50 | verification, compliance, and standardization efforts. The FLS represented a 51 | major step toward describing Rust in a way that aligns with industry 52 | requirements, particularly in high-assurance domains. Until its transfer in 53 | April 2025, Ferrous Systems had been the sole steward of the FLS since July 54 | 2023. 55 | 56 | .. _Ferrous Systems: https://ferrous-systems.com 57 | .. _donating: https://rustfoundation.org/media/ferrous-systems-donates-ferrocene-language-specification-to-rust-project/ 58 | .. _AdaCore: https://www.adacore.com -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/change.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Rust Project Developers 3 | 4 | name: Change 5 | description: File a change for the FLS 6 | title: "[Change]: " 7 | labels: ["change intake"] 8 | assignees: 9 | - PLeVasseur 10 | body: 11 | - type: markdown 12 | attributes: 13 | value: | 14 | Thank you for contributing a change! 15 | - type: input 16 | id: title 17 | attributes: 18 | label: Change description 19 | description: Description of what is intended to be changed 20 | placeholder: Fix description of lexing due to xx 21 | validations: 22 | required: true 23 | - type: dropdown 24 | id: area 25 | attributes: 26 | label: Area 27 | description: Which part of the language does this fall under? 28 | options: 29 | - ABI 30 | - async / await 31 | - attributes 32 | - closures 33 | - conditional compilation 34 | - const evaluation 35 | - conventions 36 | - destructors 37 | - diagnostics 38 | - "edition: 2015" 39 | - "edition: 2018" 40 | - "edition: 2021" 41 | - "edition: 2024" 42 | - editions 43 | - generics 44 | - glossary 45 | - grammar 46 | - inline assembly 47 | - linkage 48 | - macros 49 | - method call 50 | - panic 51 | - patterns 52 | - proc macros 53 | - resolution (names, paths, namespaces, preludes, ...) 54 | - types 55 | - type inference 56 | - type layout 57 | - undefined behavior 58 | - N/A 59 | validations: 60 | required: true 61 | - type: dropdown 62 | id: category 63 | attributes: 64 | label: Category 65 | description: What kind of change is this? 66 | options: 67 | - Bug 68 | - Formatting 69 | - Improvement to non-prose section 70 | - Language cleanup 71 | - New content 72 | - Other 73 | validations: 74 | required: true 75 | - type: input 76 | id: fls-id 77 | attributes: 78 | label: FLS Paragraph ID 79 | description: | 80 | The Paragraph ID from the FLS corresponding to what this Guideline covers. 81 | Easiest way to obtain this is to navigate to the 82 | [FLS](https://rust-lang.github.io/fls), right click a section ID 83 | (e.g. `4.2:2`), inspect, and then find it in the pane which opens in 84 | your browser. 85 | 86 | **Note**: New content need not fill this in. 87 | placeholder: fls_deaddeadbeef 88 | validations: 89 | required: false 90 | - type: textarea 91 | id: change-description 92 | attributes: 93 | label: Change description (extended) 94 | description: | 95 | A longer description of the intended change, including background and 96 | details on in what way the FLS is improved by the change. 97 | placeholder: Fix description of lexing due to xx, since under conditions yy it's possible for zz to occur. 98 | validations: 99 | required: true 100 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/definitions/paragraphs.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from .. import utils 5 | from collections import defaultdict 6 | from docutils import nodes 7 | import hashlib 8 | import sphinx 9 | 10 | 11 | ROLE = "p" 12 | NAME = "paragraph" 13 | PRETTY_NAME = "paragraph" 14 | 15 | 16 | class Paragraph: 17 | def __init__(self, id, document, section_anchor, section_id, plaintext, sequential): 18 | self.id = id 19 | self.document = document 20 | self.section_anchor = section_anchor 21 | self.section_id = section_id 22 | self.plaintext = plaintext 23 | self.sequential = sequential 24 | 25 | def number(self, env): 26 | section = ".".join( 27 | str(n) for n in env.toc_secnumbers[self.document][self.section_anchor] 28 | ) 29 | return f"{section}:{self.sequential}" 30 | 31 | def anchor(self): 32 | return self.id 33 | 34 | def include_in_search(self): 35 | return False 36 | 37 | def display_name(self, env): 38 | return f"{self.number(env)} {self.content_checksum()}" 39 | 40 | def content_checksum(self): 41 | sha256 = hashlib.sha256() 42 | sha256.update(self.plaintext.encode("utf-8")) 43 | return sha256.hexdigest() 44 | 45 | 46 | def collect_items_in_document(app, nodes_to_collect): 47 | ids = defaultdict(lambda: 1) 48 | for node in nodes_to_collect: 49 | section_node = find_parent_of_type(node, nodes.section) 50 | if section_node is None: 51 | raise RuntimeError(f"could not find section for {node!r}") 52 | 53 | try: 54 | section_id, section_anchor = utils.section_id_and_anchor(section_node) 55 | except utils.NoSectionIdError: 56 | logger = sphinx.util.logging.getLogger(__name__) 57 | logger.warn( 58 | "paragraph inside a section that doesn't have an id starting with fls_", 59 | location=node, 60 | ) 61 | return 62 | 63 | yield Paragraph( 64 | id=node["def_id"], 65 | document=app.env.docname, 66 | section_anchor=section_anchor, 67 | section_id=section_id, 68 | plaintext=plaintext_paragraph(node), 69 | sequential=ids[section_id], 70 | ) 71 | ids[section_id] += 1 72 | 73 | 74 | def replace_id_node(app, node, paragraph): 75 | new = nodes.inline() 76 | new["ids"].append(paragraph.id) 77 | new["classes"].append("spec-paragraph-id") 78 | new += nodes.Text(paragraph.number(app.env)) 79 | node.replace_self(new) 80 | 81 | 82 | def create_ref_node(env, text, item): 83 | if item is not None: 84 | return nodes.emphasis("", item.number(env)) 85 | else: 86 | return nodes.emphasis("", "Paragraph " + text) 87 | 88 | 89 | def plaintext_paragraph(node): 90 | paragraph = find_parent_of_type(node, nodes.paragraph) 91 | if paragraph is None: 92 | paragraph = node 93 | return paragraph.astext().replace("\n", " ") 94 | 95 | 96 | def find_parent_of_type(node, ty): 97 | cursor = node 98 | while cursor is not None: 99 | if isinstance(cursor, ty): 100 | return cursor 101 | cursor = cursor.parent 102 | return None 103 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | ==================================================== 6 | Contributing to the FLS 7 | ==================================================== 8 | 9 | The FLS is released publicly under an open source license, specifically MIT and 10 | Apache 2.0. 11 | 12 | The specification is still a work in progress, and while we're open to 13 | contributions, we want to manage your expectations on how much we'll be able to 14 | interact with the community in this repository: 15 | 16 | * Any change made to the specification text causes extra work for us behind the 17 | scenes, as we have other tooling required for qualification that consumes the 18 | specification text. 19 | 20 | * Our resources are limited when it comes to reviewing PRs, especially large 21 | ones. 22 | 23 | We'll try our best to review changes proposed by the community, but we might not 24 | be able to review all of them (or they might be out of date once we get to 25 | them). If there are changes you'd like to make, we recommend opening an issue 26 | beforehand, so that we can provide feedback on whether we'll be able to merge 27 | the changes. 28 | 29 | We've all dealt with those open source projects that feel open in name only, and 30 | have big patches and history-free source drops appearing from behind the walls 31 | of some large organization. We don't like that, and we're not going to do that. 32 | But please bear with us until we have the capacity to accept all external 33 | contributions. 34 | 35 | This introduction was inspired by Oxide Computer Company's `Hubris 36 | contribution guidelines 37 | `_. 38 | 39 | Contribution Process 40 | ==================== 41 | 42 | Before contributing, it would be helpful to familiarize yourself with the 43 | grammar and structure of the FLS. You'll find everything you need to in `Chapter 44 | 1: General `_ of the specification. 45 | 46 | There are three kinds of contribution that can be made: 47 | 48 | * **Flags:** Here the contributor makes the Ferrocene team aware of changes that 49 | were made upstream, but leaves the changes up to the Ferrocene team. This 50 | helps Ferrocene with our mission to "keep the moving parts safe" and ensures 51 | that we can respond to upstream changes in a timely manner. Please `open an 52 | issue `_ for this. 53 | 54 | * **Fixes:** These are defined as small errors or suggestions for improvements 55 | within one or two sentences. The structure of the content still makes sense, 56 | but the contribution makes the concept more precise or better defined. To 57 | contribute a fix to the FLS, please open a pull request! 58 | 59 | * **Rewrites:** These are bigger changes in which a contributor rewrites an 60 | entire chapter, section or subsection. Please open an issue to discuss the 61 | rewrite you want to make, and if we have the capacity to accept and review it 62 | we'll coordinate on how to best do it. 63 | 64 | PRs and approval 65 | ================ 66 | 67 | Whether the changes appear in the FLS will remain the responsibility and 68 | discretion of the Ferrocene team. Changes may be approved as is or may be edited 69 | to match the tone, style and format of the FLS. 70 | 71 | Again, we thank you for your patience as we address the suggested changes and, 72 | last but not least, thank you for your interest and contributions to the FLS! 73 | -------------------------------------------------------------------------------- /themes/fls/static/rust-lang.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 63 | 64 | -------------------------------------------------------------------------------- /themes/fls/static/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 66 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/informational.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from . import utils 5 | from collections import defaultdict 6 | from docutils import nodes 7 | from sphinx import addnodes 8 | from sphinx.directives import SphinxDirective 9 | from sphinx.environment.collectors import EnvironmentCollector 10 | from sphinx.transforms import SphinxTransform 11 | import sphinx 12 | 13 | 14 | # Marker to use inside the informational storage to signal the whole page, and 15 | # not just a section, is informational 16 | WHOLE_PAGE = "{{{whole-page}}}" 17 | 18 | 19 | def build_directive(kind): 20 | class InformationalDirective(SphinxDirective): 21 | has_content = False 22 | 23 | def run(self): 24 | paragraph = nodes.paragraph() 25 | paragraph += nodes.Text(f"The contents of this {kind} are informational.") 26 | 27 | note = nodes.note() 28 | note += paragraph 29 | 30 | return [note, InformationalMarkerNode(kind)] 31 | 32 | return InformationalDirective 33 | 34 | 35 | class InformationalMarkerNode(nodes.Element): 36 | def __init__(self, kind): 37 | super().__init__() 38 | self["kind"] = kind 39 | 40 | 41 | class InformationalPagesCollector(EnvironmentCollector): 42 | def clear_doc(self, app, env, docname): 43 | storage = get_storage(env) 44 | if docname in storage: 45 | del storage[docname] 46 | 47 | def merge_other(self, app, env, docnames, other): 48 | storage = get_storage(env) 49 | for document, contents in get_storage(other).items(): 50 | storage[document] = storage[document].union(contents) 51 | 52 | def process_doc(self, app, document): 53 | storage = get_storage(app.env) 54 | for node in document.findall(InformationalMarkerNode): 55 | if node["kind"] == "page": 56 | self.process_page(app, storage, node) 57 | elif node["kind"] == "section": 58 | self.process_section(app, storage, node) 59 | else: 60 | raise RuntimeError("unknown directive kind: " + node["kind"]) 61 | 62 | def process_page(self, app, storage, node): 63 | if addnodes.document is not type(node.parent): 64 | warn("informational-page must be at the top of the document", node) 65 | return 66 | 67 | storage[app.env.docname].add(WHOLE_PAGE) 68 | 69 | def process_section(self, app, storage, node): 70 | if nodes.section is not type(node.parent): 71 | warn("informational-section must be inside a section", node) 72 | return 73 | 74 | try: 75 | _id, anchor = utils.section_id_and_anchor(node.parent) 76 | except utils.NoSectionIdError: 77 | warn( 78 | "informational-section must be inside a section with an ID " 79 | "starting with fls_" 80 | ) 81 | return 82 | storage[app.env.docname].add(anchor) 83 | 84 | 85 | class RemoveInformationalMarkerNodesTransform(SphinxTransform): 86 | default_priority = 500 87 | 88 | def apply(self): 89 | for node in self.document.findall(InformationalMarkerNode): 90 | node.parent.remove(node) 91 | 92 | 93 | def is_document_informational(env, docname): 94 | return WHOLE_PAGE in get_storage(env)[docname] 95 | 96 | 97 | def is_section_informational(env, docname, anchor): 98 | return anchor in get_storage(env)[docname] 99 | 100 | 101 | def get_storage(env): 102 | key = "spec_informational" 103 | if not hasattr(env, key): 104 | setattr(env, key, defaultdict(set)) 105 | return getattr(env, key) 106 | 107 | 108 | def warn(message, location): 109 | logger = sphinx.util.logging.getLogger(__name__) 110 | logger.warning(message, location=location) 111 | 112 | 113 | def setup(app): 114 | app.add_node(InformationalMarkerNode) 115 | app.add_env_collector(InformationalPagesCollector) 116 | app.add_post_transform(RemoveInformationalMarkerNodesTransform) 117 | -------------------------------------------------------------------------------- /LICENSES/OFL-1.1.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025, The Raleway Project Authors (impallari@gmail.com), 2 | with Reserved Font Name Raleway. 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | 6 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 7 | 8 | SIL OPEN FONT LICENSE 9 | 10 | Version 1.1 - 26 February 2007 11 | 12 | PREAMBLE 13 | 14 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. 15 | 16 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. 17 | 18 | DEFINITIONS 19 | 20 | "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. 21 | 22 | "Reserved Font Name" refers to any names specified as such after the copyright statement(s). 23 | 24 | "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). 25 | 26 | "Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. 27 | 28 | "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. 29 | 30 | PERMISSION & CONDITIONS 31 | 32 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 33 | 34 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 35 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 36 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 37 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 38 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 39 | TERMINATION 40 | 41 | This license becomes null and void if any of the above conditions are not met. 42 | 43 | DISCLAIMER 44 | 45 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | === 6 | FLS 7 | === 8 | 9 | .. raw:: html 10 | 11 |

Read the document 12 | »

13 | 14 | The FLS is a document describing aspects of the Rust language for Rust toolchain 15 | qualification purposes. 16 | 17 | It was created by Ferrous Systems, in an original joint effort with AdaCore, as 18 | one of the prerequisites for qualifying `Ferrocene`_, a Rust toolchain qualified 19 | for safety-critical environments. The FLS is compiled of existing Rust 20 | documentation, but presented with a rigorous structure in order to meet the 21 | requirements of qualification. 22 | 23 | The FLS is not intended to be used as *the* normative specification of the Rust 24 | language (see the `Rust Reference`_), nor is it meant to replace the 25 | decision-making processes of the Rust project. Any difference between the FLS 26 | and the behavior of the Rust compiler is considered an error on our part and the 27 | FLS will be updated accordingly. 28 | 29 | The FLS text is licensed under either the ``MIT`` or ``Apache-2.0`` licenses, at 30 | your option. Individual files might have different licensing. Licensing metadata 31 | is present in each file, and the full licenses text is present in the 32 | ``LICENSES/`` directory. 33 | 34 | .. _Ferrocene: https://ferrocene.dev 35 | .. _Rust Reference: https://doc.rust-lang.org/reference/ 36 | 37 | Acknowledging Ferrous Systems 38 | ============================= 39 | 40 | The Rust Project would like to thank `Ferrous Systems`_ for `donating`_ the FLS 41 | (formerly the Ferrocene Language Specification) to the Rust Project for its 42 | continued maintenance and development. 43 | 44 | As a brief history, the FLS is a description of the Rust programming language, 45 | developed by Ferrous Systems and `AdaCore`_ in July 2022 as part of Ferrocene, a 46 | Rust compiler and toolchain designed for safety-critical and regulated 47 | industries. The FLS provides a structured and detailed reference for Rust's 48 | syntax, semantics, and behavior, serving as a foundation for verification, 49 | compliance, and standardization efforts. The FLS represented a major step toward 50 | describing Rust in a way that aligns with industry requirements, particularly in 51 | high-assurance domains. Until its transfer in April 2025, Ferrous Systems had 52 | been the sole steward of the FLS since July 2023. 53 | 54 | .. _Ferrous Systems: https://ferrous-systems.com 55 | .. _donating: https://rustfoundation.org/media/ferrous-systems-donates-ferrocene-language-specification-to-rust-project/ 56 | .. _AdaCore: https://www.adacore.com 57 | 58 | Building the specification 59 | ========================== 60 | 61 | FLS uses `Sphinx`_ to build a rendered version of the specification, and `uv`_ 62 | to install and manage Python dependencies (including Sphinx itself). To simplify 63 | building the rendered version, we created a script called ``make.py`` that takes 64 | care of invoking Sphinx with the right flags. 65 | 66 | You can build the rendered version by running:: 67 | 68 | ./make.py 69 | 70 | By default, Sphinx uses incremental rebuilds to generate the content that 71 | changed since the last invocation. If you notice a problem with incremental 72 | rebuilds, you can pass the ``-c`` flag to clear the existing artifacts before 73 | building:: 74 | 75 | ./make.py -c 76 | 77 | The rendered version will be available in ``build/html/``. 78 | 79 | You can also start a local server on port 8000 with automatic rebuild and reload 80 | whenever you change a file by passing the ``-s`` flag:: 81 | 82 | ./make.py -s 83 | 84 | Checking links consistency 85 | ========================== 86 | 87 | It's possible to run Rust's linkchecker tool on the rendered documentation, to 88 | see if there are broken links. To do so, pass the ``--check-links`` flag:: 89 | 90 | ./make.py --check-links 91 | 92 | This will clone the source code of the tool, build it, and execute it on the 93 | rendered documentation. 94 | 95 | .. _Sphinx: https://www.sphinx-doc.org 96 | .. _uv: https://docs.astral.sh/uv/ 97 | 98 | Updating build dependencies 99 | =========================== 100 | 101 | The FLS uses ``uv`` to manage the Python dependencies used for builds. If you 102 | change the list of dependencies in ``pyproject.toml`` they will automatically be 103 | installed the next time you run ``make.py``. If you want to update the packages 104 | in the lockfile, run:: 105 | 106 | uv lock --upgrade 107 | -------------------------------------------------------------------------------- /src/concurrency.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_3v733mnewssy: 7 | 8 | Concurrency 9 | =========== 10 | 11 | :dp:`fls_opt7v0mopxc8` 12 | The Rust programming language provides features for concurrent programming 13 | without :t:`[data race]s`, whose rules are presented in this chapter. 14 | 15 | .. rubric:: Legality Rules 16 | 17 | :dp:`fls_tx4b8r6i93n4` 18 | A :t:`data race` is a scenario where two or more threads access a shared memory 19 | location concurrently without any synchronization, where one of the accesses is 20 | a modification. 21 | 22 | .. rubric:: Undefined Behavior 23 | 24 | :dp:`fls_isypweqewe78` 25 | It is undefined behavior if two or more threads engage in a :t:`data race`. 26 | 27 | .. _fls_eiw4by8z75di: 28 | 29 | Send and Sync 30 | ------------- 31 | 32 | .. rubric:: Legality Rules 33 | 34 | :dp:`fls_n5l17mlglq11` 35 | The Rust programming language provides the :std:`core::marker::Send` and 36 | :std:`core::marker::Sync` :t:`[trait]s` for preventing data races at the 37 | :t:`type` level. 38 | 39 | :dp:`fls_2jujsujpjp3w` 40 | A :t:`send type` is a :t:`type` that implements the :std:`core::marker::Send` 41 | :t:`trait`. 42 | 43 | :dp:`fls_cax6fe4em23k` 44 | An :t:`abstract data type` automatically implements the 45 | :std:`core::marker::Send` :t:`trait` if the :t:`[type]s` of all its 46 | :t:`[field]s` are :t:`[send type]s`. 47 | 48 | :dp:`fls_4ypqdehn7b0v` 49 | A :t:`send type` shall have :t:`[value]s` that are safe to transfer across 50 | thread boundaries. 51 | 52 | :dp:`fls_dekskhk4g895` 53 | A :t:`sync type` is a :t:`type` that implements the :std:`core::marker::Sync` 54 | :t:`trait`. 55 | 56 | :dp:`fls_y0iqr5ibnbfe` 57 | An :t:`abstract data type` automatically implements the 58 | :std:`core::marker::Sync` :t:`trait` if the :t:`[type]s` of all its 59 | :t:`[field]s` are :t:`[sync type]s`. 60 | 61 | :dp:`fls_zgemofbs5q2x` 62 | A :t:`sync type` shall have :t:`[value]s` that are allowed to be shared across 63 | multiple threads at any given time without incurring data races. 64 | 65 | .. _fls_vyc9vcuamlph: 66 | 67 | Atomics 68 | ------- 69 | 70 | .. rubric:: Legality Rules 71 | 72 | :dp:`fls_3pjla9s93mhd` 73 | An :t:`atomic type` is a :t:`type` defined in :t:`module` 74 | :std:`core::sync::atomic`. :t:`[Atomic type]s` provide primitive shared-memory 75 | communication between threads. 76 | 77 | :dp:`fls_wn4ynaio8u47` 78 | :t:`[Atomic type]s` are related to :t:`[type]s` as follows: 79 | 80 | .. list-table:: 81 | 82 | * - :dp:`fls_q7mn6pdd8bix` 83 | - **Type** 84 | - **Atomic Type** 85 | * - :dp:`fls_jx0784jzxy00` 86 | - :c:`bool` 87 | - :std:`core::sync::atomic::AtomicBool` 88 | * - :dp:`fls_vzuwnpx7mt08` 89 | - :c:`i8` 90 | - :std:`core::sync::atomic::AtomicI8` 91 | * - :dp:`fls_cpcd0vexfbhj` 92 | - :c:`i16` 93 | - :std:`core::sync::atomic::AtomicI16` 94 | * - :dp:`fls_jt7rfq9atbiv` 95 | - :c:`i32` 96 | - :std:`core::sync::atomic::AtomicI32` 97 | * - :dp:`fls_2hqmfwswc6k` 98 | - :c:`i64` 99 | - :std:`core::sync::atomic::AtomicI64` 100 | * - :dp:`fls_5ab2sw3gwmt3` 101 | - :c:`isize` 102 | - :std:`core::sync::atomic::AtomicIsize` 103 | * - :dp:`fls_w2mw833g28eb` 104 | - ``*mut T`` 105 | - :std:`core::sync::atomic::AtomicPtr` 106 | * - :dp:`fls_mjq1l1y0vmz4` 107 | - :c:`u8` 108 | - :std:`core::sync::atomic::AtomicU8` 109 | * - :dp:`fls_906978wtss6n` 110 | - :c:`u16` 111 | - :std:`core::sync::atomic::AtomicU16` 112 | * - :dp:`fls_4urmnh4mfehl` 113 | - :c:`u32` 114 | - :std:`core::sync::atomic::AtomicU32` 115 | * - :dp:`fls_2qkrcd5eovpe` 116 | - :c:`u64` 117 | - :std:`core::sync::atomic::AtomicU64` 118 | * - :dp:`fls_cry1e78gp19q` 119 | - :c:`usize` 120 | - :std:`core::sync::atomic::AtomicUsize` 121 | 122 | .. _fls_mtuwzinpfvkl: 123 | 124 | Asynchronous Computation 125 | ------------------------ 126 | 127 | .. rubric:: Legality Rules 128 | 129 | :dp:`fls_g40xp4andj5g` 130 | The Rust programming language provides asynchronous computation through 131 | :t:`module` :std:`core::task` and the :std:`core::future::Future` :t:`trait`. 132 | 133 | :dp:`fls_fte085hi1yqj` 134 | A :t:`future` represents a :t:`value` of a :t:`type` that implements the 135 | :std:`core::future::Future` :t:`trait` which may not have finished computing 136 | yet. 137 | 138 | :dp:`fls_7muubin2wn1v` 139 | The computed :t:`value` of a :t:`future` is obtained by using an 140 | :t:`await expression` or by invoking :std:`core::future::Future::poll`. 141 | 142 | :dp:`fls_ftzey2156ha` 143 | :std:`core::future::Future::poll` shall not be invoked on a :t:`future` that has 144 | already returned :std:`core::task::Poll::Ready`. 145 | 146 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/paragraph_ids.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from . import definitions, informational, utils 5 | from collections import defaultdict 6 | from docutils import nodes 7 | from sphinx.environment.collectors import EnvironmentCollector 8 | import json 9 | import os 10 | import sphinx 11 | 12 | 13 | def write_paragraph_ids(app): 14 | env = app.env 15 | informational_storage = informational.get_storage(env) 16 | 17 | paragraphs_by_section = defaultdict(list) 18 | for paragraph in definitions.get_storage(env, definitions.paragraphs).values(): 19 | paragraphs_by_section[paragraph.section_id].append( 20 | { 21 | "id": paragraph.id, 22 | "number": paragraph.number(app.env), 23 | "link": app.builder.get_target_uri(paragraph.document) 24 | + "#" 25 | + paragraph.id, 26 | "checksum": paragraph.content_checksum(), 27 | } 28 | ) 29 | 30 | sections_by_document = defaultdict(list) 31 | for section in env.spec_sections: 32 | sections_by_document[section.document].append( 33 | { 34 | "id": section.id, 35 | "number": ".".join( 36 | str(n) for n in env.toc_secnumbers[section.document][section.anchor] 37 | ), 38 | "title": section.title, 39 | "link": app.builder.get_target_uri(section.document) + section.anchor, 40 | "paragraphs": paragraphs_by_section[section.id], 41 | "informational": ( 42 | section.anchor in informational_storage[section.document] 43 | ), 44 | } 45 | ) 46 | 47 | documents = [] 48 | for docname, title in env.titles.items(): 49 | documents.append( 50 | { 51 | "title": title.astext(), 52 | "link": app.builder.get_target_uri(docname), 53 | "sections": sections_by_document[docname], 54 | "informational": ( 55 | informational.WHOLE_PAGE in informational_storage[docname] 56 | ), 57 | } 58 | ) 59 | 60 | with open(os.path.join(app.outdir, "paragraph-ids.json"), "w") as f: 61 | json.dump({"documents": documents}, f) 62 | f.write("\n") 63 | 64 | 65 | def build_finished(app, exception): 66 | # The build finished hook also runs when an exception is raised. 67 | if exception is not None: 68 | return 69 | 70 | with sphinx.util.display.progress_message("dumping paragraph ids"): 71 | write_paragraph_ids(app) 72 | 73 | 74 | def setup(app): 75 | app.connect("build-finished", build_finished) 76 | app.add_env_collector(SectionsCollector) 77 | 78 | 79 | class SectionsCollector(EnvironmentCollector): 80 | def clear_doc(self, app, env, docname): 81 | """ 82 | This is called by Sphinx during incremental builds, either when a 83 | document was removed or when the document has been changed. In the 84 | latter case, process_doc is called after this method. 85 | """ 86 | if not hasattr(env, "spec_sections"): 87 | env.spec_sections = [] 88 | env.spec_sections = [s for s in env.spec_sections if s.document != docname] 89 | 90 | def merge_other(self, app, env, docnames, other): 91 | """ 92 | Sphinx supports parallel builds, with each process having its own 93 | environment instance, but once each document is processed those 94 | parallel environments need to be merged together. This method does it. 95 | """ 96 | if not hasattr(env, "spec_sections"): 97 | env.spec_sections = [] 98 | if not hasattr(other, "spec_sections"): 99 | return 100 | 101 | for section in other.spec_sections: 102 | if section.document not in docnames: 103 | continue 104 | env.spec_sections.append(section) 105 | 106 | def process_doc(self, app, doctree): 107 | """ 108 | This method can expect no existing information about the same document 109 | being stored in the environment, as during incremental rebuilds the 110 | clear_doc method is called ahead of this one. 111 | """ 112 | env = app.env 113 | if not hasattr(env, "spec_sections"): 114 | env.spec_sections = [] 115 | 116 | for section in doctree.findall(nodes.section): 117 | try: 118 | id, anchor = utils.section_id_and_anchor(section) 119 | except utils.NoSectionIdError: 120 | continue 121 | 122 | title = None 123 | for child in section.children: 124 | if isinstance(child, nodes.title): 125 | title = child.astext() 126 | if title is None: 127 | raise RuntimeError(f"section without title: {section}") 128 | 129 | env.spec_sections.append( 130 | Section(id=id, title=title, anchor=anchor, document=env.docname) 131 | ) 132 | 133 | 134 | class Section: 135 | def __init__(self, id, title, anchor, document): 136 | self.id = id 137 | self.title = title 138 | self.anchor = anchor 139 | self.document = document 140 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/items_with_rubric.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from collections import defaultdict 5 | from dataclasses import dataclass 6 | from docutils import nodes 7 | from sphinx.directives import SphinxDirective 8 | from sphinx.environment.collectors import EnvironmentCollector 9 | from .informational import is_document_informational, is_section_informational 10 | from sphinx.transforms import SphinxTransform 11 | import sphinx 12 | 13 | 14 | class ItemsWithRubricMarkerNode(nodes.Element): 15 | def __init__(self, rubric, location): 16 | super().__init__() 17 | self["rubric"] = rubric 18 | 19 | # Make the node's source location be the same as the directive, so that 20 | # later transforms can retrieve the location for error reporting. 21 | self.source = location[0] 22 | self.line = location[1] 23 | 24 | 25 | class ItemsWithRubricDirective(SphinxDirective): 26 | has_content = True 27 | 28 | def run(self): 29 | if len(self.content) != 1: 30 | warn( 31 | "items-with-rubric accepts only the name of the rubric", 32 | self.get_location(), 33 | ) 34 | return [] 35 | 36 | return [ItemsWithRubricMarkerNode(self.content[0], self.get_source_info())] 37 | 38 | 39 | class RubricCollector(EnvironmentCollector): 40 | def clear_doc(self, app, env, docname): 41 | storage = get_storage(env) 42 | for rubric, items in storage.items(): 43 | items[:] = (item for item in items if item.document != docname) 44 | 45 | def merge_other(self, app, env, docnames, other): 46 | current = get_storage(env) 47 | other = get_storage(other) 48 | for rubric, items in other.items(): 49 | for item in items: 50 | if item.document in docnames: 51 | current[rubric].append(item) 52 | 53 | def process_doc(self, app, document): 54 | for rubric in document.findall(nodes.rubric): 55 | self.process_rubric(app, document, rubric) 56 | 57 | def process_rubric(self, app, document, rubric): 58 | rubric_name = rubric.astext() 59 | 60 | if not isinstance(rubric.parent, nodes.section): 61 | warn("rubric is not directly inside a section", rubric) 62 | return 63 | 64 | title_node = next(rubric.parent.findall(nodes.title)) 65 | if title_node is None: 66 | warn( 67 | "section containing this rubric doesn't have a title", 68 | rubric, 69 | ) 70 | return 71 | section_title = title_node.astext() 72 | 73 | section_id = rubric.parent["ids"][-1] 74 | get_storage(app.env)[rubric_name].append( 75 | StoredRubric( 76 | document=app.env.docname, 77 | section_id=section_id, 78 | section_title=section_title, 79 | ) 80 | ) 81 | 82 | 83 | class InjectContentTransform(SphinxTransform): 84 | default_priority = 500 85 | 86 | def apply(self): 87 | for node in self.document.findall(ItemsWithRubricMarkerNode): 88 | self.replace_node(node) 89 | 90 | def replace_node(self, node): 91 | items = get_storage(self.env)[node["rubric"]] 92 | if not items: 93 | warn(f"no items with rubric {node['rubric']}", node) 94 | node.parent.remove(node) 95 | return 96 | 97 | # Ensure the items are in a sorted order to guarantee reproducibility. 98 | items.sort(key=lambda item: (item.section_title, item.section_id)) 99 | 100 | bullet_list = nodes.bullet_list() 101 | for item in items: 102 | if is_document_informational(self.env, item.document): 103 | continue 104 | if is_section_informational(self.env, item.document, f"#{item.section_id}"): 105 | continue 106 | 107 | paragraph = nodes.paragraph() 108 | paragraph += sphinx.util.nodes.make_refnode( 109 | self.app.builder, 110 | self.env.docname, 111 | item.document, 112 | item.section_id, 113 | nodes.Text(item.section_title), 114 | ) 115 | paragraph += nodes.Text(" (in ") 116 | paragraph += sphinx.util.nodes.make_refnode( 117 | self.app.builder, 118 | self.env.docname, 119 | item.document, 120 | "", 121 | nodes.Text(self.env.titles[item.document].astext()), 122 | ) 123 | paragraph += nodes.Text(")") 124 | 125 | list_item = nodes.list_item() 126 | list_item += paragraph 127 | 128 | bullet_list += list_item 129 | 130 | node.replace_self(bullet_list) 131 | 132 | 133 | def get_storage(env): 134 | key = "spec_rubrics" 135 | if not hasattr(env, key): 136 | setattr(env, key, defaultdict(list)) 137 | return getattr(env, key) 138 | 139 | 140 | @dataclass 141 | class StoredRubric: 142 | document: str 143 | section_id: str 144 | section_title: str 145 | 146 | 147 | def warn(message, location): 148 | logger = sphinx.util.logging.getLogger(__name__) 149 | logger.warning(message, location=location) 150 | 151 | 152 | def setup(app): 153 | app.add_env_collector(RubricCollector) 154 | app.add_node(ItemsWithRubricMarkerNode) 155 | app.add_post_transform(InjectContentTransform) 156 | -------------------------------------------------------------------------------- /exts/ferrocene_toctrees.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from docutils import nodes 5 | from sphinx import addnodes as sphinxnodes 6 | from sphinx.directives.other import TocTree 7 | from sphinx.environment.collectors.toctree import TocTreeCollector 8 | import gc 9 | 10 | 11 | class AppendicesDirective(TocTree): 12 | def run(self): 13 | result = super().run() 14 | 15 | def compat_check(condition): 16 | if not condition: 17 | raise RuntimeError( 18 | "bug: the toctree Sphinx directive used by appendix emitted " 19 | "unexpected nodes, please update the extension to handle that" 20 | ) 21 | 22 | # We're modifying the result of Sphinx's builtin TocTree directive, so 23 | # ensure it contains what we expect. 24 | compat_check(isinstance(result, list)) 25 | compat_check(len(result) == 1) 26 | compat_check(isinstance(result[0], nodes.compound)) 27 | compat_check(len(result[0].children) == 1) 28 | compat_check(isinstance(result[0].children[0], sphinxnodes.toctree)) 29 | 30 | # Mark this toctree as containing appendices, so that the environment 31 | # collector can distinguish it from normal toctrees. 32 | result[0].children[0]["are_appendices"] = True 33 | 34 | return result 35 | 36 | 37 | # To ensure the minimum disruption possible, to update section numbers we're 38 | # replacing the EnvironmentCollector responsible for assigning section numbers. 39 | # 40 | # We let the builtin Sphinx logic assign section numbers, and as soon as it 41 | # finishes we go over the sections and replace the first number of appendices 42 | # with a letter, and we offset everything based on the previous toctrees (to 43 | # support multiple toctrees in a site). 44 | # 45 | # Doing this as part of TocTreeCollector ensures the rest of the build always 46 | # sees the correct ID for sections, as no Sphinx code runs between the upstream 47 | # number assigning and us modifying them. 48 | class TocTreeCollectorWithAppendices(TocTreeCollector): 49 | def __init__(self, *args, **kwargs): 50 | super().__init__(*args, **kwargs) 51 | 52 | self.__within_appendices = False 53 | self.__chapter_offset = 0 54 | self.__appendix_offset = 0 55 | self.__chapter_max = 0 56 | self.__appendix_max = 0 57 | 58 | def assign_section_numbers(self, env): 59 | result = super().assign_section_numbers(env) 60 | 61 | for docname in env.numbered_toctrees: 62 | doctree = env.get_doctree(docname) 63 | for toctree in doctree.findall(sphinxnodes.toctree): 64 | self.__replace_toctree(env, toctree) 65 | 66 | self.__chapter_offset = self.__chapter_max 67 | self.__appendix_offset = self.__appendix_max 68 | 69 | return result 70 | 71 | def __replace_toctree(self, env, toctree): 72 | self.__within_appendices = "are_appendices" in toctree 73 | for _, ref in toctree["entries"]: 74 | env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"]) 75 | if ref in env.tocs: 76 | self.__replace_toc(env, ref, env.tocs[ref]) 77 | 78 | def __replace_toc(self, env, ref, node): 79 | if isinstance(node, nodes.reference): 80 | fixed_number = self.__renumber(node["secnumber"]) 81 | node["secnumber"] = fixed_number 82 | env.toc_secnumbers[ref][node["anchorname"]] = fixed_number 83 | 84 | elif isinstance(node, sphinxnodes.toctree): 85 | raise RuntimeError("nested toctrees are not supported") 86 | 87 | else: 88 | for child in node.children: 89 | self.__replace_toc(env, ref, child) 90 | 91 | def __renumber(self, number): 92 | if not number: 93 | return number 94 | 95 | if self.__within_appendices: 96 | with_offset = self.__appendix_offset + number[0] 97 | if with_offset > 26: 98 | raise RuntimeError("more than 26 appendices are not supported") 99 | 100 | fixed = chr(ord("A") - 1 + with_offset) 101 | self.__appendix_max = max(self.__appendix_max, with_offset) 102 | else: 103 | fixed = self.__chapter_offset + number[0] 104 | self.__chapter_max = max(self.__chapter_max, fixed) 105 | 106 | return (fixed, *number[1:]) 107 | 108 | 109 | # This extension needs to replace the builtin TocTreeCollector, so it's safer 110 | # to disable it. That'll avoid two TocTreeCollectors running in the build. 111 | def disable_builtin_toctree_collector(app): 112 | for obj in gc.get_objects(): 113 | if not isinstance(obj, TocTreeCollector): 114 | continue 115 | # When running sphinx-autobuild, this function might be called multiple 116 | # times. When the collector is already disabled `listener_ids` will be 117 | # `None`, and thus we don't need to disable it again. 118 | # 119 | # Note that disabling an already disabled collector will fail. 120 | if obj.listener_ids is None: 121 | continue 122 | obj.disable(app) 123 | 124 | 125 | def setup(app): 126 | app.add_directive("appendices", AppendicesDirective) 127 | 128 | disable_builtin_toctree_collector(app) 129 | app.add_env_collector(TocTreeCollectorWithAppendices) 130 | 131 | return { 132 | "version": "0", 133 | "parallel_read_safe": True, 134 | "parallel_write_safe": True, 135 | } 136 | -------------------------------------------------------------------------------- /make.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S uv run 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # SPDX-FileCopyrightText: The Ferrocene Developers 4 | # SPDX-FileCopyrightText: The Rust Project Contributors 5 | 6 | import os 7 | from pathlib import Path 8 | import argparse 9 | import subprocess 10 | import shutil 11 | 12 | # Automatically watch the following extra directories when --serve is used. 13 | EXTRA_WATCH_DIRS = ["exts", "themes"] 14 | 15 | 16 | def build_docs(root, builder, clear, serve, debug): 17 | dest = root / "build" 18 | output_dir = dest / builder 19 | 20 | args = ["-b", builder, "-d", dest / "doctrees"] 21 | if debug: 22 | # Disable parallel builds and show exceptions in debug mode. 23 | # 24 | # We can't show exceptions in parallel mode because in parallel mode 25 | # all exceptions will be swallowed up by Python's multiprocessing. 26 | # That's also why we don't show exceptions outside of debug mode. 27 | args += ["-j", "1", "-T"] 28 | else: 29 | # Enable parallel builds: 30 | args += ["-j", "auto"] 31 | if clear: 32 | if output_dir.exists(): 33 | shutil.rmtree(output_dir) 34 | # Using a fresh environment 35 | args.append("-E") 36 | if serve: 37 | for extra_watch_dir in EXTRA_WATCH_DIRS: 38 | extra_watch_dir = root / extra_watch_dir 39 | if extra_watch_dir.exists(): 40 | args += ["--watch", extra_watch_dir] 41 | else: 42 | # Error out at the *end* of the build if there are warnings: 43 | args += ["-W", "--keep-going"] 44 | 45 | commit = current_git_commit(root) 46 | if commit is not None: 47 | args += ["-D", f"html_theme_options.commit={commit}"] 48 | 49 | try: 50 | subprocess.run( 51 | [ 52 | "sphinx-autobuild" if serve else "sphinx-build", 53 | *args, 54 | root / "src", 55 | output_dir, 56 | ], 57 | check=True, 58 | ) 59 | except KeyboardInterrupt: 60 | exit(1) 61 | except subprocess.CalledProcessError: 62 | print("\nhint: if you see an exception, pass --debug to see the full traceback") 63 | exit(1) 64 | 65 | return dest / builder 66 | 67 | 68 | def build_linkchecker(root): 69 | repo = root / ".linkchecker" 70 | src = repo / "src" / "tools" / "linkchecker" 71 | bin = src / "target" / "release" / "linkchecker" 72 | 73 | if not src.is_dir(): 74 | subprocess.run(["git", "init", repo], check=True) 75 | 76 | def git(args): 77 | subprocess.run(["git", *args], cwd=repo, check=True) 78 | 79 | # Avoid fetching blobs unless needed by the sparse checkout 80 | git(["remote", "add", "origin", "https://github.com/rust-lang/rust"]) 81 | git(["config", "remote.origin.promisor", "true"]) 82 | git(["config", "remote.origin.partialCloneFilter", "blob:none"]) 83 | 84 | # Checkout only the linkchecker tool rather than the whole repo 85 | git(["config", "core.sparsecheckout", "true"]) 86 | with open(repo / ".git" / "info" / "sparse-checkout", "w") as f: 87 | f.write("/src/tools/linkchecker/") 88 | 89 | # Avoid fetching the whole history 90 | git(["fetch", "--depth=1", "origin", "main"]) 91 | git(["checkout", "main"]) 92 | 93 | if not bin.is_file(): 94 | subprocess.run(["cargo", "build", "--release"], cwd=src, check=True) 95 | 96 | return bin 97 | 98 | 99 | def current_git_commit(root): 100 | try: 101 | return ( 102 | subprocess.run( 103 | ["git", "rev-parse", "HEAD"], 104 | check=True, 105 | stdout=subprocess.PIPE, 106 | ) 107 | .stdout.decode("utf-8") 108 | .strip() 109 | ) 110 | # `git` executable missing from the system 111 | except FileNotFoundError: 112 | print("warning: failed to detect git commit: missing executable git") 113 | return 114 | # `git` returned an error (git will print the actual error to stderr) 115 | except subprocess.CalledProcessError: 116 | print("warning: failed to detect git commit: git returned an error") 117 | return 118 | 119 | 120 | def main(root): 121 | root = Path(root) 122 | 123 | parser = argparse.ArgumentParser() 124 | parser.add_argument( 125 | "-c", "--clear", help="disable incremental builds", action="store_true" 126 | ) 127 | group = parser.add_mutually_exclusive_group() 128 | group.add_argument( 129 | "-s", 130 | "--serve", 131 | help="start a local server with live reload", 132 | action="store_true", 133 | ) 134 | group.add_argument( 135 | "--check-links", help="Check whether all links are valid", action="store_true" 136 | ) 137 | group.add_argument( 138 | "--xml", help="Generate Sphinx XML rather than HTML", action="store_true" 139 | ) 140 | group.add_argument( 141 | "--debug", 142 | help="Debug mode for the extensions, showing exceptions", 143 | action="store_true", 144 | ) 145 | args = parser.parse_args() 146 | 147 | rendered = build_docs( 148 | root, "xml" if args.xml else "html", args.clear, args.serve, args.debug 149 | ) 150 | 151 | if args.check_links: 152 | linkchecker = build_linkchecker(root) 153 | if subprocess.run([linkchecker, rendered]).returncode != 0: 154 | print("error: linkchecker failed") 155 | exit(1) 156 | 157 | 158 | main(os.path.abspath(os.path.dirname(__file__))) 159 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/README.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | ==================== 5 | FLS Sphinx Extension 6 | ==================== 7 | 8 | To enhance the FLS, and to facilitate its authoring, updating, and testing it 9 | easier, we developed and use a custom Sphinx extension that adds new roles and 10 | directives. The source code of the extension is in the ``exts/ferrocene_spec`` 11 | directory. 12 | 13 | .. contents:: In this document: 14 | 15 | Definitions 16 | =========== 17 | 18 | To aid users reading the FLS, we make extensive use of internal links. Since 19 | Sphinx's native support for creating and linking to definitions did not suit 20 | our needs we implemented custom roles for defining and linking to definitions. 21 | 22 | Definition namespaces 23 | --------------------- 24 | 25 | The extension includes support for multiple definition namespaces. In addition 26 | to allowing the same name to be used as a definition in multiple namespaces, 27 | each namespace has a different styling when rendered. 28 | 29 | .. list-table:: 30 | :header-rows: 1 31 | 32 | * - Namespace 33 | - Link role 34 | - Definition role 35 | - Styling 36 | 37 | * - Terms 38 | - ``:t:`foo``` 39 | - ``:dt:`foo``` 40 | - Normal text 41 | 42 | * - Programmatic constructs 43 | - ``:c:`foo``` 44 | - ``:dc:`foo``` 45 | - Monospace text 46 | 47 | * - Syntactic categories 48 | - ``:s:`Foo``` 49 | - ``:ds:`Foo``` 50 | - Monospace text 51 | 52 | Both link roles and definition roles are standard reStructuredText roles, and 53 | can be used inline inside a sentence. For example: 54 | 55 | .. code-block:: rst 56 | 57 | An :dt:`associated item` is an :t:`item` that appears within an :dt:`implementation` or a :dt:`trait`. 58 | 59 | Definitions are case insensitive: you can define and link to them with 60 | whichever case suits the surrounding text the most. 61 | 62 | Linking to definitions 63 | ---------------------- 64 | 65 | The standard syntax for link roles is to just include the name of the 66 | definition inside the role, which will generate a link to the place the 67 | definition is defined in. In addition to that, more advanced syntaxes are 68 | available to handle more complex use cases. 69 | 70 | Prefixes and suffixes 71 | ~~~~~~~~~~~~~~~~~~~~~ 72 | 73 | Sometimes you might need to add prefixes or suffixes to a word you're linking, 74 | for example adding an ``s`` at the end to pluralize it. The native RST syntax 75 | for that is quite clunky, as you need to put an "escaped space" between the 76 | role and the rest of the word: 77 | 78 | .. code-block:: rst 79 | 80 | Multiple :t:`value`\ s can be used here. 81 | 82 | The snippet above will render as you'd expect ("Multiple values can be used 83 | here" with a link on "value"), but that syntax is hard to read and annoying to 84 | write. To ease adding prefixes and suffixes to links, the extension allows you 85 | to include the prefix and suffix inside the role itself, by wrapping the actual 86 | definition inside square brackets: 87 | 88 | .. code-block:: rst 89 | 90 | Multiple :t:`[value]s` can be used here. 91 | 92 | Arbitrary labels 93 | ~~~~~~~~~~~~~~~~ 94 | 95 | If you need to link to a definition but the link label doesn't fully contain 96 | the definition name (for example if you're using a sentence as the link label, 97 | or you need to pluralize a word with irregular plurals) you can put the 98 | arbitrary label inside the role and put the definition name at the end of the 99 | role within angle brackets: 100 | 101 | .. code-block:: rst 102 | 103 | The :t:`criteria ` used for the change are: 104 | 105 | Links to the Rust standard library 106 | ================================== 107 | 108 | You can link to the documentation of items defined in the Rust standard library 109 | (``core``, ``alloc``, ``std``, ``test`` and ``proc_macro``) by using the 110 | ``:std:`type``` role (even for types defined in other standard library crates) 111 | with the fully qualified item path: 112 | 113 | .. code-block:: rst 114 | 115 | The type needs to implement :std:`core::marker::Copy`. 116 | 117 | Syntax blocks 118 | ============= 119 | 120 | To ease the process of defining blocks of syntax definitions, the extension 121 | implements the custom ``syntax`` directive, which parses the syntax contained 122 | within it and automatically inserts definitions and links to the referenced 123 | syntactic categories: 124 | 125 | .. code-block:: rst 126 | 127 | .. syntax:: 128 | 129 | ExpressionStatement ::= 130 | ExpressionWithBlock $$;$$? 131 | | ExpressionWithoutBlock $$;$$ 132 | 133 | In the directive above, the extension will automatically insert a syntactic 134 | category definition for ``ExpressionStatement`` (since it's followed by ``::=``), and it 135 | will insert syntactic category links for both ``ExpressionWithBlock`` and 136 | ``ExpressionWithoutBlock``. 137 | 138 | Words and characters wrapped within ``$$`` are considered "literals": they will 139 | be rendered differently than syntactic categories, and they won't be considered 140 | by the extension when looking for syntactic categories. 141 | 142 | Paragraph IDs 143 | ============= 144 | 145 | Ferrocene's test suite needs each paragraph in the FLS to have a unique ID 146 | attached to it. To ensure that this happens, the extension provides a way to 147 | easily define the ID for each paragraph, and to use that ID to link to the 148 | paragraph from other parts of the FLS. 149 | 150 | Paragraph IDs can be added to a paragraph with the ``:dp:`id``` role. The role must 151 | contain an unique random ID prefixed with ``fls_``, and the role must appear at 152 | the start of a paragraph: 153 | 154 | .. code-block:: rst 155 | 156 | :dp:`fls_qTgd9xuAY3n3` 157 | This is a paragraph with an ID. 158 | 159 | You can generate a list of random IDs by running the following command from the 160 | root of the specification repository:: 161 | 162 | ./generate-random-ids.py 163 | 164 | You can also link to an existing paragraph with the ``:p:`id``` role: 165 | 166 | .. code-block:: rst 167 | 168 | See :p:`fls_qTgd9xuAY3n3` for a sample paragraph using IDs. 169 | 170 | Note that paragraph IDs are also used to generate the human-readable paragraph 171 | numbers generated by Sphinx: while IDs are supposed to be stable across FLS 172 | revisions, the human-readable paragraph numbers can change between renderings. 173 | -------------------------------------------------------------------------------- /src/statements.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_wdicg3sqa98e: 7 | 8 | Statements 9 | ========== 10 | 11 | .. rubric:: Syntax 12 | 13 | .. syntax:: 14 | 15 | Statement ::= 16 | ExpressionStatement 17 | | Item 18 | | LetStatement 19 | | TerminatedMacroInvocation 20 | | $$;$$ 21 | 22 | .. rubric:: Legality Rules 23 | 24 | :dp:`fls_7zh6ziglo5iy` 25 | An :t:`expression statement` is an :t:`expression` whose result is ignored. 26 | 27 | :dp:`fls_kdxe1ukmgl1` 28 | An :t:`item statement` is a :t:`statement` that is expressed as an :t:`item`. 29 | 30 | :dp:`fls_fftdnwe22xrb` 31 | An :t:`empty statement` is a :t:`statement` expressed as character 0x3B 32 | (semicolon). 33 | 34 | :dp:`fls_or125cqtxg9j` 35 | A :t:`macro statement` is a :t:`statement` expressed as a 36 | :t:`terminated macro invocation`. 37 | 38 | .. rubric:: Dynamic Semantics 39 | 40 | :dp:`fls_estqu395zxgk` 41 | :t:`Execution` is the process by which a :t:`statement` achieves its runtime 42 | effects. 43 | 44 | :dp:`fls_dl763ssb54q1` 45 | The :t:`execution` of an :t:`empty statement` has no effect. 46 | 47 | .. _fls_yivm43r5wnp1: 48 | 49 | Let Statements 50 | -------------- 51 | 52 | .. rubric:: Syntax 53 | 54 | .. syntax:: 55 | 56 | LetStatement ::= 57 | OuterAttributeOrDoc* $$let$$ PatternWithoutAlternation TypeAscription? LetInitializer? $$;$$ 58 | 59 | LetInitializer ::= 60 | $$=$$ Expression ($$else$$ BlockExpression)? 61 | 62 | .. rubric:: Legality Rules 63 | 64 | :dp:`fls_ct7pp7jnfr86` 65 | A :t:`let statement` is a :t:`statement` that introduces new :t:`[binding]s` 66 | produced by its :t:`pattern-without-alternation` that are optionally 67 | initialized to a :t:`value`. 68 | 69 | :dp:`fls_SR3dIgR5K0Kq` 70 | A :t:`let initializer` is a :t:`construct` that provides the :t:`value` of 71 | the :t:`[binding]s` of the :t:`let statement` using an :t:`expression`, or 72 | alternatively executes a :t:`block expression`. 73 | 74 | :dp:`fls_iqar7vvtw22c` 75 | If a :t:`let statement` lacks a :t:`block expression`, then the :t:`pattern` of 76 | the :t:`let statement` shall be an :t:`irrefutable pattern`. 77 | 78 | :dp:`fls_1s1UikGU5YQb` 79 | If a :t:`let statement` has a :t:`block expression`, then the :s:`Expression` of 80 | the :s:`LetInitializer` shall not be a :s:`LazyBooleanExpression` or end with 81 | token ``}``. 82 | 83 | :dp:`fls_iB25BeFys0j8` 84 | The :t:`expected type` of the :t:`pattern` of the :t:`let statement` is determined as follows: 85 | 86 | * :dp:`fls_zObyLdya4DYc` 87 | If the :t:`let statement` lacks a :t:`type ascription` and a :t:`let initializer`, then the :t:`expected type` is the :t:`inferred type`. 88 | 89 | * :dp:`fls_r38TXWKQPjxv` 90 | If the :t:`let statement` lacks a :t:`type ascription`, then the :t:`expected type` is the :t:`type` of the :t:`let initializer`. 91 | 92 | * :dp:`fls_6QSdwF4pzjoe` 93 | Otherwise the :t:`expected type` is the :t:`type` specified by the :t:`type ascription`. 94 | 95 | :dp:`fls_1prqh1trybwz` 96 | The :t:`type` of a :t:`binding` introduced by a :t:`let statement` is 97 | determined as follows: 98 | 99 | * :dp:`fls_djkm8r2iuu6u` 100 | If the :t:`let statement` appears with a :t:`type ascription`, then the 101 | :t:`type` is the :t:`type` specified by the :t:`type ascription`. 102 | 103 | * :dp:`fls_ppj9gvhp8wcj` 104 | If the :t:`let statement` lacks a :t:`type ascription`, then the :t:`type` is 105 | inferred using :t:`type inference`. 106 | 107 | :dp:`fls_1eBQDZdBuDsN` 108 | The :t:`type` of the :t:`block expression` of a :t:`let statement` shall be the 109 | :t:`never type`. 110 | 111 | :dp:`fls_m8a7gesa4oim` 112 | The :t:`value` of a :t:`binding` introduced by a :t:`let statement` is 113 | determined as follows: 114 | 115 | * :dp:`fls_oaxnre7m9s10` 116 | If the :t:`let statement` appears with a :t:`let initializer`, then the 117 | :t:`value` is the :t:`value` of the :t:`expression` of the 118 | :t:`let initializer`. 119 | 120 | * :dp:`fls_t5bjwluyv8za` 121 | Otherwise the :t:`binding` is uninitialized. 122 | 123 | .. rubric:: Dynamic Semantics 124 | 125 | :dp:`fls_4j9riqyf4p9` 126 | The :t:`execution` of a :t:`let statement` with a :t:`let initializer` proceeds 127 | as follows: 128 | 129 | #. :dp:`fls_t53g5hlabqw1` 130 | The :t:`expression` of the :t:`let initializer` is evaluated. 131 | 132 | #. :dp:`fls_7j4qlwg72ege` 133 | If the :t:`value` of the :t:`expression` is matched successfully against the 134 | :t:`pattern` of the :t:`let statement`, then the :t:`value` is assigned to 135 | each :t:`binding` introduced by the :t:`let statement`. 136 | 137 | #. :dp:`fls_ea9bRFZjH8Im` 138 | Otherwise the :t:`block expression` of the :t:`let initializer` is evaluated. 139 | 140 | .. rubric:: Examples 141 | 142 | .. code-block:: rust 143 | 144 | let local = 0; 145 | let local: u32; 146 | let (a, b) = (0, 0); 147 | let Some(value) = vector.pop() else { 148 | panic!(); 149 | }; 150 | 151 | .. _fls_1pg5ig740tg1: 152 | 153 | Expression Statements 154 | --------------------- 155 | 156 | .. rubric:: Syntax 157 | 158 | .. syntax:: 159 | 160 | ExpressionStatement ::= 161 | ExpressionWithBlock $$;$$? 162 | | ExpressionWithoutBlock $$;$$ 163 | 164 | .. rubric:: Legality Rules 165 | 166 | :dp:`fls_xmdj8uj7ixoe` 167 | An :t:`expression statement` is an :t:`expression` whose result is ignored. 168 | 169 | :dp:`fls_gzzmudc1hl6s` 170 | The :t:`expected type` of an :t:`expression statement` without character 0x3B 171 | (semicolon) is the :t:`unit type`. 172 | 173 | .. rubric:: Dynamic Semantics 174 | 175 | :dp:`fls_kc99n8qrszxh` 176 | The :t:`execution` of an :t:`expression statement` proceeds as follows: 177 | 178 | #. :dp:`fls_r8poocwqaglf` 179 | The :t:`operand` is evaluated. 180 | 181 | #. :dp:`fls_88e6s3erk8tj` 182 | The :t:`value` of the :t:`operand` is :t:`dropped`. 183 | 184 | .. rubric:: Examples 185 | 186 | .. code-block:: rust 187 | 188 | let mut values = vec![1, 2, 3]; 189 | 190 | :dp:`fls_4q90jb39apwr` 191 | The following expression statement ignores the result from ``pop()``. 192 | 193 | .. code-block:: rust 194 | 195 | values.pop(); 196 | 197 | :dp:`fls_xqtztcu8ibwq` 198 | The following expression statement does not require a semicolon. 199 | 200 | .. code-block:: rust 201 | 202 | if values.is_empty() { 203 | values.push(42); 204 | } 205 | else { 206 | values.remove(0); 207 | } 208 | 209 | :dp:`fls_2p9xnt519nbw` 210 | The following expression statement is not an index expression. 211 | 212 | .. code-block:: rust 213 | 214 | [42]; 215 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/syntax_directive.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from .definitions import DefIdNode, DefRefNode 5 | from docutils import nodes 6 | from sphinx.directives import SphinxDirective 7 | 8 | 9 | class SyntaxDirective(SphinxDirective): 10 | has_content = True 11 | 12 | def run(self): 13 | # The first argument of creating any docutils node is the "raw source", 14 | # which in theory is completely optional for our needs. That's why all 15 | # the nodes we create pass an empty string (the default) to it. 16 | # 17 | # Still, this block is fairly special: to decide whether to perform 18 | # syntax highlighting on a literal block, Sphinx compares the raw 19 | # source with the output of the astext() method, and it highlights only 20 | # if the two are equal. 21 | # 22 | # We had problems in the past with the heuristic randomly causing the 23 | # syntax blocks to be highlighted by Sphinx (thus losing all our custom 24 | # formatting). Thus, to avoid problems we set the raw source to 25 | # something that will never appear in the astext() output (byte zero). 26 | node = nodes.literal_block("\0") 27 | 28 | node["classes"].append("spec-syntax") 29 | 30 | for child in Parser("\n".join(self.content), self.env.docname).parse(): 31 | node += child 32 | 33 | return [node] 34 | 35 | 36 | class Parser: 37 | def __init__(self, content, document_name): 38 | self.document_name = document_name 39 | self.lexer = Lexer(content).lex() 40 | self.peek_buffer = [] 41 | 42 | def parse(self): 43 | while True: 44 | token = self.next() 45 | if token is None: 46 | return 47 | 48 | if token.kind == "literal": 49 | node = nodes.strong("", token.content) 50 | node["classes"].append("spec-syntax-literal") 51 | yield node 52 | 53 | elif token.kind == "identifier" and is_syntax_identifier(token.content): 54 | 55 | def peek_kind(kind, nth=0): 56 | peeked = self.peek(nth) 57 | return peeked is not None and peeked.kind == kind 58 | 59 | if peek_kind("definition", int(peek_kind("whitespace"))): 60 | yield DefIdNode("syntaxes", token.content) 61 | else: 62 | yield DefRefNode("syntaxes", self.document_name, token.content) 63 | 64 | else: 65 | yield nodes.Text(token.content) 66 | 67 | def next(self): 68 | if self.peek_buffer: 69 | return self.peek_buffer.pop(0) 70 | else: 71 | return next(self.lexer, None) 72 | 73 | def peek(self, nth=0): 74 | while len(self.peek_buffer) <= nth: 75 | token = next(self.lexer, None) 76 | if token is None: 77 | return None 78 | self.peek_buffer.append(token) 79 | return self.peek_buffer[nth] 80 | 81 | 82 | class Lexer: 83 | def __init__(self, content): 84 | self.content = content 85 | self.pos = 0 86 | 87 | def lex(self): 88 | while True: 89 | char = self.next() 90 | if char is None: 91 | return 92 | 93 | if char == "$" and self.peek() == "$": 94 | self.next() # Consume the second "$" 95 | 96 | # Collect all the chars until the next `$$` 97 | buffer = "" 98 | while True: 99 | peeked = self.peek() 100 | if peeked is None: 101 | break 102 | # We check that the third peek is not a "$" to perform a 103 | # greedy parsing. This way, $$$$$ is parsed as "$" 104 | # rather than "$". 105 | elif peeked == "$" and self.peek(1) == "$" and self.peek(2) != "$": 106 | self.next() # Consume the first "$" 107 | self.next() # Consume the second "$" 108 | break 109 | else: 110 | buffer += self.next() 111 | yield Token("literal", buffer) 112 | 113 | elif char == ":" and self.peek() == ":" and self.peek(1) == "=": 114 | self.next() # Consume the second ":" 115 | self.next() # Consume the "=" 116 | yield Token("definition", "::=") 117 | 118 | elif char.isalpha(): 119 | buffer = char 120 | while True: 121 | peeked = self.peek() 122 | if peeked is None or not (peeked.isalpha() or peeked == "_"): 123 | break 124 | buffer += self.next() 125 | yield Token("identifier", buffer) 126 | 127 | elif char.isspace(): 128 | buffer = char 129 | while True: 130 | peeked = self.peek() 131 | if peeked is None or not peeked.isspace(): 132 | break 133 | buffer += self.next() 134 | yield Token("whitespace", buffer) 135 | 136 | else: 137 | yield Token("other", char) 138 | 139 | def peek(self, nth=0): 140 | try: 141 | return self.content[self.pos + nth] 142 | except IndexError: 143 | return None 144 | 145 | def next(self): 146 | try: 147 | char = self.content[self.pos] 148 | except IndexError: 149 | return None 150 | self.pos += 1 151 | return char 152 | 153 | 154 | def is_syntax_identifier(identifier): 155 | EXPECT_ANY = 0 156 | EXPECT_UPPER = 1 157 | EXPECT_LOWER = 2 158 | 159 | # Some of the identifier referring to Unicode categories are called 160 | # XID_Category. The problem is that the XID_ portion is not a valid 161 | # identifier based on our rules. This code special-case that by ignoring 162 | # the problematic part of the identifier. 163 | if identifier.startswith("XID_"): 164 | identifier = identifier[len("XID_") :] 165 | # An unfortunate case where we end up with a single letter prefix violating 166 | # our rules. Special case this like above by avoiding the rule breakage. 167 | if identifier == "CStringLiteral": 168 | identifier = "CstringLiteral" 169 | 170 | expected = EXPECT_UPPER 171 | for char in identifier: 172 | if expected == EXPECT_UPPER: 173 | if not char.isupper(): 174 | return False 175 | expected = EXPECT_LOWER 176 | elif expected == EXPECT_LOWER: 177 | if char.isupper(): 178 | return False 179 | expected = EXPECT_ANY 180 | 181 | return True 182 | 183 | 184 | class Token: 185 | def __init__(self, kind, content=None): 186 | self.kind = kind 187 | self.content = content 188 | -------------------------------------------------------------------------------- /src/associated-items.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_l21tjqjkkaa0: 7 | 8 | Associated Items 9 | ================ 10 | 11 | .. rubric:: Syntax 12 | 13 | .. syntax:: 14 | 15 | AssociatedItem ::= 16 | OuterAttributeOrDoc* (AssociatedItemWithVisibility | TerminatedMacroInvocation) 17 | 18 | AssociatedItemWithVisibility ::= 19 | VisibilityModifier? ( 20 | ConstantDeclaration 21 | | FunctionDeclaration 22 | | TypeAliasDeclaration 23 | ) 24 | 25 | .. rubric:: Legality Rules 26 | 27 | :dp:`fls_ckzd25qd213t` 28 | An :t:`associated item` is an :t:`item` that appears within an 29 | :t:`implementation` or a :t:`trait`. 30 | 31 | :dp:`fls_5y6ae0xqux57` 32 | An :t:`associated constant` is a :t:`constant` that appears as an 33 | :t:`associated item`. 34 | 35 | :dp:`fls_lj7492aq7fzo` 36 | An :t:`associated function` is a :t:`function` that appears as an 37 | :t:`associated item`. 38 | 39 | :dp:`fls_8cz4rdrklaj4` 40 | An :t:`associated type` is a :t:`type alias` that appears as an 41 | :t:`associated item`. 42 | 43 | :dp:`fls_w8nu8suy7t5` 44 | An :t:`associated type` shall not be used in the :t:`path expression` of a 45 | :t:`struct expression`. 46 | 47 | :dp:`fls_wasocqdnuzd1` 48 | An :t:`associated type` with a :s:`TypeBoundList` shall appear only as an 49 | :t:`associated trait type`. 50 | 51 | :dp:`fls_PeD0DzjK57be` 52 | A :t:`generic associated type` is an :t:`associated type` with 53 | :t:`[generic parameter]s`. 54 | 55 | :dp:`fls_3foYUch29ZtF` 56 | A :t:`lifetime parameter` of a :t:`generic associated type` requires a 57 | :t:`bound` of the form ``T: 'lifetime``, where ``T`` is a :t:`type parameter` 58 | or :c:`Self` and ``'lifetime`` is the :t:`lifetime parameter`, when 59 | 60 | * :dp:`fls_SnQc0zZS57Cz` 61 | The :t:`generic associated type` is used in an :t:`associated function` of 62 | the same :t:`trait`, and 63 | 64 | * :dp:`fls_6Z05BK2JSzpP` 65 | The corresponding :t:`lifetime argument` in the use is not the ``'static`` 66 | :t:`lifetime` and has either an explicit :t:`bound` or an :t:`implied bound` 67 | that constrains the :t:`type parameter`, and 68 | 69 | * :dp:`fls_AtItgS1UvwiX` 70 | The intersection of all such uses is not empty. 71 | 72 | :dp:`fls_l3iwn56n1uz8` 73 | An :t:`associated implementation constant` is an :t:`associated constant` that 74 | appears within an :t:`implementation`. 75 | 76 | :dp:`fls_4ftfefcotb4g` 77 | An :t:`associated implementation constant` shall have a :t:`constant 78 | initializer`. 79 | 80 | :dp:`fls_qb5qpfe0uwk` 81 | An :t:`associated implementation function` is an :t:`associated function` that 82 | appears within an :t:`implementation`. 83 | 84 | :dp:`fls_1zlkeb6fz10j` 85 | An :t:`associated implementation function` shall have a :t:`function body`. 86 | 87 | :dp:`fls_tw8u0cc5867l` 88 | An :t:`associated implementation type` is an :t:`associated type` that appears 89 | within an :t:`implementation`. 90 | 91 | :dp:`fls_bx7931x4155h` 92 | An :t:`associated implementation type` shall have an :t:`initialization type`. 93 | 94 | :dp:`fls_bnTcCbDvdp94` 95 | An :t:`associated trait item` is an :t:`associated item` that appears 96 | within a :t:`trait`. 97 | 98 | :dp:`fls_N3cdn4lCZ2Bf` 99 | An :t:`associated trait implementation item` is an :t:`associated item` that 100 | appears within a :t:`trait implementation`. 101 | 102 | :dp:`fls_x564isbhobym` 103 | An :t:`associated trait constant` is an :t:`associated constant` that appears 104 | within a :t:`trait`. 105 | 106 | :dp:`fls_b6nns7oqvdpm` 107 | An :t:`associated trait function` is an :t:`associated function` that appears 108 | within a :t:`trait`. 109 | 110 | :dp:`fls_2TRwCz38kuRz` 111 | An :t:`associated trait function` shall not be subject to :t:`keyword` ``const``. 112 | 113 | :dp:`fls_WnsVATJvUdza` 114 | Every occurrence of an :t:`impl trait type` in the :t:`return type` of an 115 | :t:`associated trait function` is equivalent to referring to a new 116 | anonymous :t:`associated trait type` of the :t:`implemented trait`. 117 | 118 | :dp:`fls_yyhebj4qyk34` 119 | An :t:`associated trait type` is an :t:`associated type` that appears within 120 | a :t:`trait`. 121 | 122 | :dp:`fls_kl9p3ycl5mzf` 123 | An :t:`associated trait type` shall not have an :t:`initialization type`. 124 | 125 | :dp:`fls_a5prbmuruma4` 126 | An :t:`associated trait type` has an implicit :std:`core::marker::Sized` 127 | :t:`bound`. 128 | 129 | :dp:`fls_vp2ov6ykueue` 130 | An :t:`associated trait type` of the form 131 | 132 | .. code-block:: rust 133 | 134 | trait T { 135 | type X: Bound; 136 | } 137 | 138 | :dp:`fls_5uf74nvdm64o` 139 | is equivalent to a :t:`where clause` of the following form: 140 | 141 | .. code-block:: rust 142 | 143 | trait T where Self::X: Bound { 144 | type X; 145 | } 146 | 147 | :dp:`fls_amWtS80fPtza` 148 | An :t:`associated trait implementation function` is an :t:`associated function` 149 | that appears within a :t:`trait implementation`. 150 | 151 | :dp:`fls_Cu8FWrisrqz1` 152 | Every occurrence of an :t:`impl trait type` in the :t:`return type` of an 153 | :t:`associated trait implementation function` is equivalent to referring to the 154 | corresponding :t:`associated trait type` of the corresponding :t:`associated 155 | trait function`. 156 | 157 | :dp:`fls_oy92gzxgc273` 158 | A :t:`method` is an :t:`associated function` with a :t:`self parameter`. 159 | 160 | :dp:`fls_WXnCWfJGoQx3` 161 | The type of a :t:`self parameter` shall be one of the following: 162 | 163 | * :dp:`fls_OaszUw4IFobz` 164 | A :t:`type specification` resolving to the :t:`implementing type` of the 165 | related :t:`implementation`, or 166 | 167 | * :dp:`fls_Wd2FZRomB5yn` 168 | ``&T`` where ``T`` is one of the :t:`[type]s` listed in this enumeration, 169 | or 170 | 171 | * :dp:`fls_lcEyToYIlcmf` 172 | ``&mut T`` where ``T`` is one of the :t:`[type]s` listed in this 173 | enumeration, or 174 | 175 | * :dp:`fls_IKSPR7ZQMErU` 176 | :std:`core::pin::Pin ` where ``T`` is one of the :t:`[type]s` listed in this 177 | enumeration. 178 | 179 | :dp:`fls_oHxzyaiT7Qm6` 180 | The :t:`visibility modifier` of an :t:`associated trait item` or :t:`associated 181 | trait implementation item` is rejected, but may still be consumed by 182 | :t:`[macro]s`. 183 | 184 | .. rubric:: Examples 185 | 186 | .. code-block:: rust 187 | 188 | trait Greeter { 189 | const MAX_GREETINGS: i32; 190 | 191 | fn greet(self, message: &str); 192 | } 193 | 194 | struct Implementor { 195 | delivered_greetings: i32 196 | } 197 | 198 | impl Greeter for Implementor { 199 | const MAX_GREETINGS: i32 = 42; 200 | 201 | fn greet(mut self, message: &str) { 202 | if self.delivered_greetings < Self::MAX_GREETINGS { 203 | self.delivered_greetings += 1; 204 | println!("{}", message); 205 | } 206 | } 207 | } 208 | 209 | :dp:`fls_znfADVeOvXHD` 210 | Generic associated type with lifetime bound. 211 | 212 | .. code-block:: rust 213 | 214 | trait LendingIterator { 215 | type Item<'x> where Self: 'x; 216 | 217 | fn next<'a>(&'a mut self) -> Self::Item<'a>; 218 | } 219 | -------------------------------------------------------------------------------- /src/functions.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_qcb1n9c0e5hz: 7 | 8 | Functions 9 | ========= 10 | 11 | .. rubric:: Syntax 12 | 13 | .. syntax:: 14 | 15 | FunctionDeclaration ::= 16 | FunctionQualifierList $$fn$$ Name GenericParameterList? $$($$ FunctionParameterList? $$)$$ ReturnType? WhereClause? (FunctionBody | $$;$$) 17 | 18 | FunctionQualifierList ::= 19 | $$const$$? $$async$$? ItemSafety? AbiSpecification? 20 | 21 | FunctionParameterList ::= 22 | (FunctionParameter ($$,$$ FunctionParameter)* $$,$$?) 23 | | (SelfParameter ($$,$$ FunctionParameter)* $$,$$?) 24 | 25 | FunctionParameter ::= 26 | OuterAttributeOrDoc* (FunctionParameterPattern | FunctionParameterVariadicPart | TypeSpecification) 27 | 28 | FunctionParameterPattern ::= 29 | PatternWithoutAlternation (TypeAscription | ($$:$$ FunctionParameterVariadicPart)) 30 | 31 | FunctionParameterVariadicPart ::= 32 | $$...$$ 33 | 34 | ReturnType ::= 35 | $$->$$ TypeSpecification 36 | 37 | FunctionBody ::= 38 | BlockExpression 39 | 40 | SelfParameter ::= 41 | OuterAttributeOrDoc* (ShorthandSelf | TypedSelf) 42 | 43 | ShorthandSelf ::= 44 | ($$&$$ LifetimeIndication?)? $$mut$$? $$self$$ 45 | 46 | TypedSelf ::= 47 | $$mut$$? $$self$$ TypeAscription 48 | 49 | .. rubric:: Legality Rules 50 | 51 | :dp:`fls_gn1ngtx2tp2s` 52 | A :t:`function` is a :t:`value` of a :t:`function type` that models a behavior. 53 | 54 | :dp:`fls_bdx9gnnjxru3` 55 | A :t:`function` declares a unique :t:`function item type` for itself. 56 | 57 | :dp:`fls_87jnkimc15gi` 58 | A :t:`function qualifier` is a :t:`construct` that determines the role of 59 | a :t:`function`. 60 | 61 | :dp:`fls_nwywh1vjt6rr` 62 | A :t:`function` shall not be subject to both :t:`keyword` ``async`` and 63 | :t:`keyword` ``const``. 64 | 65 | :dp:`fls_uwuthzfgslif` 66 | A :t:`function parameter` is a :t:`construct` that yields a set of 67 | :t:`[binding]s` that bind matched input :t:`[value]s` to :t:`[name]s` at the 68 | site of a :t:`call expression` or a :t:`method call expression`. 69 | 70 | :dp:`fls_ymeo93t4mz4` 71 | A :t:`self parameter` is a :t:`function parameter` expressed by :t:`keyword` 72 | ``self``. 73 | 74 | :dp:`fls_ijbt4tgnl95n` 75 | A :t:`function` shall not specify a :t:`self parameter` unless it is an 76 | :t:`associated function`. 77 | 78 | :dp:`fls_AAYJDCNMJgTq` 79 | The :t:`type` of a :t:`function parameter` is determined as follows: 80 | 81 | * :dp:`fls_PGtp39f6gJwU` 82 | If the :t:`function parameter` is a :t:`self parameter` without a :s:`TypeSpecification`: 83 | 84 | * :dp:`fls_yZ2yIXxmy2ri` 85 | And the :t:`self parameter` has token ``&`` and :t:`keyword` ``mut``, then the :t:`type` is ``&mut Self``. 86 | 87 | * :dp:`fls_35aSvBxBnIzm` 88 | And the :t:`self parameter` has token ``&`` and lacks :t:`keyword` ``mut``, then the :t:`type` is ``&Self``. 89 | 90 | * :dp:`fls_Ogziu8S01qPQ` 91 | And the :t:`self parameter` lacks token ``&`` and :t:`keyword` ``mut``, then the :t:`type` is ``Self``. 92 | 93 | * :dp:`fls_xCSsxYUZUFed` 94 | Otherwise the :t:`type` is the specified :t:`type`. 95 | 96 | :dp:`fls_lxzinvqveuqh` 97 | The :t:`pattern` of a :t:`function parameter` shall be an :t:`irrefutable 98 | pattern`. 99 | 100 | :dp:`fls_kcAbTPZXQ5Y8` 101 | The :t:`expected type` of the :t:`pattern` of a :t:`function parameter` is the :t:`type` of the :t:`function parameter`. 102 | 103 | :dp:`fls_PGDKWK7nPvgw` 104 | The :t:`[binding]s` of all :t:`[pattern]s` of all :t:`[function parameter]s` of a :t:`function` shall not shadow another. 105 | 106 | :dp:`fls_o4uSLPo00KUg` 107 | A :dt:`variadic function` is an :t:`external function` that specifies 108 | :s:`FunctionParameterVariadicPart` as the last :t:`function parameter`. 109 | 110 | :dp:`fls_icdzs1mjh0n4` 111 | A :t:`variadic function` shall specify one of the following :t:`[ABI]s`: 112 | 113 | * :dp:`fls_OR85NVifPwjr` 114 | ``extern "C"`` 115 | * :dp:`fls_4s2IdfYDzPrX` 116 | ``extern "C-unwind"`` 117 | * :dp:`fls_ZJJppPfiJRou` 118 | ``extern "aapcs"`` 119 | * :dp:`fls_jOyZh9ujWWHQ` 120 | ``extern "aapcs-unwind"`` 121 | * :dp:`fls_Xdr0bFwxhWiB` 122 | ``extern "cdecl"`` 123 | * :dp:`fls_DpTFEHZAABdD` 124 | ``extern "cdecl-unwind"`` 125 | * :dp:`fls_b7FTlWfnX2OI` 126 | ``extern "efiapi"`` 127 | * :dp:`fls_6urL6fZ5cpaA` 128 | ``extern "system"`` 129 | * :dp:`fls_TMOzb6cYIOlH` 130 | ``extern "system-unwind"`` 131 | * :dp:`fls_eHPWHrvs7ETl` 132 | ``extern "sysv64"`` 133 | * :dp:`fls_mjCrvmikm58M` 134 | ``extern "sysv64-unwind"`` 135 | * :dp:`fls_4EUb9zFatZ97` 136 | ``extern "win64"`` 137 | * :dp:`fls_4B4B5FIqAes9` 138 | ``extern "win64-unwind"`` 139 | 140 | :dp:`fls_vljy4mm0zca2` 141 | A :t:`return type` is the :t:`type` of the result a :t:`function`, :t:`closure type` or :t:`function pointer type` returns. 142 | 143 | :dp:`fls_EqJb3Jl3vK8K` 144 | The :t:`return type` of a :t:`function` is determined as follows: 145 | 146 | * :dp:`fls_C7dvzcXcpQCy` 147 | If the :s:`FunctionDeclaration` specifies a :s:`ReturnType`, then the :t:`return type` is the specified :s:`ReturnType`. 148 | 149 | * :dp:`fls_J8X8ahnJLrMo` 150 | Otherwise the :t:`return type` is the :t:`unit type`. 151 | 152 | :dp:`fls_927nfm5mkbsp` 153 | A :t:`function body` is the :t:`block expression` of a :t:`function`. 154 | 155 | :dp:`fls_yfm0jh62oaxr` 156 | A :t:`function` shall have a :t:`function body` unless it is an 157 | :t:`associated trait function` or an :t:`external function`. 158 | 159 | :dp:`fls_bHwy8FLzEUi3` 160 | A :t:`function body` denotes a :t:`control flow boundary`. 161 | 162 | :dp:`fls_5Q861wb08DU3` 163 | A :t:`function body` of an :t:`async function` denotes an 164 | :t:`async control flow boundary`. 165 | 166 | :dp:`fls_owdlsaaygtho` 167 | A :t:`function signature` is a unique identification of a :t:`function` 168 | that encompasses of its :t:`[function qualifier]s`, :t:`name`, 169 | :t:`[generic parameter]s`, :t:`[function parameter]s`, :t:`return type`, and 170 | :t:`where clause`. 171 | 172 | :dp:`fls_2049qu3ji5x7` 173 | A :t:`constant function` is a :t:`function` subject to :t:`keyword` ``const``. 174 | 175 | :dp:`fls_7mlanuh5mvpn` 176 | The :t:`function body` of a :t:`constant function` shall be a 177 | :t:`constant expression`. 178 | 179 | :dp:`fls_otr3hgp8lj1q` 180 | A :t:`constant function` shall be callable from a :t:`constant context`. 181 | 182 | :dp:`fls_m3jiunibqj81` 183 | An :t:`async function` is a :t:`function` subject to :t:`keyword` ``async``. An 184 | :t:`async function` of the form 185 | 186 | .. code-block:: rust 187 | 188 | async fn async_fn(param: ¶m_type) -> return_type { 189 | /* tail expression */ 190 | } 191 | 192 | :dp:`fls_7vogmqyd87ey` 193 | is equivalent to :t:`function` 194 | 195 | .. code-block:: rust 196 | 197 | fn async_fn<'a>(param: &'a param_type) -> impl Future + 'a { 198 | async move { 199 | /* tail expression */ 200 | } 201 | } 202 | 203 | :dp:`fls_7ucwmzqtittv` 204 | An :t:`unsafe function` is a :t:`function` subject to an :s:`ItemSafety` with :t:`keyword` ``unsafe``. 205 | 206 | :dp:`fls_nUADhgcfvvGC` 207 | A :t:`function` shall only be subject to an :s:`ItemSafety` with :t:`keyword` ``safe`` if it is an :t:`external function` in an :t:`unsafe external block`. 208 | 209 | :dp:`fls_5hn8fkf7rcvz` 210 | The invocation of an :t:`unsafe function` shall require :t:`unsafe context`. 211 | 212 | .. rubric:: Examples 213 | 214 | .. code-block:: rust 215 | 216 | fn eucledian_distance(left: &Point, right: &Point) -> f64 { 217 | let x_delta_squared: f64 = (right.x - left.x).powi(2); 218 | let y_delta_squared: f64 = (right.y - left.y).powi(2); 219 | 220 | (x_delta_squared + y_delta_squared).sqrt() 221 | } 222 | 223 | fn main() {} 224 | -------------------------------------------------------------------------------- /exts/ferrocene_spec/definitions/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT OR Apache-2.0 2 | # SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | from . import paragraphs, syntax, terms, code_terms 5 | from docutils import nodes 6 | from sphinx.domains import ObjType 7 | from sphinx.environment.collectors import EnvironmentCollector 8 | from sphinx.roles import SphinxRole 9 | from sphinx.transforms import SphinxTransform 10 | import sphinx 11 | 12 | 13 | KINDS = [ 14 | paragraphs, 15 | syntax, 16 | terms, 17 | code_terms, 18 | ] 19 | 20 | 21 | class DefIdNode(nodes.Element): 22 | def __init__(self, kind, text): 23 | text, id = parse_target_from_text(text) 24 | super().__init__(def_kind=kind, def_text=text, def_id=id_from_text(kind, id)) 25 | 26 | def astext(self): 27 | return self["def_text"] 28 | 29 | 30 | class DefRefNode(nodes.Element): 31 | def __init__(self, kind, source_doc, text): 32 | text, target = parse_target_from_text(text) 33 | 34 | super().__init__( 35 | ref_kind=kind, 36 | ref_source_doc=source_doc, 37 | ref_text=text, 38 | ref_target=id_from_text(kind, target), 39 | ) 40 | 41 | def astext(self): 42 | return self["ref_text"] 43 | 44 | 45 | def parse_target_from_text(text): 46 | if "<" in text and text.endswith(">"): 47 | target_start = text.rfind("<") 48 | target = text[target_start + 1 : len(text) - 1] 49 | text = text[:target_start].rstrip() 50 | elif "[" in text and "]" in text: 51 | target = text[text.find("[") + 1 : text.rfind("]")] 52 | text = text.replace("[", "").replace("]", "") 53 | else: 54 | target = text 55 | 56 | return text, target 57 | 58 | 59 | class DefIdRole(SphinxRole): 60 | def __init__(self, kind): 61 | self.kind = kind 62 | 63 | def run(self): 64 | return [DefIdNode(self.kind, self.text)], [] 65 | 66 | 67 | class DefRefRole(SphinxRole): 68 | def __init__(self, kind): 69 | self.kind = kind 70 | 71 | def run(self): 72 | return [DefRefNode(self.kind, self.env.docname, self.text)], [] 73 | 74 | 75 | class DefinitionsCollector(EnvironmentCollector): 76 | def clear_doc(self, app, env, docname): 77 | """ 78 | Remove all definitions and references contained into a document. 79 | 80 | This is called by Sphinx during incremental builds, either when a 81 | document was removed or when the document has been changed. In the 82 | latter case, process_doc is called after this method. 83 | """ 84 | for kind in KINDS: 85 | storage = get_storage(env, kind) 86 | for item in list(storage.values()): 87 | if item.document == docname: 88 | del storage[item.id] 89 | 90 | def merge_other(self, app, env, docnames, other): 91 | """ 92 | Merge the collected informations from two environments into one. 93 | 94 | Sphinx supports parallel builds, with each process having its own 95 | environment instance, but once each document is processed those 96 | parallel environments need to be merged together. This method does it. 97 | """ 98 | for kind in KINDS: 99 | storage = get_storage(env, kind) 100 | other_storage = get_storage(other, kind) 101 | 102 | for item in other_storage.values(): 103 | if item.document in docnames: 104 | storage[item.id] = item 105 | 106 | def process_doc(self, app, document): 107 | """ 108 | Collect all the definitions and references present in the document. 109 | 110 | This method can expect no existing information about the same document 111 | being stored in the environment, as during incremental rebuilds the 112 | clear_doc method is called ahead of this one. 113 | """ 114 | for kind in KINDS: 115 | storage = get_storage(app.env, kind) 116 | nodes = filter( 117 | lambda node: node["def_kind"] == kind.NAME, 118 | document.findall(DefIdNode), 119 | ) 120 | for item in kind.collect_items_in_document(app, nodes): 121 | storage[item.id] = item 122 | 123 | 124 | class DefinitionsTransform(SphinxTransform): 125 | default_priority = 500 126 | 127 | def apply(self): 128 | for kind in KINDS: 129 | storage = get_storage(self.env, kind) 130 | 131 | for node in self.document.findall(DefIdNode): 132 | if node["def_kind"] != kind.NAME: 133 | continue 134 | item = storage[node["def_id"]] 135 | kind.replace_id_node(self.app, node, item) 136 | 137 | for node in self.document.findall(DefRefNode): 138 | if node["ref_kind"] != kind.NAME: 139 | continue 140 | 141 | if node["ref_target"] in storage: 142 | item = storage[node["ref_target"]] 143 | node.replace_self( 144 | sphinx.util.nodes.make_refnode( 145 | self.app.builder, 146 | node["ref_source_doc"], 147 | item.document, 148 | item.anchor(), 149 | kind.create_ref_node(self.env, node["ref_text"], item), 150 | ) 151 | ) 152 | else: 153 | new = nodes.inline( 154 | "", 155 | "", 156 | kind.create_ref_node(self.env, node["ref_text"], None), 157 | ) 158 | new["classes"].append("spec-missing-ref") 159 | node.replace_self(new) 160 | 161 | 162 | def get_objects(env): 163 | """ 164 | Get objects that will be included in the objects.inv file and in search. 165 | 166 | The return type is a list of tuples of: 167 | * Fully qualified name 168 | * Display name in search 169 | * Object type 170 | * Document name 171 | * Anchor 172 | * Search priority (1: default, 0: important, 2: not important, -1: ignore) 173 | """ 174 | result = [] 175 | for kind in KINDS: 176 | storage = get_storage(env, kind) 177 | for item in storage.values(): 178 | result.append( 179 | ( 180 | item.id, 181 | item.display_name(env), 182 | kind.NAME, 183 | item.document, 184 | item.anchor(), 185 | 1 if item.include_in_search() is not None else -1, 186 | ) 187 | ) 188 | 189 | return result 190 | 191 | 192 | def get_storage(env, kind): 193 | key = f"spec_items_{kind.NAME}" 194 | if not hasattr(env, key): 195 | setattr(env, key, {}) 196 | return getattr(env, key) 197 | 198 | 199 | def get_roles(): 200 | result = {} 201 | for kind in KINDS: 202 | result["d" + kind.ROLE[0]] = DefIdRole(kind.NAME) 203 | result[kind.ROLE[0]] = DefRefRole(kind.NAME) 204 | return result 205 | 206 | 207 | def get_object_types(): 208 | result = {} 209 | for kind in KINDS: 210 | result[kind.NAME] = ObjType(kind.PRETTY_NAME, kind.ROLE) 211 | return result 212 | 213 | 214 | def id_from_text(kind, text): 215 | # We lowercase the text so that capitalization does not matter for 216 | # references and definitions, which is sometimes the case for when they are 217 | # used at the start of a sentence. 218 | # Notably though, this breaks for paragraph ids which are unique randomized 219 | # strings where capitalization matters for hyperlinking, so we don't do so 220 | # for those 221 | return "".join( 222 | c if c.isalnum() else "_" 223 | for c in (text if kind == "paragraph" else text.lower()) 224 | ) 225 | 226 | 227 | def setup(app): 228 | app.add_node(DefIdNode) 229 | app.add_env_collector(DefinitionsCollector) 230 | app.add_post_transform(DefinitionsTransform) 231 | -------------------------------------------------------------------------------- /src/program-structure-and-compilation.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_hdwwrsyunir: 7 | 8 | Program Structure and Compilation 9 | ================================= 10 | 11 | .. _fls_s35hob3i7lr: 12 | 13 | Source Files 14 | ------------ 15 | 16 | .. rubric:: Syntax 17 | 18 | .. syntax:: 19 | 20 | SourceFile ::= 21 | ZeroWidthNoBreakSpace? 22 | Shebang? 23 | InnerAttributeOrDoc* 24 | Item* 25 | 26 | ZeroWidthNoBreakSpace ::= 27 | $$\u{FEFF}$$ 28 | 29 | Shebang ::= 30 | $$#!$$ ~[NewLine]* 31 | 32 | NewLine ::= 33 | $$\n$$ 34 | 35 | .. rubric:: Legality Rules 36 | 37 | :dp:`fls_4vicosdeaqmp` 38 | A :t:`source file` contains the program text consisting of :t:`[inner 39 | attribute]s`, :t:`[inner doc comment]s`, and :t:`[item]s`. The location of a 40 | :t:`source file` is tool defined. 41 | 42 | :dp:`fls_ann3cha1xpek` 43 | A :s:`Shebang` does not have an effect on the compilation. 44 | 45 | .. _fls_e9hwvqsib5d5: 46 | 47 | Modules 48 | ------- 49 | 50 | .. rubric:: Syntax 51 | 52 | .. syntax:: 53 | 54 | ModuleDeclaration ::= 55 | $$unsafe$$? $$mod$$ Name ModuleSpecification 56 | 57 | ModuleSpecification ::= 58 | InlineModuleSpecification 59 | | OutlineModuleSpecification 60 | 61 | InlineModuleSpecification ::= 62 | $${$$ 63 | InnerAttributeOrDoc* 64 | Item* 65 | $$}$$ 66 | 67 | OutlineModuleSpecification ::= 68 | $$;$$ 69 | 70 | .. rubric:: Legality Rules 71 | 72 | :dp:`fls_odd1hj3y1mgu` 73 | A :t:`module` is a container for zero or more :t:`[item]s`. 74 | 75 | :dp:`fls_whgv72emrm47` 76 | The ``unsafe`` :t:`keyword` of a :t:`module` is rejected, but may still 77 | be consumed by :t:`[macro]s`. 78 | 79 | :dp:`fls_qypjjpcf8uwq` 80 | An :t:`inline module` is a :t:`module` with an :s:`InlineModuleSpecification`. 81 | 82 | :dp:`fls_cavwpr1ybk37` 83 | An :t:`outline module` is a :t:`module` with an :s:`OutlineModuleSpecification`. 84 | 85 | :dp:`fls_plepew2319g4` 86 | An :t:`outline module` loads a :t:`source file` and considers the text of the 87 | :t:`source file` to be inlined within the context of the :t:`outline module`. 88 | 89 | :dp:`fls_1aruwps62c4p` 90 | The location of a :t:`module` :t:`source file` can be specified using 91 | :t:`attribute` :c:`path`. 92 | 93 | .. rubric:: Examples 94 | 95 | .. code-block:: rust 96 | 97 | #[path = "path/to/module"] 98 | pub mod module { 99 | #![allow(dead_code)] 100 | 101 | struct Struct; 102 | pub mod other; 103 | } 104 | 105 | .. _fls_maw4u1o8q37u: 106 | 107 | Crates 108 | ------ 109 | 110 | .. rubric:: Legality Rules 111 | 112 | :dp:`fls_qwghk79ok5h0` 113 | A :t:`crate` is a unit of compilation and linking that contains a tree of 114 | nested :t:`[module]s`. 115 | 116 | :dp:`fls_unxalgMqIr3v` 117 | The :t:`crate type` of a :t:`crate` is the value of the :t:`attribute` 118 | ``crate_type`` of a :t:`crate` or the value of ``--crate-type`` flag passed to 119 | the tool compiling the :t:`crate`. 120 | 121 | :dp:`fls_e7jGvXvTsFpC` 122 | The :t:`crate type` of a :t:`crate` if not specified is ``bin``. 123 | 124 | :dp:`fls_kQiJPwb2Hjcc` 125 | A :t:`crate` may be subject to multiple :t:`[crate type]s`, treating each type 126 | as a separate :t:`crate`. 127 | 128 | :dp:`fls_9ub6ks8qrang` 129 | A :t:`binary crate` is a :t:`crate` whose :t:`crate type` is ``bin``. 130 | 131 | :dp:`fls_OyFwBtDGVimT` 132 | A :t:`binary crate` that is not subject to :t:`attribute` ``no_main`` shall have 133 | a :t:`function` in scope of its :t:`crate root module` under the :t:`name` 134 | ``main`` with a :t:`main function signature`. 135 | 136 | :dp:`fls_jQqXxPyND1ds` 137 | The :t:`function` in scope of a :t:`binary crate`'s :t:`crate root module` under 138 | the :t:`name` ``main`` with a :t:`main function signature` is the :t:`binary 139 | crate`'s :t:`program entry point`. 140 | 141 | :dp:`fls_d9nn4yuiw1ja` 142 | A :t:`library crate` is a :t:`crate` whose :t:`crate type` is ``lib``, ``rlib``, 143 | ``staticlib``, ``dylib``, or ``cdylib``. 144 | 145 | :dp:`fls_Mf62VqAhoZ3c` 146 | A :t:`proc-macro crate` is a :t:`crate` whose :t:`crate type` is ``proc-macro``. 147 | 148 | :dp:`fls_RJJmN4tP7j4m` 149 | A :t:`proc-macro crate` shall not declare :t:`[item]s` in its :t:`crate root 150 | module` with :t:`public visibility` unless the :t:`item` is a :t:`procedural 151 | macro`. 152 | 153 | :dp:`fls_h93C3wfbAoz1` 154 | Only a :t:`proc-macro crate` shall declare :t:`[procedural macro]s`. 155 | 156 | .. _fls_gklst7joeo33: 157 | 158 | Crate Imports 159 | ------------- 160 | 161 | .. rubric:: Syntax 162 | 163 | .. syntax:: 164 | 165 | ExternalCrateImport ::= 166 | $$extern$$ $$crate$$ CrateIndication Renaming? $$;$$ 167 | 168 | CrateIndication ::= 169 | Identifier 170 | | $$self$$ 171 | 172 | .. rubric:: Legality Rules 173 | 174 | :dp:`fls_d0pa807s5d5h` 175 | A :t:`crate import` specifies a required dependency on an external :t:`crate`. 176 | 177 | :dp:`fls_vfam3wzeAiah` 178 | A :t:`crate indication` is a :t:`construct` that indicates a :t:`crate`. 179 | 180 | :dp:`fls_ft860vkz0lkc` 181 | A :t:`crate import` binds an external :t:`crate` to its :t:`crate indication`. 182 | 183 | :dp:`fls_k90qtnf8kgu1` 184 | :t:`Crate indication` ``self`` shall require a :t:`renaming`. 185 | 186 | :dp:`fls_siv8bl6s2ndu` 187 | A :t:`crate import` with a :t:`renaming` with an :t:`identifier` binds the 188 | external :t:`crate` to a local :t:`name` and introduces the local :t:`name` into 189 | the enclosing :t:`scope`. 190 | 191 | :dp:`fls_7vz5n3x6jo1s` 192 | If a :t:`crate import` appears at the :t:`crate root module`, then the 193 | :t:`crate indication` is added to the :t:`external prelude`. 194 | 195 | :dp:`fls_3bgpc8m8yk4p` 196 | A :t:`crate indication` shall resolve to an external :t:`crate`. The process of 197 | resolving a :t:`crate indication` to an external :t:`crate` is tool-defined. 198 | 199 | .. _fls_5w50kf83oo1u: 200 | 201 | Compilation Roots 202 | ----------------- 203 | 204 | .. rubric:: Legality Rules 205 | 206 | :dp:`fls_fhiqvgdamq5` 207 | A :t:`crate root module` is the root of the nested :t:`module` tree of a 208 | :t:`crate`. 209 | 210 | :dp:`fls_tk8tl2e0a34` 211 | A tool can define a :t:`crate root module` for a single :t:`crate`. 212 | 213 | :dp:`fls_bsyfxdk3ap1t` 214 | A :t:`compilation root` is an input to a compilation performed by a tool. A 215 | :t:`crate root module` is a :t:`compilation root`. 216 | 217 | .. _fls_u1afezy1ye99: 218 | 219 | Conditional Compilation 220 | ----------------------- 221 | 222 | .. rubric:: Legality Rules 223 | 224 | :dp:`fls_9stc6nul6vq9` 225 | :t:`Conditionally-compiled source code` is source code that may or may 226 | not be considered a part of a Rust program depending on 227 | :t:`[configuration predicate]s`. 228 | 229 | :dp:`fls_a0u9nnaf6drz` 230 | :t:`Conditional compilation` is the process of compiling 231 | :t:`conditionally-compiled source code`. 232 | 233 | :dp:`fls_pf1v89h7pjhh` 234 | A :t:`construct` subject to :t:`attribute` :c:`cfg` where the related 235 | :t:`configuration predicate` evaluates to ``false`` is not considered part of a 236 | Rust program. 237 | 238 | :dp:`fls_y56RGw3cbFex` 239 | A :t:`crate root module` subject to :t:`attribute` :c:`cfg` where the related 240 | :t:`configuration predicate` evaluates to ``false`` is considered empty except 241 | for all :t:`[attribute]s` up to the invoked :t:`attribute` :c:`cfg`. 242 | 243 | :dp:`fls_h6b1fuw4nvi1` 244 | An :t:`attribute` :c:`cfg_attr` where the related :t:`configuration predicate` 245 | evaluates to ``false`` is not considered part of a Rust program. 246 | 247 | 248 | .. _fls_8JB3SJqamdpU: 249 | 250 | Program Entry Point 251 | ------------------- 252 | 253 | .. rubric:: Legality Rules 254 | 255 | :dp:`fls_dp64b08em9BJ` 256 | A :t:`program entry point` is a :t:`function` that is invoked at the start of 257 | a Rust program. 258 | 259 | :dp:`fls_sbGnkm8Ephiu` 260 | A :t:`main function signature` is a :t:`function signature` subject to the 261 | following restrictions: 262 | 263 | * :dp:`fls_o4fxok23134r` 264 | It lacks :t:`[function qualifier]s` ``async`` and ``unsafe``, 265 | 266 | * :dp:`fls_bk755pvc1l53` 267 | Its :t:`ABI` is Rust, 268 | 269 | * :dp:`fls_a3je4wc53bmo` 270 | It lacks :t:`[generic parameter]s`, 271 | 272 | * :dp:`fls_w8q15zp7kyl0` 273 | It lacks :t:`[function parameter]s`, 274 | 275 | * :dp:`fls_4psnfphsgdek` 276 | It lacks a :t:`return type`, 277 | 278 | * :dp:`fls_m7xfrhqif74` 279 | It lacks a :t:`where clause`, 280 | 281 | * :dp:`fls_qq9fzrw4aykd` 282 | It has a :t:`function body`. 283 | -------------------------------------------------------------------------------- /src/ffi.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_osd6c4utyjb3: 7 | 8 | FFI 9 | === 10 | 11 | .. rubric:: Legality Rules 12 | 13 | :dp:`fls_djlglv2eaihl` 14 | :t:`Foreign Function Interface` or :t:`FFI` employs :t:`ABI`, 15 | :t:`[attribute]s`, :t:`[external block]s`, :t:`[external function]s`, linkage, 16 | and :t:`type` :t:`layout` to interface a Rust program with foreign code. 17 | 18 | :dp:`fls_k1hiwghzxtfa` 19 | The following :t:`[attribute]s` affect :t:`FFI`: 20 | 21 | * :dp:`fls_3cgtdk4698hm` 22 | :t:`Attribute` :c:`export_name`. 23 | 24 | * :dp:`fls_shzmgci4f7o5` 25 | :t:`Attribute` :c:`link`. 26 | 27 | * :dp:`fls_m7x5odt4nb23` 28 | :t:`Attribute` :c:`link_section` 29 | 30 | * :dp:`fls_4akfvpq1yg4g` 31 | :t:`Attribute` :c:`no_mangle`. 32 | 33 | * :dp:`fls_9d8v0xeyi0f` 34 | :t:`Attribute` :c:`used`. 35 | 36 | .. _fls_usgd0xlijoxv: 37 | 38 | ABI 39 | --- 40 | 41 | .. rubric:: Syntax 42 | 43 | .. syntax:: 44 | 45 | AbiSpecification ::= 46 | $$extern$$ AbiKind? 47 | 48 | AbiKind ::= 49 | RawStringLiteral 50 | | StringLiteral 51 | 52 | .. rubric:: Legality Rules 53 | 54 | :dp:`fls_xangrq3tfze0` 55 | :t:`Application Binary Interface` or :t:`ABI` is a set of conventions that 56 | dictate how data and computation cross language boundaries. 57 | 58 | :dp:`fls_2w0xi6rxw3uz` 59 | The :t:`ABI kind` indicates the :t:`ABI` of a :t:`construct`. 60 | 61 | :dp:`fls_9zitf1fvvfk8` 62 | The following :t:`[ABI]s` are supported: 63 | 64 | * :dp:`fls_x7ct9k82fpgn` 65 | ``extern "C"`` - The default :t:`ABI` of :t:`C` code, referred to as 66 | :dt:`extern C ABI`. 67 | 68 | * :dp:`fls_LfjvLXvI6TFL` 69 | ``extern "C-unwind"`` - The same as ``extern "C"`` with the addition that 70 | unwinding across FFI is permitted. 71 | 72 | * :dp:`fls_a2d8ltpgtvn6` 73 | ``extern "Rust"`` - The default :t:`ABI` of a Rust program, referred to as 74 | :dt:`Rust ABI`. 75 | 76 | * :dp:`fls_8m7pc3riokst` 77 | ``extern "system"`` - The operating system-dependent :t:`ABI`. 78 | 79 | * :dp:`fls_NQAzj5ai1La5` 80 | ``extern "system-unwind"`` - The same as ``extern "system"`` with the 81 | addition that unwinding across FFI is permitted. 82 | 83 | :dp:`fls_r2drzo3dixe4` 84 | A :t:`function` without an explicit :t:`ABI` has implicit :t:`Rust ABI`, unless 85 | it appears within an :t:`external block`. 86 | 87 | :dp:`fls_z2kzyin8dyr7` 88 | A :t:`function` with an :t:`ABI` but without a specified :t:`ABI kind` has 89 | implicit :t:`extern C ABI`. 90 | 91 | .. rubric:: Implementation Permissions 92 | 93 | :dp:`fls_j6pqchx27ast` 94 | A tool is allowed to specify additional :t:`[ABI]s`. These :t:`[ABI]s` may 95 | include, but may not be limited to, the following: 96 | 97 | * :dp:`fls_dbbfqaqa80r8` 98 | ``extern "aapcs"`` - The soft-float ABI for 32-bit ARM targets. 99 | 100 | * :dp:`fls_UippZpUyYpHl` 101 | ``extern "aapcs-unwind"`` - The same as ``extern "aapcs"`` 102 | with the addition that unwinding across FFI is permitted. 103 | 104 | * :dp:`fls_36qrs2fxxvi7` 105 | ``extern "cdecl"`` - The x86_32 :t:`ABI` of :t:`C` code. 106 | 107 | * :dp:`fls_CIyK8BYzzo26` 108 | ``extern "cdecl-unwind"`` - The same as ``extern "cdecl"`` 109 | with the addition that unwinding across FFI is permitted. 110 | 111 | * :dp:`fls_6rtj6rwqxojh` 112 | ``extern "fastcall"`` - The ``fastcall`` :t:`ABI` that corresponds to MSVC's 113 | ``__fastcall`` and GCC and clang's ``__attribute__((fastcall))``. 114 | 115 | * :dp:`fls_d3nmpc5mtg27` 116 | ``extern "stdcall"`` - The x86_32 :t:`ABI` of the Win32 API. 117 | 118 | * :dp:`fls_7t7yxh94wnbl` 119 | ``extern "sysv64"`` - The x86_64 non-Windows :t:`ABI` of :t:`C` code. 120 | 121 | * :dp:`fls_ccFdnlX5HIYk` 122 | ``extern "sysv64-unwind"`` - The same as ``extern "sysv64"`` 123 | with the addition that unwinding across FFI is permitted. 124 | 125 | * :dp:`fls_sxj4vy39sj4g` 126 | ``extern "vectorcall"`` - The ``vectorcall`` :t:`ABI` that corresponds to 127 | MSVC's ``__vectorcall`` and clang's ``__attribute__((vectorcall))``. 128 | 129 | * :dp:`fls_tyjs1x4j8ovp` 130 | ``extern "win64"`` - The x86_64 Windows :t:`ABI` of :t:`C` code. 131 | 132 | * :dp:`fls_xrCRprWS13R1` 133 | ``extern "win64-unwind"`` - The same as ``extern "win64"`` 134 | with the addition that unwinding across FFI is permitted. 135 | 136 | * :dp:`fls_JHlqXjn4Sf07` 137 | ``extern "efiapi"`` - The :t:`ABI` for `UEFI `_. 138 | 139 | .. rubric:: Undefined Behavior 140 | 141 | :dp:`fls_M4LqHf8hbPA8` 142 | It is undefined behavior when a foreign exception crosses a 143 | :t:`foreign function interface` boundary with an :t:`ABI` that does not end in 144 | ``-unwind``. 145 | 146 | .. rubric:: Examples 147 | 148 | .. code-block:: rust 149 | 150 | extern 151 | extern "C" 152 | 153 | .. _fls_tmoh3y9oyqsy: 154 | 155 | External Blocks 156 | --------------- 157 | 158 | .. rubric:: Syntax 159 | 160 | .. syntax:: 161 | 162 | ExternalBlock ::= 163 | $$unsafe$$? $$extern$$ AbiKind? $${$$ 164 | InnerAttributeOrDoc* 165 | ExternItem* 166 | $$}$$ 167 | 168 | ExternItem ::= 169 | OuterAttributeOrDoc* (ExternalItemWithVisibility | TerminatedMacroInvocation) 170 | 171 | ExternalItemWithVisibility ::= 172 | VisibilityModifier? ( 173 | FunctionDeclaration 174 | | StaticDeclaration 175 | ) 176 | 177 | .. rubric:: Legality Rules 178 | 179 | :dp:`fls_4dje9t5y2dia` 180 | An :t:`external block` is a :t:`construct` that provides the declarations of 181 | :t:`[external function]s` and :t:`[external static]s` as unchecked imports. 182 | 183 | :dp:`fls_8ltVLtAfvy0m` 184 | An :t:`unsafe external block` is an :t:`external block` subject to keyword ``unsafe``. 185 | 186 | :dp:`fls_Nz0l16hMxqTd` 187 | The :t:`ABI` of an :t:`external block` is determined as follows: 188 | 189 | * :dp:`fls_4XOoiFloXM7t` 190 | If the :t:`external block` specifies an :s:`AbiKind`, then the :t:`ABI` is the specified :s:`AbiKind`. 191 | 192 | * :dp:`fls_PBsepNHImJKH` 193 | Otherwise the :t:`ABI` is the :t:`extern C ABI`. 194 | 195 | .. rubric:: Examples 196 | 197 | .. code-block:: rust 198 | 199 | extern "C" { 200 | static MAX_LENGTH: size_t; 201 | 202 | fn compress 203 | (input: *const u8, 204 | input_length: size_t, 205 | compressed: *mut u8, 206 | compressed_length: *mut size_t) -> c_int; 207 | fn log(msg: *const c_char, ...); 208 | } 209 | 210 | .. _fls_yztwtek0y34v: 211 | 212 | External Functions 213 | ------------------ 214 | 215 | .. rubric:: Legality Rules 216 | 217 | :dp:`fls_v24ino4hix3m` 218 | An :t:`external function` is an unchecked import of a foreign :t:`function`. 219 | 220 | :dp:`fls_l88r9fj82650` 221 | An :t:`external function` shall be invoked from an :t:`unsafe context` unless it is defined in an :t:`unsafe external block` and subject to :s:`ItemSafety` with keyword ``safe``. 222 | 223 | :dp:`fls_qwchgvvnp0qe` 224 | An :t:`external function` shall not specify a :s:`FunctionQualifierList`. 225 | 226 | :dp:`fls_w00qi1gx204e` 227 | An :t:`external function` inherits the :t:`ABI` of its enclosing 228 | :t:`external block`. 229 | 230 | :dp:`fls_m7tu4w4lk8v` 231 | An :t:`external function` shall not specify a :s:`GenericParameterList` 232 | containing :t:`[constant parameter]s` or :t:`[type parameter]s`. 233 | 234 | :dp:`fls_rdu4723vp0oo` 235 | An :t:`external function` shall not specify a :s:`FunctionBody`. 236 | 237 | :dp:`fls_9div9yusw64h` 238 | An :t:`external function` shall not specify :t:`[pattern]s` other than 239 | :t:`[identifier pattern]s` and :t:`[underscore pattern]s`. 240 | 241 | :dp:`fls_juob30rst11r` 242 | Only the last parameter :s:`FunctionParameter` of an :t:`external function` may 243 | specify a :s:`FunctionParameterVariadicPart`. 244 | 245 | .. _fls_s4yt19sptl7d: 246 | 247 | External Statics 248 | ---------------- 249 | 250 | .. rubric:: Legality Rules 251 | 252 | :dp:`fls_8ddsytjr4il6` 253 | An :t:`external static` is an import of a foreign :t:`variable`. 254 | 255 | :dp:`fls_H0cg9XMaGz0y` 256 | An :t:`external static` inherits the :t:`ABI` of its enclosing 257 | :t:`external block`. 258 | 259 | :dp:`fls_fo9with6xumo` 260 | An :t:`external static` shall be referenced from an :t:`unsafe context` unless it is defined in an :t:`unsafe external block` and subject to :s:`ItemSafety` with keyword ``safe``. 261 | 262 | :dp:`fls_tr7purzcldn0` 263 | An :t:`external static` shall not specify a :t:`static initializer`. 264 | 265 | .. rubric:: Dynamic Semantics 266 | 267 | :dp:`fls_en2h09ehj0j3` 268 | An :t:`immutable` :t:`external static` shall be initialized before Rust code 269 | is executed. 270 | -------------------------------------------------------------------------------- /src/implementations.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_fk2m2irwpeof: 7 | 8 | Implementations 9 | =============== 10 | 11 | .. rubric:: Syntax 12 | 13 | .. syntax:: 14 | 15 | Implementation ::= 16 | InherentImplementation 17 | | TraitImplementation 18 | 19 | InherentImplementation ::= 20 | $$impl$$ GenericParameterList? ImplementingType WhereClause? ImplementationBody 21 | 22 | TraitImplementation ::= 23 | $$unsafe$$? $$impl$$ GenericParameterList? $$!$$? ImplementedTrait $$for$$ ImplementingType WhereClause? ImplementationBody 24 | 25 | ImplementingType ::= 26 | TypeSpecification 27 | 28 | ImplementedTrait ::= 29 | TypePath 30 | 31 | ImplementationBody ::= 32 | $${$$ 33 | InnerAttributeOrDoc* 34 | AssociatedItem* 35 | $$}$$ 36 | 37 | .. rubric:: Legality Rules 38 | 39 | :dp:`fls_ivxpoxggy7s6` 40 | An :t:`implementation` is an :t:`item` that supplements an 41 | :t:`implementing type` by extending its functionality. 42 | 43 | :dp:`fls_yopmjbnw8tbl` 44 | An :t:`implementing type` is the :t:`type` that the :t:`[associated item]s` of 45 | an :t:`implementation` are associated with. 46 | 47 | :dp:`fls_eIHc8Y9fBtr0` 48 | Within an :t:`implementation`, the :t:`type` :c:`Self` acts as a :t:`type alias` 49 | for the :t:`implementing type`. 50 | 51 | :dp:`fls_Mcpdzzcw43M7` 52 | An :t:`implementation body` is a :t:`construct` that encapsulates the 53 | :t:`[associated item]s`, :t:`[inner attribute]s`, and 54 | :t:`[inner doc comment]s` of an :t:`implementation`. 55 | 56 | :dp:`fls_v0n0bna40dqr` 57 | An :t:`inherent implementation` is an :t:`implementation` that adds direct 58 | functionality. 59 | 60 | :dp:`fls_797etpdk5dyb` 61 | :t:`[Inherent implementation]s` of the same :t:`implementing type` shall be 62 | defined within the same :t:`crate`. 63 | 64 | :dp:`fls_ry3an0mwb63g` 65 | A :t:`trait implementation` is an :t:`implementation` that adds functionality 66 | specified by a :t:`trait`. 67 | 68 | :dp:`fls_8pwr7ibvhmhu` 69 | An :t:`unsafe trait implementation` is a :t:`trait implementation` subject to 70 | :t:`keyword` ``unsafe``. 71 | 72 | :dp:`fls_47x0ep8of8wr` 73 | An :t:`implemented trait` is a :t:`trait` whose functionality has been 74 | implemented by an :t:`implementing type`. 75 | 76 | :dp:`fls_agitlryvyc16` 77 | The :t:`type path` of a :t:`trait implementation` shall resolve to a :t:`trait`. 78 | 79 | :dp:`fls_mx5xjcejwa6u` 80 | A :t:`trait implementation` shall be an :t:`unsafe trait implementation` if and 81 | only if it implements an :t:`unsafe trait`. 82 | 83 | :dp:`fls_z78dg261oob6` 84 | :t:`[Trait implementation]s` are subject to :t:`implementation coherence` and 85 | :t:`implementation conformance`. 86 | 87 | :dp:`fls_89yNjGNB7KI3` 88 | :t:`[Inherent implementation]s` of the same :t:`implementing type` shall not 89 | define more than one :t:`associated item` with the same :t:`name` in the same 90 | :t:`namespace`. 91 | 92 | .. rubric:: Examples 93 | 94 | .. code-block:: rust 95 | 96 | trait Shape { 97 | fn area(self) -> f64; 98 | } 99 | 100 | :dp:`fls_yuyesijndu9n` 101 | ``Circle`` is an implementing type. 102 | 103 | .. code-block:: rust 104 | 105 | struct Circle { 106 | radius: f64 107 | } 108 | 109 | :dp:`fls_o62i75sjzp9y` 110 | The following is an inherent implementation: 111 | 112 | .. code-block:: rust 113 | 114 | impl Circle { 115 | fn set_radius(mut self, new_radius: f64) { 116 | self.radius = new_radius; 117 | } 118 | } 119 | 120 | :dp:`fls_a2utf0tmuhy4` 121 | The following is a trait implementation: 122 | 123 | .. code-block:: rust 124 | 125 | impl Shape for Circle { 126 | fn area(self) -> f64 { 127 | self.radius.powi(2) * std::f64::consts::PI 128 | } 129 | } 130 | 131 | .. _fls_46ork6fz5o2e: 132 | 133 | Implementation Coherence 134 | ------------------------ 135 | 136 | .. rubric:: Legality Rules 137 | 138 | :dp:`fls_fv1l4yjuut7p` 139 | A :t:`trait implementation` exhibits :t:`implementation coherence` when it is 140 | valid and does not overlap with another :t:`trait implementation`. 141 | 142 | :dp:`fls_swdusjwzgksx` 143 | Two :t:`[trait implementation]s` of the same :t:`implemented trait` overlap when 144 | the intersection of the :t:`[implementing type]s` is non-empty. 145 | 146 | :dp:`fls_ir7hp941ky8t` 147 | Given :t:`trait implementation` 148 | ``impl Trait for T0``, the 149 | :t:`trait implementation` is considered valid when 150 | 151 | * :dp:`fls_3tbm20k2ixol` 152 | ``Trait`` is :t:`fundamental` or a :t:`local trait`, or 153 | 154 | * :dp:`fls_lscc9ileg3gm` 155 | All of 156 | 157 | * :dp:`fls_9klwbsh3vlxu` 158 | At least one of :t:`[type]s` ``T0, T1, .., TN`` is :T:`fundamental` or a 159 | :t:`local type`, and 160 | 161 | * :dp:`fls_9gmc1tcscq9v` 162 | No :t:`type parameter` of ``P1, P2, .., PN`` that is not used in another 163 | :t:`type` may appear in the :t:`non-[local type]s` and 164 | :t:`non-[fundamental]` :t:`[type]s` of ``T0, T1, .., TN``. 165 | 166 | :dp:`fls_UkQhjEWSJpDq` 167 | A :t:`trait` or :t:`type` is :t:`fundamental` when its 168 | :t:`implementation coherence` rules are relaxed and the :t:`trait` or :t:`type` 169 | is always treated as if it was a :t:`local trait` or a :t:`local type`. 170 | 171 | :dp:`fls_fSybUG40hA5r` 172 | The following :t:`[type]s` are :t:`fundamental`: 173 | 174 | * :dp:`fls_z8APl0CEF7a0` 175 | :t:`[reference type]s` 176 | 177 | * :dp:`fls_RJJafhpVsi6M` 178 | :std:`core::pin::Pin` 179 | 180 | .. 181 | also `alloc::boxed::Box` 182 | 183 | :dp:`fls_dtUJxhNkl8Ty` 184 | The following :t:`[trait]s` are :t:`fundamental`: 185 | 186 | * :dp:`fls_zJKovQrXQWdU` 187 | :std:`core::ops::Fn` 188 | 189 | * :dp:`fls_V6R8yQtsqNyv` 190 | :std:`core::ops::FnMut` 191 | 192 | * :dp:`fls_CpC6XQN1iWqU` 193 | :std:`core::ops::FnOnce` 194 | 195 | * :dp:`fls_dj7YGw4e4i4H` 196 | :std:`core::marker::Sized` 197 | 198 | :dp:`fls_koy70k770ayu` 199 | A :t:`trait implementation` shall be coherent. 200 | 201 | .. _fls_e1pgdlv81vul: 202 | 203 | Implementation Conformance 204 | -------------------------- 205 | 206 | .. rubric:: Legality Rules 207 | 208 | :dp:`fls_YyUSuAYG4lX6` 209 | A :t:`trait implementation` exhibits :t:`implementation conformance` when it 210 | satisfies the constraints of its :t:`implemented trait`. 211 | 212 | :dp:`fls_v31idwjau90d` 213 | An :t:`associated trait constant` is conformant with an :t:`associated constant` 214 | of an :t:`implemented trait` when 215 | 216 | * :dp:`fls_k3wfh5japmyw` 217 | The :t:`[name]s` of both :t:`[associated constant]s` are the same, and 218 | 219 | * :dp:`fls_11qrqfuc3rmh` 220 | The :t:`type` of the :t:`associated constant` in the :t:`implementation` is a 221 | :t:`subtype` of the :t:`type` of the :t:`associated trait constant`. 222 | 223 | :dp:`fls_qmhduwunxww0` 224 | An :t:`associated trait function` is conformant with an :t:`associated function` 225 | of an :t:`implemented trait` when 226 | 227 | * :dp:`fls_2500ivh0cc3y` 228 | The :t:`function signature` of the :t:`associated function` of the 229 | :t:`implemented trait` is a :t:`subtype` of the :t:`function signature` of 230 | the :t:`associated trait function`, and 231 | 232 | * :dp:`fls_18gimgfy0kw9` 233 | The :t:`[bound]s` of the :t:`associated function` of the 234 | :t:`implemented trait` are more general that the :t:`[bound]s` of the 235 | :t:`associated trait function`. 236 | 237 | :dp:`fls_fi4qmauirlsm` 238 | An :t:`associated type` of a :t:`trait implementation` is conformant with an 239 | :t:`associated type` of an :t:`implemented trait` when 240 | 241 | * :dp:`fls_2s8lh3k4rw6u` 242 | The :t:`[name]s` of both :t:`[type]s` are the same, and 243 | 244 | * :dp:`fls_bb874uu2alt3` 245 | The :t:`type specification` of the :t:`associated type` of the 246 | :t:`implemented trait` conforms to the :t:`[bound]s` of the 247 | :t:`associated type` of the :t:`trait implementation`. 248 | 249 | :dp:`fls_so8em6rphkhv` 250 | A :t:`trait implementation` is conformant with an :t:`implemented trait` when: 251 | 252 | * :dp:`fls_ldu9bmb9cy10` 253 | The :t:`trait implementation` has a conformant :t:`associated constant` 254 | for each :t:`associated constant` of the :t:`implemented trait`, unless the 255 | :t:`associated constant` of the :t:`implemented trait` has a default value, 256 | and 257 | 258 | * :dp:`fls_5cr6un2gzdft` 259 | The :t:`trait implementation` has a conformant :t:`associated function` 260 | for each :t:`associated function` of the :t:`implemented trait`, unless 261 | the :t:`associated function` of the :t:`implemented trait` has a default 262 | implementation in the :t:`implemented trait`, and 263 | 264 | * :dp:`fls_pshfe3ioh0mg` 265 | The :t:`trait implementation` has a conformant :t:`associated type` for each 266 | :t:`associated type` of the :t:`implemented trait`. 267 | 268 | :dp:`fls_8yq1g7nzv9px` 269 | A :t:`trait implementation` shall be conformant. 270 | 271 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | 37 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 38 | 39 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | 41 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 42 | 43 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | 57 | APPENDIX: How to apply the Apache License to your work. 58 | 59 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 60 | 61 | Copyright [yyyy] [name of copyright owner] 62 | 63 | Licensed under the Apache License, Version 2.0 (the "License"); 64 | you may not use this file except in compliance with the License. 65 | You may obtain a copy of the License at 66 | 67 | http://www.apache.org/licenses/LICENSE-2.0 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. 74 | -------------------------------------------------------------------------------- /src/values.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. _fls_94a8v54bufn8: 7 | 8 | Values 9 | ====== 10 | 11 | .. rubric:: Legality Rules 12 | 13 | :dp:`fls_buyaqara7am4` 14 | A :t:`value` is either a :t:`literal` or the result of a computation, that may 15 | be stored in a memory location, and interpreted based on some :t:`type`. 16 | 17 | :dp:`fls_CUJyMj0Sj8NS` 18 | An :dt:`allocated object` is a :t:`value` stored at some memory address. 19 | 20 | :dp:`fls_kaomYy0Ml4Nh` 21 | The :dt:`base address` of an :t:`allocated object` is the memory address where 22 | the object is stored. 23 | 24 | :dp:`fls_B5cmkWfD5GNt` 25 | An :t:`[allocated object]s` :dt:`memory size` is the number of bytes the object 26 | spans in memory from its :t:`base address`. 27 | 28 | :dp:`fls_rixdyyc525xp` 29 | Two :t:`[value]s` :t:`overlap` when 30 | 31 | * :dp:`fls_m6ctqq70vcxr` 32 | Both :t:`[value]s` are the same, or 33 | 34 | * :dp:`fls_s231d18x5eay` 35 | One :t:`value` is of an :t:`abstract data type` and the other denotes a 36 | :t:`field` of the same :t:`value`, or 37 | 38 | * :dp:`fls_dfr4yqo93fsn` 39 | One :t:`value` denotes an :t:`array` and the other denotes an element of the 40 | same :t:`value`, or 41 | 42 | * :dp:`fls_eoak5mdl6ma` 43 | Both :t:`[value]s` are elements of the same :t:`array`. 44 | 45 | .. rubric:: Undefined Behavior 46 | 47 | :dp:`fls_6lg0oaaopc26` 48 | It is undefined behavior to create a :t:`value` from uninitialized memory unless 49 | the :t:`type` of the :t:`value` is a :t:`union type`. 50 | 51 | :dp:`fls_oqhQ62mDLckN` 52 | It is undefined behavior to create an :t:`allocated object` at :t:`base address` 53 | :c:`null`. 54 | 55 | :dp:`fls_uhwpuv6cx4ip` 56 | It is undefined behavior to create an :t:`allocated object` with :t:`memory 57 | size` ``size`` at a :t:`base address` ``base`` where ``base + size`` is greater 58 | than the architectures maximum :c:`usize` value. 59 | 60 | :dp:`fls_xuuFKmm181bs` 61 | It is undefined behavior to create an :t:`allocated object` with :t:`memory 62 | size` ``size`` where ``size`` is greater than the architectures maximum 63 | :c:`isize` value. 64 | 65 | .. _fls_ixjc5jaamx84: 66 | 67 | Constants 68 | --------- 69 | 70 | .. rubric:: Syntax 71 | 72 | .. syntax:: 73 | 74 | ConstantDeclaration ::= 75 | $$const$$ (Name | $$_$$) TypeAscription ConstantInitializer? $$;$$ 76 | 77 | ConstantInitializer ::= 78 | $$=$$ Expression 79 | 80 | .. rubric:: Legality Rules 81 | 82 | :dp:`fls_5o5iu4j8in4l` 83 | A :t:`constant` is an :t:`immutable` :t:`value expression` whose uses are substituted by 84 | the :t:`value`. 85 | 86 | :dp:`fls_3mhj0kkupwuz` 87 | An :t:`unnamed constant` is a :t:`constant` declared with character 0x5F (low 88 | line). 89 | 90 | :dp:`fls_ka4y2yd100dx` 91 | The :t:`type specification` of a :t:`constant` shall have ``'static`` 92 | :t:`lifetime`. 93 | 94 | :dp:`fls_vt9tlkd676ql` 95 | The :t:`type` of a :t:`constant` shall implement the :std:`core::marker::Sized` 96 | :t:`trait`. 97 | 98 | :dp:`fls_ndmfqxjpvsqy` 99 | A :t:`constant initializer` is a :t:`construct` that provides the :t:`value` of 100 | its related :t:`constant`. 101 | 102 | :dp:`fls_6rxwbbhf5tc5` 103 | A :t:`constant` shall have a :t:`constant initializer`, unless it is an 104 | :t:`associated trait constant`. 105 | 106 | :dp:`fls_vnc3ttnid1qr` 107 | The :t:`expression` of a :t:`constant initializer` shall be a 108 | :t:`constant expression`. 109 | 110 | :dp:`fls_deuo1pn8cjd6` 111 | The value of a :t:`constant` is determined by evaluating its 112 | :t:`constant initializer`. 113 | 114 | :dp:`fls_ooOYxhVh8hZo` 115 | After :t:`type coercion`, the value of the constant cannot contain any 116 | :t:`[mutable reference]s`, except when 117 | 118 | - :dp:`fls_zkNFeBLy80UA` 119 | The :t:`mutable reference` is contained within an :t:`external static`, or 120 | 121 | - :dp:`fls_VhzGfnWg7YrG` 122 | The :t:`mutable reference` is contained within a :t:`mutable static`, or 123 | 124 | - :dp:`fls_qC6L0km0ZMFI` 125 | The :t:`mutable reference` is contained within a :t:`static` 126 | whose type is subject to :t:`interior mutability`, or 127 | 128 | - :dp:`fls_ibYKKQdB2tDn` 129 | The :t:`mutable reference` is contained within an :t:`union`, or 130 | 131 | - :dp:`fls_dQdSxf8kOgbi` 132 | The :t:`referent` is a value of a :t:`zero-sized type`. 133 | 134 | .. rubric:: Dynamic Semantics 135 | 136 | :dp:`fls_xezt9hl069h4` 137 | The :t:`elaboration` of a :t:`constant` evaluates its :t:`constant initializer`. 138 | 139 | :dp:`fls_ndobth7s92if` 140 | A :t:`path` that refers to a :t:`constant` is replaced with the :t:`value` of 141 | the :t:`constant`. 142 | 143 | .. rubric:: Examples 144 | 145 | .. code-block:: rust 146 | 147 | const ZERO: u32 = 0; 148 | 149 | .. _fls_xdvdl2ssnhlo: 150 | 151 | Statics 152 | ------- 153 | 154 | .. rubric:: Syntax 155 | 156 | .. syntax:: 157 | 158 | StaticDeclaration ::= 159 | ItemSafety? $$static$$ $$mut$$? Name TypeAscription StaticInitializer? $$;$$ 160 | 161 | StaticInitializer ::= 162 | $$=$$ Expression 163 | 164 | .. rubric:: Legality Rules 165 | 166 | :dp:`fls_ibrmiwfypldh` 167 | A :t:`static` is a :t:`value` that is associated with a specific memory 168 | location. 169 | 170 | :dp:`fls_mt94jvoot9dx` 171 | A :t:`static` defined within a :t:`generic function` exists once in the 172 | output executable or library. 173 | 174 | :dp:`fls_k0r2c6uq29tu` 175 | The :t:`type specification` of a :t:`static` shall have ``'static`` 176 | :t:`lifetime`. 177 | 178 | :dp:`fls_b6ods85htuyn` 179 | The :t:`type` of a :t:`static` shall implement the :std:`core::marker::Sized` 180 | :t:`trait`. 181 | 182 | :dp:`fls_WRpcVF1fLEpr` 183 | A :t:`static` shall only be subject to an :s:`ItemSafety` if it is an :t:`external static` in an :t:`unsafe external block`. 184 | 185 | :dp:`fls_doi4z6u55bi7` 186 | A :t:`mutable static` is a :t:`static` with :t:`keyword` ``mut`` whose 187 | :t:`value` can be modified. 188 | 189 | :dp:`fls_74hp208pto22` 190 | Access to a :t:`mutable static` shall require :t:`unsafe context`. 191 | 192 | :dp:`fls_jfde2vg6mtww` 193 | An :t:`immutable static` is a :t:`static` whose :t:`value` cannot be modified. 194 | 195 | :dp:`fls_k4tyqb1j6zjo` 196 | The type of an :t:`immutable static` shall implement the 197 | :std:`core::marker::Sync` :t:`trait`. 198 | 199 | :dp:`fls_t17h5h6a6v4c` 200 | A :t:`static initializer` is a :t:`construct` that provides the :t:`value` of 201 | its related :t:`static`. 202 | 203 | :dp:`fls_yq0hpy4jx2qb` 204 | A :t:`static` shall have a :t:`static initializer`, unless it is an 205 | :t:`external static`. 206 | 207 | :dp:`fls_vgidvfwzm4ks` 208 | The :t:`expression` of a :t:`static initializer` shall be a 209 | :t:`constant expression`. 210 | 211 | :dp:`fls_8dcldbvu7lav` 212 | A use of a :t:`static` is a :t:`place expression` referring to the unique 213 | location of the :t:`static`. 214 | 215 | .. rubric:: Dynamic Semantics 216 | 217 | :dp:`fls_w0nb0mphho7b` 218 | The :t:`elaboration` of a :t:`static` evaluates its :t:`static initializer`. 219 | 220 | :dp:`fls_eeocxst9vafn` 221 | All :t:`[path]s` that refer to a :t:`static` refer to the same memory location. 222 | 223 | :dp:`fls_47khd5ljsxeq` 224 | A :t:`static` is not :t:`dropped` during :t:`destruction`. 225 | 226 | :dp:`fls_dowxbphqvk3n` 227 | An :t:`immutable static` whose :t:`type` is not subject to 228 | :t:`interior mutability` may reside in read-only memory. 229 | 230 | .. rubric:: Undefined Behavior 231 | 232 | :dp:`fls_b5wsmii7vz3v` 233 | It is undefined behavior to mutate an :t:`immutable static` whose :t:`type` is 234 | not subject to :t:`interior mutability`. 235 | 236 | .. rubric:: Examples 237 | 238 | .. code-block:: rust 239 | 240 | static mut GLOBAL: u32 = 0; 241 | 242 | .. _fls_cleoffpn5ew6: 243 | 244 | Temporaries 245 | ----------- 246 | 247 | .. rubric:: Legality Rules 248 | 249 | :dp:`fls_awpw61yofckz` 250 | A :t:`temporary` is an anonymous :t:`variable` produced by some intermediate 251 | computation. 252 | 253 | .. _fls_gho955gmob73: 254 | 255 | Variables 256 | --------- 257 | 258 | .. rubric:: Legality Rules 259 | 260 | :dp:`fls_hl5tnd9yy252` 261 | A :t:`variable` is a placeholder for a :t:`value` that is allocated on the 262 | stack. 263 | 264 | :dp:`fls_vgi0gh5zmoiu` 265 | The following :t:`[construct]s` are :t:`[variable]s`: 266 | 267 | * :dp:`fls_81dlbula47nu` 268 | A :t:`binding`. 269 | 270 | * :dp:`fls_3p0sb9ppmg3w` 271 | A :t:`temporary`. 272 | 273 | :dp:`fls_r9km9f969bu8` 274 | A :t:`variable` shall be used only after it has been initialized through all 275 | :t:`[reachable control flow path]s` up to the point of its usage. 276 | 277 | .. rubric:: Dynamic Semantics 278 | 279 | :dp:`fls_g8etd5lsgn9j` 280 | A :t:`variable` is not initialized when allocated. 281 | 282 | .. _fls_wttihxen35as: 283 | 284 | Constant Promotion 285 | ~~~~~~~~~~~~~~~~~~ 286 | 287 | .. rubric:: Legality Rules 288 | 289 | :dp:`fls_udn9lyf3m0z6` 290 | :t:`Constant promotion` is the process of converting a :t:`value expression` 291 | into a :t:`constant`. 292 | 293 | :dp:`fls_yvkdcs4pmxjf` 294 | :t:`Constant promotion` is possible only when 295 | 296 | * :dp:`fls_n570za6a9nqd` 297 | The :t:`value expression` is a :t:`constant expression`, and 298 | 299 | * :dp:`fls_tms5r9f5ogcb` 300 | The :t:`type` of the :t:`value expression` does not have a :t:`destructor`, 301 | and 302 | 303 | * :dp:`fls_bysv5r7iuf5j` 304 | The :t:`value expression` does not employ a :t:`struct expression` 305 | constructing a :std:`core::cell::UnsafeCell`, and 306 | 307 | * :dp:`fls_3h5vr7xk2rrt` 308 | The :t:`value expression` only consists of operations that will always succeed 309 | evaluation, and 310 | 311 | * :dp:`fls_3BGncWvMumEt` 312 | The :t:`value expression` is the :t:`operand` of an 313 | :t:`immutable borrow expression`. 314 | 315 | :dp:`fls_m690b8qg9d9r` 316 | :t:`Constant promotion` is always possible for :t:`expression` ``&mut []``, 317 | promoting the produced :t:`mutable borrow` to have ``'static`` :t:`lifetime`. 318 | 319 | :dp:`fls_uf0sg25awre6` 320 | :t:`Constant promotion` proceeds as follows: 321 | 322 | #. :dp:`fls_o7cqfdnr253y` 323 | An anonymous :t:`constant` is created, whose :t:`constant initializer` holds 324 | the result of the :t:`value expression`. 325 | 326 | #. :dp:`fls_ap85svxyuhvg` 327 | The :t:`value` of the anonymous :t:`constant` is :t:`borrowed` with 328 | ``'static`` :t:`lifetime`. 329 | -------------------------------------------------------------------------------- /src/general.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | SPDX-FileCopyrightText: The Rust Project Contributors 4 | 5 | .. default-domain:: spec 6 | 7 | .. informational-page:: 8 | 9 | .. _fls_48qldfwwh493: 10 | 11 | General 12 | ======= 13 | 14 | :dp:`fls_c4ry0kgmvk9z` 15 | This document is influenced by the `Ada Reference Manual 16 | `_ 17 | Ada 202x edition, as well as the `Rust Language Reference 18 | `_, the `Rust 19 | Guidebook `_, and the `Rustonomicon 20 | `_. 21 | 22 | :dp:`fls_gxqbj0qoiaio` 23 | Parts of these documents have been copied, in whole or in part, in particular 24 | but not limited to: 25 | 26 | * :dp:`fls_u8k9zr8da30` 27 | The outline and structure of the documents; 28 | 29 | * :dp:`fls_8mt9iigoboba` 30 | The title, outline, organization, and numbering of chapters; 31 | 32 | * :dp:`fls_suhf2g3fatfa` 33 | The structure, formality, wording, and numbering of paragraphs; 34 | 35 | * :dp:`fls_jjr5kbn0wuco` 36 | The definitions and uses of terms; 37 | 38 | * :dp:`fls_4dfcjyprkzbx` 39 | The categories of syntactic and semantic rules. 40 | 41 | :dp:`fls_tq9jcv5ddvwn` 42 | Consult :doc:`licenses` for the relevant copyright notices and licenses. 43 | 44 | .. _fls_fo1c7pg2mw1: 45 | 46 | Scope 47 | ----- 48 | 49 | :dp:`fls_srdq4mota5pr` 50 | This document specifies the form and meaning of programs written in the 2021 Edition of the 51 | programming language Rust, as implemented by the :t:`rustc` |spec_version| compiler shipped 52 | with Ferrocene. It documents the current understanding for the purposes of 53 | compiler validation. As such, given any doubt, it prefers documenting behavior 54 | of :t:`rustc` as included in the associated Ferrocene release over claiming 55 | correctness as a specification. 56 | 57 | :dp:`fls_dv1qish8svc` 58 | This document is made available for contribution and review as it is useful 59 | outside of the Ferrocene effort and can be a place of shared understanding. It 60 | is not intended as a discussion ground for language evolution. It is also not 61 | intended as a document enabling conformance between compilers. 62 | 63 | .. _fls_10yukmkhl0ng: 64 | 65 | Extent 66 | ~~~~~~ 67 | 68 | :dp:`fls_x78yd1sszydv` 69 | This document specifies: 70 | 71 | * :dp:`fls_9e032738udnb` 72 | The form of a program written in Rust; 73 | 74 | * :dp:`fls_jk7scu5xs17z` 75 | The effect of translating and executing such a program; 76 | 77 | * :dp:`fls_jiryupa5fxgf` 78 | The manner in which :t:`[crate]s` and :t:`[module]s` may be combined to form 79 | Rust programs; 80 | 81 | * :dp:`fls_sph1a3sapinh` 82 | The language-defined libraries that a conforming tool is required to supply; 83 | 84 | * :dp:`fls_7tm19jxtffc8` 85 | The violations that a conforming tool is required to detect, and the effect of 86 | attempting to translate or execute a program containing such violations; 87 | 88 | * :dp:`fls_5pbrl8lhuth1` 89 | The violations that a conforming tool is not required to detect. 90 | 91 | :dp:`fls_o8fc3e53vp7g` 92 | This document does not specify: 93 | 94 | * :dp:`fls_rw0y5t13y6gs` 95 | The means by which a Rust program is transformed into object code executable 96 | by a processor; 97 | 98 | * :dp:`fls_x7c3o621qj9z` 99 | The means by which translation or execution of Rust programs is invoked and 100 | the executing units are controlled; 101 | 102 | * :dp:`fls_5y2b6yjcl1vz` 103 | The size or speed of the object code, or the relative execution speed of 104 | different language constructs; 105 | 106 | * :dp:`fls_8dennhk2dha` 107 | The form or contents of any listings produced by a tool; in particular, the 108 | form or contents of error or warning messages; 109 | 110 | * :dp:`fls_j2gs3hrbxtyx` 111 | The effect of undefined behavior; 112 | 113 | * :dp:`fls_gy2c7vfwkd8j` 114 | The size of a program or program unit that will exceed the capacity of a 115 | conforming tool. 116 | 117 | .. _fls_xscgklvg1wd2: 118 | 119 | Structure 120 | ~~~~~~~~~ 121 | 122 | :dp:`fls_6lrqailxjb02` 123 | This document contains 22 chapters, 4 appendices, and an index. 124 | 125 | :dp:`fls_tys7ciqnp8bn` 126 | The specification of the Rust language is separated into: 127 | 128 | * :dp:`fls_3ubhkaheu8i1` 129 | Chapters 1 through 22, 130 | 131 | * :dp:`fls_xw3grr2g5zgi` 132 | Appendices A through D 133 | 134 | :dp:`fls_6srbinvnyd54` 135 | The specification is normative, except for the material in each of the items 136 | listed below, which is informative: 137 | 138 | * :dp:`fls_ciixfg9jhv42` 139 | Text under an "Examples" heading. 140 | 141 | * :dp:`fls_ej94lm2682kg` 142 | Each subchapter whose title starts with the word "Example" or "Examples". 143 | 144 | :dp:`fls_xgk91jrbpyoc` 145 | All appendices are informative. 146 | 147 | :dp:`fls_jc4upf6685bw` 148 | Each chapter is divided into subchapters that have a common structure. Each 149 | chapter and subchapter is then organized to include the following segments as is 150 | relevant to the topic: 151 | 152 | .. rubric:: Syntax 153 | 154 | :dp:`fls_oxzjqxgejx9t` 155 | The syntax representation of a :t:`construct`. 156 | 157 | .. rubric:: Legality Rules 158 | 159 | :dp:`fls_gmx688d6ek1o` 160 | Compile-time rules and facts for each :t:`construct`. A :t:`construct` is legal 161 | if it obeys all of the Legality Rules. 162 | 163 | :dp:`fls_5zdjikp1jhc` 164 | Legality Rules are verified after :t:`macro expansion` takes place. 165 | 166 | .. rubric:: Dynamic Semantics 167 | 168 | :dp:`fls_as5bhc5t285g` 169 | Run-time effects of each :t:`construct`. 170 | 171 | .. rubric:: Undefined Behavior 172 | 173 | :dp:`fls_70qjvaqoz007` 174 | Situations that result in unbounded errors. 175 | 176 | .. rubric:: Implementation Requirements 177 | 178 | :dp:`fls_o4rdsbc7u98` 179 | Additional requirements for conforming tools. 180 | 181 | .. rubric:: Examples 182 | 183 | :dp:`fls_w8j575w2hmc8` 184 | Examples illustrating the possible forms of a :t:`construct`. This material 185 | is informative. 186 | 187 | .. _fls_99b7xi1bkgih: 188 | 189 | Conformity 190 | ~~~~~~~~~~ 191 | 192 | .. rubric:: Implementation Requirements 193 | 194 | :dp:`fls_kdyqtnc6loam` 195 | A conforming tool shall: 196 | 197 | * :dp:`fls_dBKu9jgx3OyH` 198 | Correctly translate legal programs written in Rust, 199 | 200 | * :dp:`fls_faRvWyJJpno8` 201 | Reject programs that exceed the tool's implementation capacity, 202 | 203 | * :dp:`fls_GZmxrO61eiJ1` 204 | Reject programs that contain errors whose detection is required by this document, 205 | 206 | :dp:`fls_nnmx2qsu14ft` 207 | The external effect of the execution of a Rust program is defined in terms of 208 | its interactions with its external environment. The following are defined as 209 | external interactions: 210 | 211 | * :dp:`fls_gu3331rmv2ho` 212 | Any call to an :t:`external function`, 213 | 214 | * :dp:`fls_AR8ZIYlDRSNs` 215 | Any interaction with an :t:`external static`, 216 | 217 | * :dp:`fls_xAYhvEh7WWel` 218 | Any result returned from a :t:`program entry point`, 219 | 220 | * :dp:`fls_QvFpU8v5p8Hb` 221 | Any result returned from an :t:`exported function` to an external caller. 222 | 223 | :dp:`fls_pl0fyjcwslqm` 224 | A tool that conforms to this document shall produce for the execution of a given 225 | Rust program a set of interactions with the external environment whose order and 226 | timing are consistent with the definitions and requirements of this document for 227 | the semantics of the given program. 228 | 229 | :dp:`fls_lkdm0mdghppv` 230 | A tool that conforms to this document shall support each capability required by 231 | the language as specified. 232 | 233 | :dp:`fls_d07x1mbhgpsd` 234 | A tool that conforms to this document may provide additional :t:`[attribute]s` 235 | as long as their names are not the same as the names of :t:`[built-in 236 | attribute]s`. 237 | 238 | .. _fls_79rl6ylmct07: 239 | 240 | Method of Description and Syntax Notation 241 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 242 | 243 | :dp:`fls_mc4a28do6kcp` 244 | The form of a Rust program is described by means of a context-free syntax 245 | together with context-dependent requirements expressed by narrative rules. 246 | 247 | :dp:`fls_ioyp4wux6skt` 248 | The semantic meaning of a Rust program is described by means of narrative rules defining 249 | both the effects of each construct and the composition rules for constructs. 250 | 251 | :dp:`fls_jsflt7691ye4` 252 | The context-free syntax of Rust is described using a simple variant of the 253 | Backus-Naur form. In particular: 254 | 255 | * :dp:`fls_98fm7z04lq9` 256 | A ``monospaced`` font is used to denote Rust syntax. 257 | 258 | * :dp:`fls_ceb5a8t6cakr` 259 | Words in PascalCase font are used to denote a syntactic category, for example: 260 | 261 | .. syntax:: 262 | 263 | FloatExponent 264 | 265 | * :dp:`fls_pts29mb5ld68` 266 | Words in **bold** font are used to indicate literal words and :t:`[keyword]s`, 267 | for example: 268 | 269 | .. syntax:: 270 | 271 | $$crate$$ 272 | $$proc_macro_derive$$ 273 | $$Self$$ 274 | $$tt$$ 275 | 276 | * :dp:`fls_gqjo5oh7vn3b` 277 | Characters in **bold** font are used to indicate literal characters and 278 | literal punctuation, for example: 279 | 280 | .. syntax:: 281 | 282 | $$1$$ 283 | $$F$$ 284 | $${$$ 285 | $$&&$$ 286 | $$>>=$$ 287 | 288 | * :dp:`fls_1dz634xp8xp5` 289 | A character preceded by ``\`` (bold reverse solidus) is used to denote an 290 | :t:`escaped character`, for example: 291 | 292 | .. syntax:: 293 | 294 | $$\t$$ 295 | $$\\$$ 296 | 297 | * :dp:`fls_pp9vtjlyblrl` 298 | A prefix followed by ``?`` (question mark) is used to denote an optional 299 | prefix, for example: 300 | 301 | .. syntax:: 302 | 303 | IntegerSuffix? 304 | 305 | * :dp:`fls_6e2vd9fvhsmk` 306 | A prefix followed by ``*`` (asterisk) is used to denote zero or more 307 | repetitions of the prefix, for example: 308 | 309 | .. syntax:: 310 | 311 | OuterAttributeOrDoc* 312 | 313 | * :dp:`fls_4onq0kkrt6qv` 314 | A prefix followed by ``+`` (plus sign) is used to denote one or more 315 | repetitions of the prefix, for example: 316 | 317 | .. syntax:: 318 | 319 | MacroMatch+ 320 | 321 | * :dp:`fls_qu4rsmnq659w` 322 | A prefix followed by ``L-H`` is used to denote the number of repetitions of 323 | the prefix within the range from L to H, inclusive. For example: 324 | 325 | .. syntax:: 326 | 327 | HexadecimalDigit1-6 328 | 329 | * :dp:`fls_rllu7aksf17e` 330 | ``[ ]`` (square brackets) indicate any character within, for example: 331 | 332 | .. syntax:: 333 | 334 | [$$8$$ $$a$$ $$\r$$ $$:$$] 335 | 336 | * :dp:`fls_blvsfqeevosr` 337 | ``~[ ]`` (square brackets preceded by tilde) indicate any character except the 338 | characters within, for example: 339 | 340 | .. syntax:: 341 | 342 | ~[$$8$$ $$a$$ $$\r$$ $$:$$] 343 | 344 | * :dp:`fls_lwcjq3wzjyvb` 345 | ``[ - ]`` indicates any character within the specified range, inclusive. For 346 | example: 347 | 348 | .. syntax:: 349 | 350 | [$$a$$-$$f$$] 351 | 352 | * :dp:`fls_v7wd5yk00im6` 353 | A ``|`` (vertical line) separates alternative items, for example: 354 | 355 | .. syntax:: 356 | 357 | $$self$$ | Identifier | $$_$$ 358 | 359 | * :dp:`fls_nf8alga8uz6c` 360 | ``( )`` (parentheses) are used to group items, for example: 361 | 362 | .. syntax:: 363 | 364 | ($$,$$ ConfigurationPredicate) 365 | 366 | .. _fls_9cd746qe40ag: 367 | 368 | Versioning 369 | ---------- 370 | 371 | :dp:`fls_l80e3kdwnldc` 372 | Ferrocene is a qualified compiler and this is the accompanying language 373 | specification for the qualified version of the compiler. This document will 374 | be updated with each qualification to accurately reflect the behavior of the 375 | compiler qualified under that version of Ferrocene. 376 | 377 | .. _fls_ijzgf4h0mp3c: 378 | 379 | Definitions 380 | ----------- 381 | 382 | :dp:`fls_sm2kexes5pr7` 383 | Terms are defined throughout this document, indicated by *italic* type. Terms 384 | explicitly defined in this document are not to be presumed to refer implicitly 385 | to similar terms defined elsewhere. 386 | 387 | :dp:`fls_2o98zw29xc46` 388 | Mathematical terms not defined in this document are to be interpreted according 389 | to the CRC Concise Encyclopedia of Mathematics, Second Edition. 390 | 391 | :dp:`fls_lon5qffd65fi` 392 | Other terms not defined in this document are to be interpreted according to the 393 | Webster's Third New International Dictionary of the English Language. 394 | 395 | :dp:`fls_qeolgxvcy75` 396 | The definitions of terms are available in :doc:`glossary`. 397 | 398 | :dp:`fls_h2m244agxaxs` 399 | A *rule* is a requirement imposed on the programmer, stated in normative 400 | language such as "shall", "shall not", "must", "must not", except for text 401 | under Implementation Requirements heading. 402 | 403 | :dp:`fls_47svine904xk` 404 | A *fact* is a requirement imposed on a conforming tool, stated in informative 405 | language such as "is", "is not", "can", "cannot". 406 | -------------------------------------------------------------------------------- /src/licenses.rst: -------------------------------------------------------------------------------- 1 | .. SPDX-License-Identifier: MIT OR Apache-2.0 2 | SPDX-FileCopyrightText: The Ferrocene Developers 3 | 4 | .. default-domain:: spec 5 | 6 | .. informational-page:: 7 | 8 | .. _fls_kd7fcvfrwks0: 9 | 10 | Licenses 11 | ======== 12 | 13 | .. _fls_mwoe9jy6l7er: 14 | 15 | Ada Reference Manual Copyright Notice 16 | ------------------------------------- 17 | 18 | :dp:`fls_9rpvtm5tjrpp` 19 | **Fourth Edition (Ada** 202x\ **)** 20 | 21 | :dp:`fls_7uhb9t9x8r0c` 22 | Copyright © 2016, 2017, 2018, 2019, 2020, 2021 AXE Consultants. All Rights 23 | Reserved. 24 | 25 | :dp:`fls_ej4g7lz5eqm8` 26 | This document may be copied, in whole or in part, in any form or by any means, 27 | as is, or with alterations, provided that (1) alterations are clearly marked as 28 | alterations and (2) this copyright notice is included unmodified in any copy. 29 | Any other use or distribution of this document is prohibited without the prior 30 | express permission of AXE. 31 | 32 | :dp:`fls_l9uu4q48v1co` 33 | You use this document on the condition that you indemnify and hold harmless 34 | AXE, its board, officers, agents, and employees, from any and all liability or 35 | damages to yourself or your hardware or software, or third parties, including 36 | attorneys' fees, court costs, and other related costs and expenses, arising out 37 | of your use of this document irrespective of the cause of said liability. 38 | 39 | :dp:`fls_3j7jx4qsqucs` 40 | AXE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, 41 | EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, 42 | OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL AXE BE LIABLE FOR ANY GENERAL, 43 | CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF AXE 44 | HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 45 | 46 | .. _fls_w6b35kn6la40: 47 | 48 | Rust Reference Apache License 49 | ----------------------------- 50 | 51 | :dp:`fls_wn4kcs3skqra` 52 | Apache License 53 | 54 | :dp:`fls_mtcsb64efiw1` 55 | Version 2.0, January 2004 56 | 57 | :dp:`fls_9tssu3wp22cz` 58 | http://www.apache.org/licenses/ 59 | 60 | :dp:`fls_4pclfuqukw5o` 61 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 62 | 63 | :dp:`fls_rgn86bsd9tl5` 64 | 1. Definitions. 65 | 66 | :dp:`fls_n6ash4u0e838` 67 | "License" shall mean the terms and conditions for use, reproduction, and 68 | distribution as defined by Sections 1 through 9 of this document. 69 | 70 | :dp:`fls_4z50m2plw8lg` 71 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 72 | owner that is granting the License. 73 | 74 | :dp:`fls_bmx87il86j77` 75 | "Legal Entity" shall mean the union of the acting entity and all other entities 76 | that control, are controlled by, or are under common control with that entity. 77 | For the purposes of this definition, "control" means (i) the power, direct 78 | or indirect, to cause the direction or management of such entity, whether by 79 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 80 | outstanding shares, or (iii) beneficial ownership of such entity. 81 | 82 | :dp:`fls_467b9ucekcv3` 83 | "You" (or "Your") shall mean an individual or Legal Entity exercising 84 | permissions granted by this License. 85 | 86 | :dp:`fls_9ws2rqie234r` 87 | "Source" form shall mean the preferred form for making modifications, including 88 | but not limited to software source code, documentation source, and configuration 89 | files. 90 | 91 | :dp:`fls_j075fx75s7wg` 92 | "Object" form shall mean any form resulting from mechanical transformation or 93 | translation of a Source form, including but not limited to compiled object code, 94 | generated documentation, and conversions to other media types. 95 | 96 | :dp:`fls_akjks1czkd7n` 97 | "Work" shall mean the work of authorship, whether in Source or Object form, made 98 | available under the License, as indicated by a copyright notice that is included 99 | in or attached to the work (an example is provided in the Appendix below). 100 | 101 | :dp:`fls_6n4t2e7lxq3` 102 | "Derivative Works" shall mean any work, whether in Source or Object form, that 103 | is based on (or derived from) the Work and for which the editorial revisions, 104 | annotations, elaborations, or other modifications represent, as a whole, an 105 | original work of authorship. For the purposes of this License, Derivative Works 106 | shall not include works that remain separable from, or merely link (or bind by 107 | name) to the interfaces of, the Work and Derivative Works thereof. 108 | 109 | :dp:`fls_g0gyduo0wc55` 110 | "Contribution" shall mean any work of authorship, including the original version 111 | of the Work and any modifications or additions to that Work or Derivative 112 | Works thereof, that is intentionally submitted to Licensor for inclusion in the 113 | Work by the copyright owner or by an individual or Legal Entity authorized to 114 | submit on behalf of the copyright owner. For the purposes of this definition, 115 | "submitted" means any form of electronic, verbal, or written communication 116 | sent to the Licensor or its representatives, including but not limited to 117 | communication on electronic mailing lists, source code control systems, and 118 | issue tracking systems that are managed by, or on behalf of, the Licensor for 119 | the purpose of discussing and improving the Work, but excluding communication 120 | that is conspicuously marked or otherwise designated in writing by the copyright 121 | owner as "Not a Contribution." 122 | 123 | :dp:`fls_w8npkgeox7u5` 124 | "Contributor" shall mean Licensor and any individual or Legal Entity on 125 | behalf of whom a contribution has been received by Licensor and subsequently 126 | incorporated within the Work. 127 | 128 | :dp:`fls_iygftblnws72` 129 | 2. Grant of Copyright License. Subject to the terms and conditions of this 130 | License, each Contributor hereby grants to You a perpetual, worldwide, 131 | non-exclusive, no-charge, royalty-free, irrevocable copyright license to 132 | reproduce, prepare Derivative Works of, publicly display, publicly perform, 133 | sublicense, and distribute the Work and such Derivative Works in Source or 134 | Object form. 135 | 136 | :dp:`fls_s32i8ovj5nqu` 137 | 3. Grant of Patent License. Subject to the terms and conditions of this License, 138 | each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 139 | no-charge, royalty-free, irrevocable (except as stated in this section) 140 | patent license to make, have made, use, offer to sell, sell, import, and 141 | otherwise transfer the Work, where such license applies only to those patent 142 | claims licensable by such Contributor that are necessarily infringed by their 143 | Contribution(s) alone or by combination of their Contribution(s) with the 144 | Work to which such Contribution(s) was submitted. If You institute patent 145 | litigation against any entity (including a cross-claim or counterclaim in a 146 | lawsuit) alleging that the Work or a Contribution incorporated within the Work 147 | constitutes direct or contributory patent infringement, then any patent licenses 148 | granted to You under this License for that Work shall terminate as of the date 149 | such litigation is filed. 150 | 151 | :dp:`fls_c673i0mbecb9` 152 | 4. Redistribution. You may reproduce and distribute copies of the Work or 153 | Derivative Works thereof in any medium, with or without modifications, and in 154 | Source or Object form, provided that You meet the following conditions: 155 | 156 | :dp:`fls_pwpt8rg76oj3` 157 | (a) You must give any other recipients of the Work or Derivative Works a copy of 158 | this License; and 159 | 160 | :dp:`fls_yu3hgzo57bvm` 161 | (b) You must cause any modified files to carry prominent notices stating that 162 | You changed the files; and 163 | 164 | :dp:`fls_37aibo9w67e8` 165 | (c) You must retain, in the Source form of any Derivative Works that You 166 | distribute, all copyright, patent, trademark, and attribution notices from the 167 | Source form of the Work, excluding those notices that do not pertain to any part 168 | of the Derivative Works; and 169 | 170 | :dp:`fls_py9om9jvbulw` 171 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then 172 | any Derivative Works that You distribute must include a readable copy of the 173 | attribution notices contained within such NOTICE file, excluding those notices 174 | that do not pertain to any part of the Derivative Works, in at least one of 175 | the following places: within a NOTICE text file distributed as part of the 176 | Derivative Works; within the Source form or documentation, if provided along 177 | with the Derivative Works; or, within a display generated by the Derivative 178 | Works, if and wherever such third-party notices normally appear. The contents 179 | of the NOTICE file are for informational purposes only and do not modify the 180 | License. You may add Your own attribution notices within Derivative Works 181 | that You distribute, alongside or as an addendum to the NOTICE text from the 182 | Work, provided that such additional attribution notices cannot be construed as 183 | modifying the License. 184 | 185 | :dp:`fls_wkf26wyy0ndr` 186 | You may add Your own copyright statement to Your modifications and may provide 187 | additional or different license terms and conditions for use, reproduction, or 188 | distribution of Your modifications, or for any such Derivative Works as a whole, 189 | provided Your use, reproduction, and distribution of the Work otherwise complies 190 | with the conditions stated in this License. 191 | 192 | :dp:`fls_qsvzdiicam4f` 193 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 194 | Contribution intentionally submitted for inclusion in the Work by You to the 195 | Licensor shall be under the terms and conditions of this License, without any 196 | additional terms or conditions. Notwithstanding the above, nothing herein shall 197 | supersede or modify the terms of any separate license agreement you may have 198 | executed with Licensor regarding such Contributions. 199 | 200 | :dp:`fls_n4zpph83hza1` 201 | 6. Trademarks. This License does not grant permission to use the trade names, 202 | trademarks, service marks, or product names of the Licensor, except as required 203 | for reasonable and customary use in describing the origin of the Work and 204 | reproducing the content of the NOTICE file. 205 | 206 | :dp:`fls_6gvjqsyyk3sg` 207 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to 208 | in writing, Licensor provides the Work (and each Contributor provides its 209 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 210 | ANY KIND, either express or implied, including, without limitation, any 211 | warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or 212 | FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining 213 | the appropriateness of using or redistributing the Work and assume any risks 214 | associated with Your exercise of permissions under this License. 215 | 216 | :dp:`fls_evwltjyhvhz` 217 | 8. Limitation of Liability. In no event and under no legal theory, whether 218 | in tort (including negligence), contract, or otherwise, unless required by 219 | applicable law (such as deliberate and grossly negligent acts) or agreed to 220 | in writing, shall any Contributor be liable to You for damages, including any 221 | direct, indirect, special, incidental, or consequential damages of any character 222 | arising as a result of this License or out of the use or inability to use the 223 | Work (including but not limited to damages for loss of goodwill, work stoppage, 224 | computer failure or malfunction, or any and all other commercial damages or 225 | losses), even if such Contributor has been advised of the possibility of such 226 | damages. 227 | 228 | :dp:`fls_xj0b5mrjgdbt` 229 | 9. Accepting Warranty or Additional Liability. While redistributing the 230 | Work or Derivative Works thereof, You may choose to offer, and charge a 231 | fee for, acceptance of support, warranty, indemnity, or other liability 232 | obligations and/or rights consistent with this License. However, in accepting 233 | such obligations, You may act only on Your own behalf and on Your sole 234 | responsibility, not on behalf of any other Contributor, and only if You agree to 235 | indemnify, defend, and hold each Contributor harmless for any liability incurred 236 | by, or claims asserted against, such Contributor by reason of your accepting any 237 | such warranty or additional liability. 238 | 239 | :dp:`fls_ecitsmzb8l28` 240 | END OF TERMS AND CONDITIONS 241 | 242 | :dp:`fls_wx0hv6f68i4f` 243 | APPENDIX: How to apply the Apache License to your work. 244 | 245 | :dp:`fls_fgjjzdwbw1t8` 246 | To apply the Apache License to your work, attach the following boilerplate 247 | notice, with the fields enclosed by brackets "[]" replaced with your own 248 | identifying information. (Don't include the brackets!) The text should 249 | be enclosed in the appropriate comment syntax for the file format. We also 250 | recommend that a file or class name and description of purpose be included on 251 | the same "printed page" as the copyright notice for easier identification within 252 | third-party archives. 253 | 254 | :dp:`fls_hnxekf2ahnif` 255 | Copyright [yyyy] [name of copyright owner] 256 | 257 | :dp:`fls_e0ytxo6b451` 258 | Licensed under the Apache License, Version 2.0 (the "License"); 259 | 260 | :dp:`fls_145e22m6bw47` 261 | you may not use this file except in compliance with the License. 262 | 263 | :dp:`fls_9o0wr812ggf2` 264 | You may obtain a copy of the License at 265 | 266 | :dp:`fls_cqaian5c7mwr` 267 | http://www.apache.org/licenses/LICENSE-2.0 268 | 269 | :dp:`fls_eil4b7ffojqa` 270 | Unless required by applicable law or agreed to in writing, software distributed 271 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 272 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 273 | specific language governing permissions and limitations under the License. 274 | 275 | .. _fls_un9oqipiretc: 276 | 277 | Rust Reference MIT License 278 | -------------------------- 279 | 280 | :dp:`fls_bkxw1o1hanmk` 281 | **Copyright (c) 2010 The Rust Project Developers** 282 | 283 | :dp:`fls_yc3wyw3plm1s` 284 | Permission is hereby granted, free of charge, to any person obtaining a copy 285 | of this software and associated documentation files (the "Software"), to deal 286 | in the Software without restriction, including without limitation the rights to 287 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 288 | the Software, and to permit persons to whom the Software is furnished to do so, 289 | subject to the following conditions: 290 | 291 | :dp:`fls_ypomxdgiswq8` 292 | The above copyright notice and this permission notice shall be included in all 293 | copies or substantial portions of the Software. 294 | 295 | :dp:`fls_q6rhvbuhxa21` 296 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 297 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 298 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 299 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 300 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 301 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 302 | 303 | --------------------------------------------------------------------------------