From 6ab149077896ee91ef3a509ad25d5841e4888aae Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:15:07 +0900 Subject: [PATCH 001/110] Add canonical syntax migration tools: core migration and extension tools Co-authored-by: Codex --- scripts/migrate-sol-extension.py | 98 ++++ scripts/migrate-syntax-unsafe.txt | 16 + scripts/migrate-syntax.py | 727 ++++++++++++++++++++++++++++++ 3 files changed, 841 insertions(+) create mode 100644 scripts/migrate-sol-extension.py create mode 100644 scripts/migrate-syntax-unsafe.txt create mode 100644 scripts/migrate-syntax.py diff --git a/scripts/migrate-sol-extension.py b/scripts/migrate-sol-extension.py new file mode 100644 index 00000000..c1721bf2 --- /dev/null +++ b/scripts/migrate-sol-extension.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Rename tracked Solcore sources from .solc to .sol and update references.""" + +from pathlib import Path +import re +import subprocess + + +ROOT = Path(__file__).resolve().parents[1] +TEXT_EXTENSIONS = { + ".c", + ".css", + ".h", + ".html", + ".js", + ".json", + ".lua", + ".md", + ".mjs", + ".py", + ".rs", + ".sh", + ".snap", + ".toml", + ".ts", + ".tsx", + ".tsv", + ".txt", + ".vim", + ".el", + ".yaml", + ".yml", +} +TEXT_NAMES = {"Makefile"} + +# These spellings intentionally exercise rejection of the retired extension. +# Protect them so the one-shot migration remains idempotent when rerun while +# reviewing or extending the cut-over. +REFERENCE_EXCEPTIONS = { + Path("crates/driver/src/standard_json.rs"): ('"main.solc"',), +} + + +def tracked_files() -> list[Path]: + output = subprocess.check_output( + ["git", "ls-files", "-z"], cwd=ROOT + ).decode("utf-8") + return [ROOT / name for name in output.rstrip("\0").split("\0") if name] + + +def rename_sources(files: list[Path]) -> None: + for source in files: + if source.suffix != ".solc" or not source.exists(): + continue + destination = source.with_suffix(".sol") + if destination.exists(): + raise RuntimeError(f"refusing to overwrite {destination.relative_to(ROOT)}") + source.rename(destination) + + +def update_references(files: list[Path]) -> None: + for path in files: + if path.suffix == ".solc": + path = path.with_suffix(".sol") + if not path.exists() or not path.is_file(): + continue + if path.suffix not in TEXT_EXTENSIONS and path.name not in TEXT_NAMES: + continue + try: + original = path.read_text() + except UnicodeDecodeError: + continue + relative = path.relative_to(ROOT) + protected = original + placeholders: list[tuple[str, str]] = [] + for index, spelling in enumerate(REFERENCE_EXCEPTIONS.get(relative, ())): + marker = f"__SOLCORE_EXTENSION_MIGRATION_EXCEPTION_{index}__" + if marker in protected: + raise RuntimeError(f"migration marker already present in {relative}") + protected = protected.replace(spelling, marker) + placeholders.append((marker, spelling)) + # Match an extension-like suffix, not the `.solc` prefix in names such + # as `settings.solcore` or TextMate's `source.solcore` scope. + updated = re.sub(r"\.solc(?=$|[^A-Za-z0-9_-])", ".sol", protected) + for marker, spelling in placeholders: + updated = updated.replace(marker, spelling) + if updated != original: + path.write_text(updated) + + +def main() -> None: + files = tracked_files() + rename_sources(files) + update_references(files) + + +if __name__ == "__main__": + main() diff --git a/scripts/migrate-syntax-unsafe.txt b/scripts/migrate-syntax-unsafe.txt new file mode 100644 index 00000000..c3687383 --- /dev/null +++ b/scripts/migrate-syntax-unsafe.txt @@ -0,0 +1,16 @@ +# Syntax migration exceptions + +The following tracked sources required a conservative migration or +still contain an intentionally malformed construct. Intentional +parser-error fixtures are not skipped wholesale: independent syntax +around the error is rewritten normally. +Paths use their pre-extension-migration `.solc` spelling. + +- `crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.solc` — intentional parser-error fixture; cannot migrate function declaration: unbalanced function parameters +- `crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.solc` — intentional parser-error fixture; cannot migrate function declaration: unterminated function header +- `crates/uitest/tests/fixtures/parse/class_missing_body_brace/main.solc` — intentional parser-error fixture; cannot migrate class declaration: declaration has no body +- `crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.solc` — intentional parser-error fixture; cannot migrate function declaration: function parameter list not found +- `crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.solc` — intentional parser-error fixture; unterminated import declaration +- `crates/uitest/tests/fixtures/parse/instance_missing_head/main.solc` — intentional parser-error fixture; cannot migrate instance declaration: invalid predicate +- `crates/uitest/tests/fixtures/parse/missing_semicolon/main.solc` — intentional parser-error fixture; unterminated import declaration +- `crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.solc` — intentional parser-error fixture; unterminated import declaration diff --git a/scripts/migrate-syntax.py b/scripts/migrate-syntax.py new file mode 100644 index 00000000..195bc021 --- /dev/null +++ b/scripts/migrate-syntax.py @@ -0,0 +1,727 @@ +#!/usr/bin/env python3 +"""Migrate tracked Solcore sources to the syntax documented in syntax.md. + +The repository is in the middle of changing its source extension. The input +set is therefore the tracked ``*.solc`` paths, but a missing input is resolved +to its sibling ``*.sol`` file. This makes the script safe to rerun before or +after the extension-only migration. + +The transformer is deliberately token based. It does not touch comments, +strings, or the contents of ``assembly { ... }`` blocks. Intentional +syntax-error fixtures are migrated too: the malformed construct is retained +where possible, while independent surrounding declarations are canonicalized. +""" + +from __future__ import annotations + +import argparse +import dataclasses +import pathlib +import re +import subprocess +import sys +from collections.abc import Iterable, Sequence + + +ROOT = pathlib.Path(__file__).resolve().parents[1] +REPORT = ROOT / "scripts" / "migrate-syntax-unsafe.txt" + + +@dataclasses.dataclass(frozen=True) +class Tok: + text: str + start: int + end: int + + +TOKEN_RE = re.compile( + r""" + (?P\s+) + | (?P//[^\n]*) + | (?P/\*.*?\*/) + | (?P"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*') + | (?P[A-Za-z_$][A-Za-z0-9_$-]*) + | (?P0[xX][0-9A-Fa-f]+|[0-9]+) + | (?P:=|->|=>|==|!=|>=|<=|&&|\|\||\+=|-=|\*=|/=|\^=|&=|\|=|%=|~=) + | (?P.) + """, + re.S | re.X, +) + + +def tokens(source: str) -> list[Tok]: + out: list[Tok] = [] + for match in TOKEN_RE.finditer(source): + if match.lastgroup in {"space", "line", "block", "string"}: + continue + out.append(Tok(match.group(), match.start(), match.end())) + return out + + +def pairs(ts: Sequence[Tok]) -> tuple[dict[int, int], dict[int, int]]: + # Angle tokens are ambiguous outside a known type context: they are also + # comparison operators. Pairing them globally makes `i < n` hide later + # braces and declarations from the migrator. + opens = {"(": ")", "[": "]", "{": "}"} + close_to_open = {value: key for key, value in opens.items()} + stack: list[tuple[str, int]] = [] + forward: dict[int, int] = {} + backward: dict[int, int] = {} + for i, tok in enumerate(ts): + if tok.text in opens: + stack.append((tok.text, i)) + elif tok.text in close_to_open: + wanted = close_to_open[tok.text] + # Invalid fixtures can contain unmatched delimiters. Pair only a + # well-nested suffix and let the caller classify the file unsafe. + if stack and stack[-1][0] == wanted: + _, j = stack.pop() + forward[j] = i + backward[i] = j + return forward, backward + + +def split_top( + ts: Sequence[Tok], separator: str = ",", *, angles: bool = True +) -> list[list[Tok]]: + result: list[list[Tok]] = [] + current: list[Tok] = [] + depth = {"(": 0, "[": 0, "{": 0} + close = {")": "(", "]": "[", "}": "{"} + if angles: + depth["<"] = 0 + close[">"] = "<" + for tok in ts: + if tok.text == separator and not any(depth.values()): + result.append(current) + current = [] + continue + current.append(tok) + if tok.text in depth: + depth[tok.text] += 1 + elif tok.text in close and depth[close[tok.text]]: + depth[close[tok.text]] -= 1 + result.append(current) + return result + + +def top_index( + ts: Sequence[Tok], choices: set[str], *, angles: bool = True +) -> int | None: + depth = {"(": 0, "[": 0, "{": 0} + close = {")": "(", "]": "[", "}": "{"} + if angles: + depth["<"] = 0 + close[">"] = "<" + for i, tok in enumerate(ts): + if tok.text in choices and not any(depth.values()): + return i + if tok.text in depth: + depth[tok.text] += 1 + elif tok.text in close and depth[close[tok.text]]: + depth[close[tok.text]] -= 1 + return None + + +def source_slice(source: str, ts: Sequence[Tok]) -> str: + return "" if not ts else source[ts[0].start : ts[-1].end] + + +def apply_edits(source: str, edits: Iterable[tuple[int, int, str]]) -> str: + ordered = sorted(edits, key=lambda edit: (edit[0], edit[1])) + for left, right in zip(ordered, ordered[1:]): + if left[1] > right[0]: + raise ValueError(f"overlapping migration edits: {left[:2]} and {right[:2]}") + for start, end, replacement in reversed(ordered): + source = source[:start] + replacement + source[end:] + return source + + +def assembly_ranges(ts: Sequence[Tok]) -> list[tuple[int, int]]: + ranges: list[tuple[int, int]] = [] + for i, tok in enumerate(ts[:-1]): + if tok.text != "assembly" or ts[i + 1].text != "{": + continue + # Pair assembly braces independently of parentheses/brackets. Parser + # recovery fixtures intentionally contain an unclosed Yul call; the + # surrounding assembly block is still delimited and must remain fully + # opaque to every Core syntax transform. + depth = 1 + j = i + 2 + while j < len(ts): + if ts[j].text == "{": + depth += 1 + elif ts[j].text == "}": + depth -= 1 + if depth == 0: + ranges.append((i + 1, j)) + break + j += 1 + return ranges + + +def in_ranges(index: int, ranges: Sequence[tuple[int, int]]) -> bool: + return any(start <= index <= end for start, end in ranges) + + +class TypeParser: + def __init__(self, ts: Sequence[Tok]): + self.ts = list(ts) + self.i = 0 + + def take(self, text: str | None = None) -> Tok: + if self.i >= len(self.ts): + raise ValueError("unexpected end of type") + tok = self.ts[self.i] + if text is not None and tok.text != text: + raise ValueError(f"expected {text!r}, found {tok.text!r}") + self.i += 1 + return tok + + def parse(self): + left = self.atom() + if self.i < len(self.ts) and self.ts[self.i].text == "->": + self.i += 1 + return ("fn-old", left, self.parse()) + return left + + def atom(self): + tok = self.take() + if tok.text == "comptime": + if self.i == len(self.ts): + return ("named", "comptime", []) + if self.i < len(self.ts) and self.ts[self.i].text == "<": + self.i += 1 + inner = self.parse() + self.take(">") + else: + inner = self.atom() + return ("comptime", inner) + if tok.text == "@": + return ("proxy", self.parse()) + if tok.text == "function": + self.take("(") + params = self.list_until(")") + ret = ("tuple", []) + if self.i < len(self.ts) and self.ts[self.i].text == "returns": + self.i += 1 + self.take("(") + ret = ("tuple", self.list_until(")")) + return ("fn", params, ret) + if tok.text == "(": + return ("tuple", self.list_until(")")) + if not re.fullmatch(r"[A-Za-z_$][A-Za-z0-9_$-]*", tok.text): + raise ValueError(f"expected type name, found {tok.text!r}") + name = tok.text + while self.i + 1 < len(self.ts) and self.ts[self.i].text == ".": + self.i += 1 + name += "." + self.take().text + args = [] + if self.i < len(self.ts) and self.ts[self.i].text in {"(", "<"}: + opener = self.take().text + closing = ")" if opener == "(" else ">" + if name == "mapping" and opener == "(": + key = self.parse() + if self.i < len(self.ts) and self.ts[self.i].text == "=>": + self.i += 1 + value = self.parse() + self.take(")") + args = [key, value] + else: + self.take(",") + value = self.parse() + self.take(")") + args = [key, value] + else: + args = self.list_until(closing) + return ("named", name, args) + + def list_until(self, closing: str): + values = [] + if self.i < len(self.ts) and self.ts[self.i].text == closing: + self.i += 1 + return values + while True: + values.append(self.parse()) + if self.i < len(self.ts) and self.ts[self.i].text == ",": + self.i += 1 + if self.i < len(self.ts) and self.ts[self.i].text == closing: + self.i += 1 + return values + continue + self.take(closing) + return values + + +def render_type_node(node) -> str: + kind = node[0] + if kind == "named": + _, name, args = node + if name == "mapping" and len(args) == 2: + return f"mapping({render_type_node(args[0])} => {render_type_node(args[1])})" + if args: + return f"{name}<" + ", ".join(map(render_type_node, args)) + ">" + return name + if kind == "tuple": + return "(" + ", ".join(map(render_type_node, node[1])) + ")" + if kind == "proxy": + return "@" + render_type_node(node[1]) + if kind == "comptime": + return "comptime<" + render_type_node(node[1]) + ">" + if kind in {"fn", "fn-old"}: + if kind == "fn": + params, ret = node[1], node[2] + else: + domain, ret = node[1], node[2] + if domain[0] == "tuple" and len(domain[1]) != 1: + params = domain[1] + elif domain[0] == "tuple" and len(domain[1]) == 1: + params = domain[1] + else: + params = [domain] + text = "function(" + ", ".join(map(render_type_node, params)) + ")" + if not (ret[0] == "tuple" and not ret[1]): + returns = ret[1] if ret[0] == "tuple" else [ret] + text += " returns (" + ", ".join(map(render_type_node, returns)) + ")" + return text + raise AssertionError(kind) + + +def render_type(ts: Sequence[Tok]) -> str: + parser = TypeParser(ts) + node = parser.parse() + if parser.i != len(parser.ts): + raise ValueError("trailing tokens in type: " + " ".join(t.text for t in parser.ts[parser.i :])) + return render_type_node(node) + + +def unwrap_outer(ts: Sequence[Tok]) -> Sequence[Tok]: + if len(ts) >= 2 and ts[0].text == "(" and ts[-1].text == ")": + forward, _ = pairs(ts) + if forward.get(0) == len(ts) - 1: + return ts[1:-1] + return ts + + +def render_predicate(ts: Sequence[Tok]) -> str: + ts = list(unwrap_outer(ts)) + colon = top_index(ts, {":"}) + if colon is None or not ts[:colon] or not ts[colon + 1 :]: + raise ValueError("invalid predicate") + subject = render_type(ts[:colon]) + rhs = ts[colon + 1 :] + name = rhs[0].text + if len(rhs) == 1: + return f"{subject}: {name}" + if rhs[1].text not in {"(", "<"} or rhs[-1].text not in {")", ">"}: + raise ValueError("invalid predicate class application") + args = split_top(rhs[2:-1]) + return f"{subject}: {name}<" + ", ".join(render_type(arg) for arg in args if arg) + ">" + + +def render_predicates(ts: Sequence[Tok]) -> str: + ts = list(unwrap_outer(ts)) + return ", ".join(render_predicate(part) for part in split_top(ts) if part) + + +def transform_imports(source: str, warnings: list[str]) -> str: + ts = tokens(source) + edits = [] + for i, tok in enumerate(ts): + if tok.text != "import": + continue + j = i + 1 + depth = 0 + while j < len(ts): + if ts[j].text in "({[<": + depth += 1 + elif ts[j].text in ")}]>" and depth: + depth -= 1 + elif ts[j].text == ";" and depth == 0: + break + j += 1 + if j == len(ts): + warnings.append("unterminated import declaration") + continue + body = ts[i + 1 : j] + if not body: + continue + if body[0].text == "{": + local_forward, _ = pairs(body) + close = local_forward.get(0) + from_i = close + 1 if close is not None else None + if ( + close is not None + and any(item.text == "*" for item in body[1:close]) + and from_i is not None + and from_i < len(body) + and body[from_i].text == "from" + ): + # Wildcard selection is canonical only as `import * from M`; + # selected names next to it are redundant because the open + # import already brings every public name into scope. + module = "".join(item.text for item in body[from_i + 1:]) + edits.append((tok.start, ts[j].end, f"import * from {module};")) + continue + if body[0].text == "*": + continue + hiding = next((k for k, item in enumerate(body) if item.text == "hiding"), None) + hiding_text = "" + if hiding is not None: + hiding_text = " " + source_slice(source, body[hiding:]).strip() + body = body[:hiding] + brace = next((k for k, item in enumerate(body) if item.text == "{"), None) + as_pos = top_index(body, {"as"}) + if brace is not None and brace > 0 and body[brace - 1].text == ".": + forward, _ = pairs(body) + end = forward.get(brace) + if end is None: + warnings.append("unbalanced selective import") + continue + path = "".join(item.text for item in body[: brace - 1]) + inside = body[brace + 1 : end] + if len(inside) == 1 and inside[0].text == "*": + replacement = f"import * from {path}{hiding_text};" + else: + selector = source_slice(source, inside).strip() + replacement = f"import {{{selector}}} from {path}{hiding_text};" + edits.append((tok.start, ts[j].end, replacement)) + elif as_pos is not None: + path = "".join(item.text for item in body[:as_pos]) + alias = "".join(item.text for item in body[as_pos + 1 :]) + edits.append((tok.start, ts[j].end, f"import * as {alias} from {path}{hiding_text};")) + return apply_edits(source, edits) + + +def transform_data(source: str, warnings: list[str]) -> str: + ts = tokens(source) + asm = assembly_ranges(ts) + forward, _ = pairs(ts) + edits = [] + for i, tok in enumerate(ts): + if tok.text != "data" or in_ranges(i, asm): + continue + if i + 1 >= len(ts): + warnings.append("incomplete data declaration") + continue + j = i + 2 + params: list[Tok] = [] + if j < len(ts) and ts[j].text == "(": + end = forward.get(j) + if end is None: + warnings.append("unbalanced data type parameters") + continue + params = ts[j + 1 : end] + j = end + 1 + while j < len(ts) and ts[j].text not in {"=", ";"}: + j += 1 + if j == len(ts): + warnings.append("unterminated data declaration") + continue + name = ts[i + 1].text + generic = "" + if params: + generic = "<" + ", ".join(t.text for part in split_top(params) for t in part) + ">" + # The old binder grammar is identifiers only; restore separators. + generic = "<" + ", ".join("".join(t.text for t in part) for part in split_top(params) if part) + ">" + if ts[j].text == ";": + edits.append((tok.start, ts[j].end, f"enum {name}{generic} {{}}")) + continue + start_variants = j + 1 + k = start_variants + depth = 0 + declaration_starters = { + "class", "constructor", "contract", "data", "default", "enum", + "error", "event", "fallback", "forall", "function", "impl", + "import", "instance", "modifier", "payable", "pragma", "public", + "receive", "struct", "trait", "type", + } + missing_semicolon = False + while k < len(ts): + if ts[k].text in "([<": + depth += 1 + elif ts[k].text in ")]>": + depth -= 1 + elif ts[k].text == ";" and depth == 0: + break + elif depth == 0 and ( + ts[k].text == "}" + or ( + k > start_variants + and ts[k].text in declaration_starters + and "\n" in source[ts[k - 1].end : ts[k].start] + ) + ): + # Several intentional parser failures omit the old data + # terminator. Stop at the next item rather than swallowing + # the rest of the file, so that its surrounding syntax can + # still be migrated. + missing_semicolon = True + break + k += 1 + if k == len(ts): + missing_semicolon = True + variants = [] + variant_tokens = ts[start_variants:k] + malformed_trailing_pipe = bool(variant_tokens and variant_tokens[-1].text == "|") + failed = False + for variant in split_top(variant_tokens, "|"): + if not variant: + continue + vname = variant[0].text + if len(variant) == 1: + variants.append(vname) + elif variant[1].text == "(" and variant[-1].text == ")": + fields = split_top(variant[2:-1]) + try: + rendered = ", ".join(render_type(field) for field in fields if field) + except ValueError as error: + warnings.append(f"data {name}: {error}") + failed = True + break + variants.append(vname + "(" + rendered + ")") + else: + warnings.append(f"unsupported data constructor in {name}") + failed = True + break + if failed: + continue + replacement = f"enum {name}{generic} {{ " + ", ".join(variants) + " }" + if malformed_trailing_pipe: + # Preserve the dedicated trailing-separator parser failure in the + # new enum spelling. A trailing comma would be accepted. + replacement = replacement[:-2] + " | }" + if missing_semicolon: + warnings.append(f"migrated unterminated data declaration {name}") + end = ts[k].end if k < len(ts) and ts[k].text == ";" else ts[k - 1].end + edits.append((tok.start, end, replacement)) + return apply_edits(source, edits) + + +def declaration_start(ts: Sequence[Tok], keyword: int) -> int: + # A declaration prefix contains no braces. The first brace or semicolon + # on the left is therefore its item/member boundary. In particular, stop + # at a previous function's closing `}` instead of walking through its body. + paren_depth = 0 + bracket_depth = 0 + j = keyword - 1 + while j >= 0: + text = ts[j].text + if text == ")": + paren_depth += 1 + elif text == "(" and paren_depth: + paren_depth -= 1 + elif text == "]": + bracket_depth += 1 + elif text == "[" and bracket_depth: + bracket_depth -= 1 + elif paren_depth == 0 and bracket_depth == 0 and text in {";", "{", "}"}: + return j + 1 + j -= 1 + return 0 + + +def parse_prefix(prefix: Sequence[Tok]): + prefix = list(prefix) + vars_: list[str] = [] + predicates: list[Tok] = [] + modifiers: list[str] = [] + if prefix and prefix[0].text == "forall": + dot = top_index(prefix, {"."}) + if dot is None: + raise ValueError("forall clause has no terminator") + binders = [part for part in split_top(prefix[1:dot]) if part] + for binder in binders: + # Whitespace-separated binders do not have comma tokens, so each + # token is a binder unless a bounded-binder colon is present. + colon = top_index(binder, {":"}) + if colon is None: + vars_.extend(tok.text for tok in binder if tok.text != ",") + else: + vars_.append(binder[0].text) + if predicates: + predicates.append(Tok(",", binder[0].start, binder[0].start)) + predicates.extend(binder) + prefix = prefix[dot + 1 :] + modifiers = [tok.text for tok in prefix if tok.text in {"public", "payable"}] + prefix = [tok for tok in prefix if tok.text not in {"public", "payable", "default"}] + fat = top_index(prefix, {"=>"}) + if fat is not None: + predicates = list(prefix[:fat]) + prefix = prefix[fat + 1 :] + if prefix: + raise ValueError("unrecognized declaration prefix: " + " ".join(t.text for t in prefix)) + return vars_, predicates, modifiers + + +def parse_params(ts: Sequence[Tok]) -> str: + rendered = [] + for param in split_top(ts): + if not param: + continue + colon = top_index(param, {":"}) + if colon is None: + rendered.append(" ".join(t.text for t in param)) + continue + left = " ".join(t.text for t in param[:colon]) + rendered.append(f"{left}: {render_type(param[colon + 1:])}") + return ", ".join(rendered) + + +def transform_declarations(source: str, warnings: list[str]) -> str: + ts = tokens(source) + asm = assembly_ranges(ts) + forward, _ = pairs(ts) + edits = [] + occupied: list[tuple[int, int]] = [] + for i, tok in enumerate(ts): + if tok.text not in {"class", "instance", "function", "constructor", "fallback"} or in_ranges(i, asm): + continue + start = declaration_start(ts, i) + if any(left < i < right for left, right in occupied): + continue + old = tok.text in {"class", "instance"} or any( + item.text in {"forall", "=>", "public", "payable"} for item in ts[start:i] + ) + if tok.text in {"function", "constructor", "fallback"}: + # Inspect only this header: arrows in a later declaration must not + # make an already-migrated declaration look old. Constructors and + # fallbacks used the same legacy arrow shell as functions. + h = i + local_depth = 0 + while h < len(ts): + if ts[h].text in "([<": local_depth += 1 + elif ts[h].text in ")]>" and local_depth: local_depth -= 1 + elif local_depth == 0 and ts[h].text in {"{", ";"}: break + h += 1 + old = old or any(item.text == "->" for item in ts[i:h]) + if tok.text in {"constructor", "fallback"}: + old = old or bool(ts[start:i]) + if not old: + continue + try: + try: + vars_, pred_ts, modifiers = parse_prefix(ts[start:i]) + except ValueError: + # A malformed preceding item (for example, a pragma missing + # its semicolon or a stray block-comment terminator) must not + # keep an independent function header in legacy syntax. + prefix = ts[start:i] + if prefix and prefix[0].text not in { + "forall", "(", "public", "payable", "default" + }: + start = i + vars_, pred_ts, modifiers = parse_prefix([]) + else: + raise + if tok.text in {"class", "instance"}: + j = i + 1 + depth = 0 + while j < len(ts): + if ts[j].text in "([<": depth += 1 + elif ts[j].text in ")]>" and depth: depth -= 1 + elif ts[j].text == "{" and depth == 0: break + j += 1 + if j == len(ts): + raise ValueError("declaration has no body") + head = ts[i + 1:j] + # A few older fixtures put the instance context after the + # `instance` keyword instead of in the declaration prefix: + # `instance (a:C) => T(a):D`. Canonical impl syntax always + # moves that context to a trailing where-clause. + if tok.text == "instance": + fat = top_index(head, {"=>"}) + if fat is not None: + inline_predicates = list(head[:fat]) + head = head[fat + 1:] + if pred_ts and inline_predicates: + pred_ts = list(pred_ts) + [ + Tok(",", inline_predicates[0].start, inline_predicates[0].start) + ] + inline_predicates + elif inline_predicates: + pred_ts = inline_predicates + if tok.text == "class": + pred = render_predicate(head) + subject, rhs = pred.split(": ", 1) + trait_name = rhs.split("<", 1)[0] + if not vars_: + # This is only lossless when every head component is a + # bare variable; semantic fail fixtures often violate it. + vars_ = [subject] + if "<" in rhs: + vars_.extend(rhs[rhs.index("<") + 1 : -1].split(", ")) + if not all(re.fullmatch(r"[A-Za-z_$][A-Za-z0-9_$-]*", v) for v in vars_): + raise ValueError("trait head is not representable by generic binders") + replacement = "trait " + trait_name + "<" + ", ".join(vars_) + ">" + else: + default = "default " if "default" in (item.text for item in ts[start:i]) else "" + # parse_prefix does not consume default. + clean_prefix = [item for item in ts[start:i] if item.text != "default"] + vars_, pred_ts, modifiers = parse_prefix(clean_prefix) + pred = render_predicate(head) + subject, rhs = pred.split(": ", 1) + if "<" in rhs: + cls, args = rhs.split("<", 1) + args = args[:-1] + app = f"{cls}<{subject}, {args}>" + else: + app = f"{rhs}<{subject}>" + replacement = default + "impl" + if vars_: + replacement += "<" + ", ".join(vars_) + ">" + replacement += " " + app + if pred_ts: + replacement += " where " + render_predicates(pred_ts) + replacement += " " + edits.append((ts[start].start, ts[j].start, replacement)) + occupied.append((start, j)) + continue + + # Function/constructor/fallback header. + name_i = i + 1 if tok.text == "function" else i + paren_i = name_i + 1 + if paren_i >= len(ts) or ts[paren_i].text != "(": + raise ValueError("function parameter list not found") + end_paren = forward.get(paren_i) + if end_paren is None: + raise ValueError("unbalanced function parameters") + j = end_paren + 1 + while j < len(ts) and ts[j].text not in {"{", ";"}: + j += 1 + if j == len(ts): + raise ValueError("unterminated function header") + suffix = ts[end_paren + 1:j] + arrow = top_index(suffix, {"->"}) + if arrow is not None: + ret_ts = suffix[arrow + 1:] + suffix_mods = [item.text for item in suffix[:arrow] if item.text in {"public", "payable"}] + else: + ret_ts = [] + suffix_mods = [item.text for item in suffix if item.text in {"public", "payable"}] + modifiers.extend(mod for mod in suffix_mods if mod not in modifiers) + if tok.text == "function": + replacement = "function " + ts[name_i].text + if vars_: + replacement += "<" + ", ".join(vars_) + ">" + else: + replacement = tok.text + replacement += "(" + parse_params(ts[paren_i + 1:end_paren]) + ")" + if modifiers: + replacement += " " + " ".join(dict.fromkeys(modifiers)) + if ret_ts: + ret = render_type(ret_ts) + if ret != "()": + if ret.startswith("(") and ret.endswith(")"): + replacement += " returns " + ret + else: + replacement += " returns (" + ret + ")" + if pred_ts: + replacement += " where " + render_predicates(pred_ts) + replacement += " " + edits.append((ts[start].start, ts[j].start, replacement)) + occupied.append((start, j)) + except ValueError as error: + warnings.append(f"cannot migrate {tok.text} declaration: {error}") + return apply_edits(source, edits) + + From 4043de66363ddabe356d3cadd28415b81f56b88a Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:15:07 +0900 Subject: [PATCH 002/110] Add canonical syntax migration tools: type and expression migration Co-authored-by: Codex --- scripts/migrate-syntax.py | 657 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 657 insertions(+) diff --git a/scripts/migrate-syntax.py b/scripts/migrate-syntax.py index 195bc021..f8885448 100644 --- a/scripts/migrate-syntax.py +++ b/scripts/migrate-syntax.py @@ -725,3 +725,660 @@ def transform_declarations(source: str, warnings: list[str]) -> str: return apply_edits(source, edits) +def transform_type_contexts(source: str, warnings: list[str]) -> str: + ts = tokens(source) + asm = assembly_ranges(ts) + forward, _ = pairs(ts) + edits = [] + + # Typed local bindings. + for i, tok in enumerate(ts): + if tok.text != "let" or in_ranges(i, asm) or i + 2 >= len(ts) or ts[i + 2].text != ":": + continue + j = i + 3 + depth = 0 + while j < len(ts): + if ts[j].text in "([<": depth += 1 + elif ts[j].text in ")]>" and depth: depth -= 1 + elif depth == 0 and ts[j].text in {"=", ";", ","}: break + j += 1 + try: + edits.append((ts[i + 3].start, ts[j - 1].end, render_type(ts[i + 3:j]))) + except (ValueError, IndexError) as error: + warnings.append(f"cannot migrate let type: {error}") + + # Contract fields and type-alias RHS. A field begins immediately after a + # declaration boundary and consists of one identifier followed by a colon. + for i, tok in enumerate(ts): + if in_ranges(i, asm): + continue + if tok.text == "type": + j = i + 1 + depth = 0 + while j < len(ts): + if ts[j].text in "([<": depth += 1 + elif ts[j].text in ")]>" and depth: depth -= 1 + elif ts[j].text == "=" and depth == 0: break + j += 1 + k = j + 1 + while k < len(ts) and ts[k].text != ";": k += 1 + if j < len(ts) and k < len(ts): + try: + edits.append((ts[j + 1].start, ts[k - 1].end, render_type(ts[j + 1:k]))) + except ValueError as error: + warnings.append(f"cannot migrate type alias RHS: {error}") + boundary = i == 0 or ts[i - 1].text in {"{", "}", ";"} + if boundary and i + 1 < len(ts) and re.fullmatch(r"[A-Za-z_$][A-Za-z0-9_$-]*", tok.text) and ts[i + 1].text == ":": + j = i + 2 + depth = 0 + while j < len(ts): + if ts[j].text in "([<": depth += 1 + elif ts[j].text in ")]>" and depth: depth -= 1 + elif depth == 0 and ts[j].text in {"=", ";"}: break + j += 1 + if j < len(ts): + try: + edits.append((ts[i + 2].start, ts[j - 1].end, render_type(ts[i + 2:j]))) + except ValueError: + pass + # Deduplicate exact edits (a malformed source can be recognized twice). + edits = list(dict.fromkeys(edits)) + return apply_edits(source, edits) + + +def transform_signature_type_contexts(source: str, warnings: list[str]) -> str: + """Canonicalize types in every callable signature, including arrowless ones.""" + ts = tokens(source) + asm = assembly_ranges(ts) + forward, _ = pairs(ts) + edits = [] + for i, tok in enumerate(ts): + if tok.text not in {"function", "constructor", "fallback", "lam"} or in_ranges(i, asm): + continue + j = i + 1 + while j < len(ts) and ts[j].text != "(" and ts[j].text not in {"{", ";"}: + j += 1 + end = forward.get(j) + if end is None: + continue + for param in split_top(ts[j + 1 : end]): + colon = top_index(param, {":"}) + if colon is None or not param[colon + 1 :]: + continue + try: + replacement = render_type(param[colon + 1 :]) + except ValueError as error: + line = source.count("\n", 0, param[colon].start) + 1 + warnings.append(f"cannot migrate parameter type at line {line}: {error}") + continue + edits.append((param[colon + 1].start, param[-1].end, replacement)) + + k = end + 1 + if tok.text == "lam" and k < len(ts) and ts[k].text == "->": + type_start = k + 1 + type_end = type_start + while type_end < len(ts) and ts[type_end].text != "{": + type_end += 1 + if type_start < type_end: + try: + edits.append( + ( + ts[type_start].start, + ts[type_end - 1].end, + render_type(ts[type_start:type_end]), + ) + ) + except ValueError as error: + line = source.count("\n", 0, ts[k].start) + 1 + warnings.append(f"cannot migrate lambda result type at line {line}: {error}") + return apply_edits(source, dict.fromkeys(edits)) + + +def transform_proxy_annotations(source: str) -> str: + ts = tokens(source) + asm = assembly_ranges(ts) + edits = [] + i = 0 + while i + 4 < len(ts): + if in_ranges(i, asm) or ts[i].text != "Proxy" or ts[i + 1].text != ":" or ts[i + 2].text != "Proxy" or ts[i + 3].text not in {"(", "<"}: + i += 1 + continue + forward, _ = pairs(ts) + end = forward.get(i + 3) + if end is None: + i += 1 + continue + try: + inner = render_type(ts[i + 4:end]) + except ValueError: + i += 1 + continue + edits.append((ts[i].start, ts[end].end, "@" + inner)) + i = end + 1 + return apply_edits(source, edits) + + +def delimiter_keys(ts: Sequence[Tok]) -> list[tuple[str, ...]]: + """Return the delimiter stack immediately before each token.""" + keys: list[tuple[str, ...]] = [] + stack: list[str] = [] + matching = {")": "(", "]": "[", "}": "{"} + for tok in ts: + keys.append(tuple(stack)) + if tok.text in {"(", "[", "{"}: + stack.append(tok.text) + elif tok.text in matching and stack and stack[-1] == matching[tok.text]: + stack.pop() + return keys + + +def transform_conditionals(source: str, warnings: list[str]) -> str: + """Canonicalize old conditional expressions and statement conditions. + + Expression `if c then x else y` is parenthesized when rewritten so nested + conditionals keep the old tree even though canonical `?:` associates to + the right. Statement `if c { ... }` merely gains condition parentheses. + """ + ts = tokens(source) + asm = assembly_ranges(ts) + keys = delimiter_keys(ts) + + # An `if` is an expression exactly when a same-delimiter `then` occurs + # before its statement body or expression boundary. Nested old `if`s are + # deliberately not skipped: seeing either one's `then` is enough to + # classify the outer token as expression syntax. + expr_ifs: set[int] = set() + for i, tok in enumerate(ts): + if tok.text != "if" or in_ranges(i, asm): + continue + key = keys[i] + for j in range(i + 1, len(ts)): + if keys[j] != key: + continue + if ts[j].text == "then": + expr_ifs.add(i) + break + if ts[j].text in {"{", ";", "}", "=>"}: + break + + # Match if/then/else at each delimiter nesting. A completed inner + # conditional ends immediately before an enclosing then/else. At an + # ordinary expression boundary, all open else branches share that end. + frames: dict[tuple[str, ...], list[dict[str, int | str | None]]] = {} + complete: list[dict[str, int | str | None]] = [] + + def close_else_frames(key: tuple[str, ...], end: int) -> None: + stack = frames.setdefault(key, []) + while stack and stack[-1]["state"] == "else": + frame = stack.pop() + frame["end"] = end + complete.append(frame) + + for i, tok in enumerate(ts): + if in_ranges(i, asm): + continue + key = keys[i] + text = tok.text + if text == "if" and i in expr_ifs: + frames.setdefault(key, []).append( + {"if": i, "then": None, "else": None, "end": None, "state": "cond"} + ) + continue + if text == "then": + close_else_frames(key, tok.start) + stack = frames.setdefault(key, []) + if stack and stack[-1]["state"] == "cond": + stack[-1]["then"] = i + stack[-1]["state"] = "then" + continue + if text == "else": + close_else_frames(key, tok.start) + stack = frames.setdefault(key, []) + if stack and stack[-1]["state"] == "then": + stack[-1]["else"] = i + stack[-1]["state"] = "else" + continue + if text in {",", ";", "=>"}: + close_else_frames(key, tok.start) + elif text in {")", "]", "}"}: + # The key before a closing delimiter still contains that + # delimiter; conditionals inside it end at the close token. + close_else_frames(key, tok.start) + + for stack in frames.values(): + while stack and stack[-1]["state"] == "else": + frame = stack.pop() + frame["end"] = len(source) + complete.append(frame) + for frame in stack: + line = source.count("\n", 0, ts[int(frame["if"])].start) + 1 + warnings.append(f"cannot migrate incomplete conditional expression at line {line}") + + edits: list[tuple[int, int, str]] = [] + boundary_by_start = {tok.start: tok.text for tok in ts} + expression_starts = { + "(", "[", "{", ",", ";", "=", ":", "?", "=>", + "return", "then", "else", + } + for frame in complete: + if_i = int(frame["if"]) + then_i = int(frame["then"]) + else_i = int(frame["else"]) + end = int(frame["end"]) + previous = ts[if_i - 1].text if if_i else None + # Canonical ternaries already associate correctly through their then + # and else branches. Parentheses are needed when this conditional is + # itself another conditional's condition, or appears as an operand of + # a stronger operator. Avoiding redundant parentheses also preserves + # the dedicated excessive-conditional-nesting diagnostic instead of + # turning it into delimiter nesting. + need_parens = ( + boundary_by_start.get(end) == "then" + or (previous is not None and previous not in expression_starts) + ) + edits.extend( + [ + (ts[if_i].start, ts[if_i].end, "(" if need_parens else ""), + (ts[then_i].start, ts[then_i].end, " ? "), + (ts[else_i].start, ts[else_i].end, " : "), + ] + ) + if need_parens: + edits.append((end, end, ")")) + + # Statement conditions: find their same-delimiter opening body brace and + # wrap only when the condition is not already one outer parenthesized + # expression. + forward, _ = pairs(ts) + for i, tok in enumerate(ts): + if tok.text != "if" or i in expr_ifs or in_ranges(i, asm): + continue + key = keys[i] + brace = None + for j in range(i + 1, len(ts)): + if keys[j] == key and ts[j].text == "{": + brace = j + break + if keys[j] == key and ts[j].text in {";", "}", "=>"}: + break + if brace is None or brace == i + 1: + continue + already_parenthesized = ( + ts[i + 1].text == "(" + and forward.get(i + 1) == brace - 1 + ) + if not already_parenthesized: + edits.append((tok.end, tok.end, " (")) + edits.append((ts[brace].start, ts[brace].start, ") ")) + + return apply_edits(source, edits) + + +def transform_core_colon_equals(source: str) -> str: + ts = tokens(source) + asm = assembly_ranges(ts) + edits = [ + (tok.start, tok.end, "=") + for i, tok in enumerate(ts) + if tok.text == ":=" and not in_ranges(i, asm) + ] + return apply_edits(source, edits) + + +def transform_expression_annotations(source: str, warnings: list[str]) -> str: + """Remove legacy expected-type annotations from expressions. + + The canonical syntax gets expected types from the surrounding return, + argument, assignment, or typed-binding context. Declaration/predicate + colons and ternary separators are protected explicitly; every remaining + colon which is followed by an old type is a legacy expression annotation. + """ + ts = tokens(source) + asm = assembly_ranges(ts) + forward, _ = pairs(ts) + protected: set[int] = set() + + # Named parameter colons for functions, constructors, fallbacks, and + # lambdas. Only top-level entries in the parameter list bind names. + for i, tok in enumerate(ts): + if tok.text not in {"function", "constructor", "fallback", "lam"} or in_ranges(i, asm): + continue + j = i + 1 + while j < len(ts) and ts[j].text != "(" and ts[j].text not in {"{", ";"}: + j += 1 + end = forward.get(j) + if end is None: + continue + depth = 0 + for k in range(j + 1, end): + if ts[k].text in "([": + depth += 1 + elif ts[k].text in ")]" and depth: + depth -= 1 + elif ts[k].text == ":" and depth == 0: + protected.add(k) + + # Typed locals. + for i, tok in enumerate(ts[:-2]): + if tok.text == "let" and ts[i + 2].text == ":" and not in_ranges(i, asm): + protected.add(i + 2) + + # Where-clause predicates. The clause terminates at the declaration body + # or method-signature semicolon. + for i, tok in enumerate(ts): + if tok.text != "where" or in_ranges(i, asm): + continue + j = i + 1 + depth = 0 + while j < len(ts): + if ts[j].text in "([": + depth += 1 + elif ts[j].text in ")]" and depth: + depth -= 1 + elif depth == 0 and ts[j].text in {"{", ";"}: + break + elif ts[j].text == ":": + protected.add(j) + j += 1 + + # Protect only direct contract members. A bare `expr : T;` at the start + # of a function statement is an annotation, not a field. + for i, tok in enumerate(ts): + if tok.text != "contract" or in_ranges(i, asm): + continue + opening = i + 1 + while opening < len(ts) and ts[opening].text != "{": + opening += 1 + closing = forward.get(opening) + if closing is None: + continue + depth = 0 + for j in range(opening + 1, closing - 1): + if ts[j].text == "{": + depth += 1 + continue + if ts[j].text == "}" and depth: + depth -= 1 + continue + boundary = j == opening + 1 or ts[j - 1].text in {"}", ";"} + if ( + depth == 0 + and boundary + and re.fullmatch(r"[A-Za-z_$][A-Za-z0-9_$-]*", ts[j].text) + and ts[j + 1].text == ":" + ): + protected.add(j + 1) + + # Pair each ternary question mark with its same-nesting colon. A stack is + # needed for right-nested conditional expressions. + delimiter_stack: list[str] = [] + questions: dict[tuple[str, ...], list[int]] = {} + matching = {")": "(", "]": "[", "}": "{"} + for i, tok in enumerate(ts): + if in_ranges(i, asm): + continue + if tok.text in "([{": + delimiter_stack.append(tok.text) + continue + if tok.text in matching: + if delimiter_stack and delimiter_stack[-1] == matching[tok.text]: + delimiter_stack.pop() + continue + key = tuple(delimiter_stack) + if tok.text == "?": + questions.setdefault(key, []).append(i) + elif tok.text == ":" and questions.get(key): + questions[key].pop() + protected.add(i) + + edits = [] + for i, tok in enumerate(ts): + if tok.text != ":" or i in protected or in_ranges(i, asm): + continue + parser = TypeParser(ts[i + 1 :]) + try: + parser.parse() + except ValueError as error: + line = source.count("\n", 0, tok.start) + 1 + warnings.append(f"cannot remove expression annotation at line {line}: {error}") + continue + if parser.i == 0: + continue + end = ts[i + parser.i] + edits.append((tok.start, end.end, "")) + return apply_edits(source, edits) + + +def transform_matches(source: str, warnings: list[str]) -> str: + # Match bodies need nested statement-aware brace insertion. Process the + # innermost match first and retokenize after every replacement. + while True: + ts = tokens(source) + asm = assembly_ranges(ts) + forward, _ = pairs(ts) + candidate = None + for i, tok in enumerate(ts): + if tok.text != "match" or in_ranges(i, asm): + continue + j = i + 1 + if j < len(ts) and ts[j].text == "(" and j in forward: + after = forward[j] + 1 + if after < len(ts) and ts[after].text == "{": + j = after + else: + j = i + 1 + if j == i + 1: + depth = 0 + while j < len(ts): + if ts[j].text in "([": depth += 1 + elif ts[j].text in ")]" and depth: depth -= 1 + elif ts[j].text == "{" and depth == 0: break + j += 1 + if j == len(ts) or j not in forward: + continue + match_body = ts[j + 1 : forward[j]] + # Canonical bodies begin with case/default. Parentheses around an + # old scrutinee do not make a pipe-arm body canonical. + if not legacy_match_arm_starts(match_body): + continue + candidate = (i, j, forward[j]) + if candidate is None: + return source + i, brace, end = candidate + body = ts[brace + 1:end] + arms = [] + max_pattern_arity = 1 + starts = legacy_match_arm_starts(body) + if not starts: + warnings.append("match has no recognizable legacy arms") + return source + for n, start in enumerate(starts): + stop = starts[n + 1] if n + 1 < len(starts) else len(body) + arm = body[start + 1:stop] + fat = top_index(arm, {"=>"}, angles=False) + if fat is None: + warnings.append("match arm has no =>") + return source + pats = arm[:fat] + pat_parts = [part for part in split_top(pats, angles=False) if part] + max_pattern_arity = max(max_pattern_arity, len(pat_parts)) + wildcard = bool(pat_parts) and all( + len(part) == 1 and part[0].text == "_" for part in pat_parts + ) + if wildcard: + head = "default" + else: + pat = source[body[start].end : arm[fat].start].strip() + if len(pat_parts) > 1: + pat = "(" + pat + ")" + head = "case " + pat + body_end = body[stop].start if stop < len(body) else ts[end].start + stmts = source[arm[fat].end : body_end].strip() + arms.append(head + " {\n" + stmts + "\n}") + scrutinee_ts = ts[i + 1:brace] + if len(scrutinee_ts) >= 2 and scrutinee_ts[0].text == "(" and scrutinee_ts[-1].text == ")": + local_forward, _ = pairs(scrutinee_ts) + if local_forward.get(0) == len(scrutinee_ts) - 1: + inner = scrutinee_ts[1:-1] + tuple_scrutinee = len( + [part for part in split_top(inner, angles=False) if part] + ) > 1 + # Legacy `match (a, b) { | x => ... }` has one tuple + # scrutinee. Canonical match parentheses delimit a scrutinee + # list, so retain the expression parentheses as a nested pair. + # Multi-pattern arms (`| p, q =>`) identify the genuinely + # multi-scrutinee form and may drop the legacy wrapper. + if not tuple_scrutinee or max_pattern_arity > 1: + scrutinee_ts = inner + scrutinees = source_slice(source, scrutinee_ts).strip() + leading = source[ts[brace].end : body[starts[0]].start].strip() + contents = ((leading + "\n") if leading else "") + "\n".join(arms) + replacement = "match (" + scrutinees + ") {\n" + contents + "\n}" + replace_end = ts[end + 1].end if end + 1 < len(ts) and ts[end + 1].text == ";" else ts[end].end + source = apply_edits(source, [(ts[i].start, replace_end, replacement)]) + + +def legacy_match_arm_starts(body: Sequence[Tok]) -> list[int]: + """Return top-level pipes which introduce a legacy `| pat =>` arm. + + A top-level bitwise-or in an arm body is not an arm separator. A candidate + pipe counts only when a top-level fat arrow occurs before the next + top-level pipe. + """ + pipes: list[int] = [] + depth = 0 + for i, tok in enumerate(body): + if tok.text in "({[": + depth += 1 + elif tok.text in ")}]" and depth: + depth -= 1 + elif tok.text == "|" and depth == 0: + pipes.append(i) + starts = [] + for position, start in enumerate(pipes): + stop = pipes[position + 1] if position + 1 < len(pipes) else len(body) + depth = 0 + for tok in body[start + 1 : stop]: + if tok.text in "({[": + depth += 1 + elif tok.text in ")}]" and depth: + depth -= 1 + elif tok.text == "=>" and depth == 0: + starts.append(start) + break + return starts + + +def tracked_targets() -> list[pathlib.Path]: + output = subprocess.check_output( + ["git", "ls-files", "--", "*.solc"], cwd=ROOT, text=True + ) + targets = [] + for relative in output.splitlines(): + if not ( + relative.startswith("std/") + or relative.startswith("tests/e2e/") + or relative.startswith("fuzz/corpus/") + or re.match(r"^crates/[^/]+/tests/fixtures/", relative) + ): + continue + path = ROOT / relative + if not path.exists(): + path = path.with_suffix(".sol") + if path.exists(): + targets.append(path) + return targets + + +def unsafe_paths() -> set[str]: + unsafe = set() + manifest = ROOT / "crates/parser/tests/fixtures/corpus/reference-frontend.tsv" + if manifest.exists(): + for line in manifest.read_text().splitlines(): + cols = line.split("\t") + if len(cols) >= 3 and cols[1:3] == ["fail", "SC0001"]: + name = pathlib.Path(cols[0]).with_suffix(".solc").as_posix() + unsafe.add("crates/parser/tests/fixtures/corpus/fail/test/examples/" + name) + unsafe.update( + { + "crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.solc", + "crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.solc", + } + ) + for path in subprocess.check_output( + ["git", "ls-files", "--", "crates/uitest/tests/fixtures/parse/*.solc", "crates/uitest/tests/fixtures/parse/**/*.solc"], + cwd=ROOT, + text=True, + ).splitlines(): + unsafe.add(path) + return unsafe + + +def old_relative(path: pathlib.Path) -> str: + relative = path.relative_to(ROOT).as_posix() + return relative[:-4] + ".solc" if relative.endswith(".sol") else relative + + +def migrate(source: str, warnings: list[str]) -> str: + source = transform_imports(source, warnings) + source = transform_data(source, warnings) + source = transform_declarations(source, warnings) + source = transform_signature_type_contexts(source, warnings) + source = transform_type_contexts(source, warnings) + source = transform_proxy_annotations(source) + source = transform_matches(source, warnings) + source = transform_conditionals(source, warnings) + source = transform_core_colon_equals(source) + source = transform_expression_annotations(source, warnings) + return source + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--check", action="store_true", help="report changes without writing") + parser.add_argument("paths", nargs="*", help="optional repository-relative source paths") + args = parser.parse_args() + + targets = [ROOT / path for path in args.paths] if args.paths else tracked_targets() + unsafe = unsafe_paths() + changed = 0 + report = [ + "# Syntax migration exceptions", + "", + "The following tracked sources required a conservative migration or", + "still contain an intentionally malformed construct. Intentional", + "parser-error fixtures are not skipped wholesale: independent syntax", + "around the error is rewritten normally.", + "Paths use their pre-extension-migration `.solc` spelling.", + "", + ] + for path in targets: + relative = old_relative(path) + intentional_error = relative in unsafe + original = path.read_text() + warnings: list[str] = [] + try: + migrated = migrate(original, warnings) + except (ValueError, IndexError) as error: + migrated = original + warnings.append(f"file-level migration failure: {error}") + if warnings: + for warning in sorted(set(warnings)): + fixture = "intentional parser-error fixture; " if intentional_error else "" + report.append(f"- `{relative}` — {fixture}{warning}") + if migrated != original: + changed += 1 + if not args.check: + path.write_text(migrated) + + report_text = "\n".join(report) + "\n" + if not args.check: + REPORT.write_text(report_text) + print(f"{len(targets)} source files inspected; {changed} would change" if args.check else f"{len(targets)} source files inspected; {changed} changed") + if args.check and changed: + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 7068ade99b34843cee89e84750378c03e42d8cae Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:15:07 +0900 Subject: [PATCH 003/110] Add canonical syntax migration tools: embedded source migration Co-authored-by: Codex --- scripts/migrate-embedded-syntax.py | 899 +++++++++++++++++++++++++++++ 1 file changed, 899 insertions(+) create mode 100644 scripts/migrate-embedded-syntax.py diff --git a/scripts/migrate-embedded-syntax.py b/scripts/migrate-embedded-syntax.py new file mode 100644 index 00000000..434ead6d --- /dev/null +++ b/scripts/migrate-embedded-syntax.py @@ -0,0 +1,899 @@ +#!/usr/bin/env python3 +"""Migrate legacy Solcore syntax inside Rust, TypeScript, and JavaScript strings. + +Only literals containing recognizable Solcore declarations are rewritten. +Rust format templates are decoded with interpolation placeholders protected, +then their literal source braces are escaped again after migration. This is a +temporary migration aid for the syntax cut-over. +""" + +from __future__ import annotations + +import argparse +import importlib.util +import re +import sys +from pathlib import Path + + +IDENT = re.compile(r"[A-Za-z_][A-Za-z0-9_]*") +PRESERVE_NEXT_LITERAL_MARKER = "syntax-migration: preserve-next-literal" +PRESERVE_LITERALS_BEGIN_MARKER = "syntax-migration: preserve-literals-begin" +PRESERVE_LITERALS_END_MARKER = "syntax-migration: preserve-literals-end" + + +def load_source_migrator(): + path = Path(__file__).with_name("migrate-syntax.py") + if not path.is_file(): + return None + spec = importlib.util.spec_from_file_location("solcore_source_migrator", path) + if spec is None or spec.loader is None: + return None + module = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + return module + + +SOURCE_MIGRATOR = load_source_migrator() +SOURCE_MARKER = re.compile( + r"(?m)^\s*(?:(?:import|export|pragma)\b[^\n;]*;|type\s+[A-Za-z_][A-Za-z0-9_]*\s*=|" + r"data\s+[A-Za-z_][A-Za-z0-9_.,:()<> \t-]*(?:=|;)|" + r"(?:enum|class|trait|instance)\s+[A-Za-z_(][A-Za-z0-9_.,:()<> \t-]*\{|" + r"impl(?:\s*<[^{}\n>]*>)?\s+[A-Za-z_(][A-Za-z0-9_.,:()<> \t-]*\{|" + r"default\s+(?:instance\s+|impl(?:\s*<[^{}\n>]*>)?\s+)[A-Za-z_(][A-Za-z0-9_.,:()<> \t-]*\{|" + r"function\s+[A-Za-z_][A-Za-z0-9_]*\s*(?:<[^\n>]+>)?\s*\(|" + r"contract\s+[A-Za-z_][A-Za-z0-9_]*\s*\{|(?:constructor|fallback)\s*\(|" + r"(?:public|payable)(?:\s+(?:public|payable))*\s+function\s+" + r"[A-Za-z_][A-Za-z0-9_]*\s*(?:<[^\n>]+>)?\s*\()" +) +MATCH_SOURCE_MARKER = re.compile( + r"(?m)^\s*match\s*(?:\([^\n{}]*\)|[A-Za-z_][A-Za-z0-9_.]*)\s*\{\s*" + r"(?:\||case\b|default\b|})" +) + + +def matching_paren(text: str, start: int) -> int | None: + pairs = {"(": ")", "[": "]", "<": ">"} + opening = text[start] + closing = pairs[opening] + depth = 0 + for index in range(start, len(text)): + char = text[index] + if char == opening: + depth += 1 + elif char == closing and not ( + opening == "<" and index > start and text[index - 1] in "=-" + ): + depth -= 1 + if depth == 0: + return index + return None + + +def split_top_level(text: str, delimiter: str = ",") -> list[str]: + parts: list[str] = [] + start = 0 + paren = bracket = angle = 0 + for index, char in enumerate(text): + if char == "(": + paren += 1 + elif char == ")": + paren -= 1 + elif char == "[": + bracket += 1 + elif char == "]": + bracket -= 1 + elif char == "<": + angle += 1 + elif char == ">" and angle and (index == 0 or text[index - 1] not in "=-"): + angle -= 1 + elif char == delimiter and paren == bracket == angle == 0: + parts.append(text[start:index]) + start = index + 1 + parts.append(text[start:]) + return parts + + +def top_level_arrow(text: str) -> int | None: + paren = bracket = angle = 0 + index = 0 + while index + 1 < len(text): + char = text[index] + if char == "(": + paren += 1 + elif char == ")": + paren -= 1 + elif char == "[": + bracket += 1 + elif char == "]": + bracket -= 1 + elif char == "<": + angle += 1 + elif text[index : index + 2] == "->" and paren == bracket == angle == 0: + return index + elif char == ">" and angle and (index == 0 or text[index - 1] not in "=-"): + angle -= 1 + index += 1 + return None + + +def convert_type(text: str) -> str: + leading = text[: len(text) - len(text.lstrip())] + trailing = text[len(text.rstrip()) :] + core = text.strip() + if not core: + return text + + if core == "()": + return leading + core + trailing + + canonical_fn = re.fullmatch( + r"function\s*\((?P.*)\)\s*returns\s*\((?P.*)\)", + core, + re.S, + ) + if canonical_fn: + params = ",".join(convert_type(part) for part in split_top_level(canonical_fn.group("params"))) + ret = convert_type(canonical_fn.group("ret")) + return f"{leading}function({params}) returns({ret}){trailing}" + + arrow = top_level_arrow(core) + if arrow is not None: + lhs = convert_type(core[:arrow]).strip() + rhs = convert_type(core[arrow + 2 :]) + # Parentheses here describe the function parameter list. Preserve a + # doubly-parenthesized tuple parameter as one tuple parameter. + if lhs == "()": + params = "" + elif lhs.startswith("(") and lhs.endswith(")"): + params = lhs[1:-1] + else: + params = lhs + return f"{leading}function({params}) returns({rhs.strip()}){trailing}" + + out: list[str] = [] + index = 0 + while index < len(core): + comptime = re.match(r"comptime\s+", core[index:]) + if comptime: + atom_start = index + comptime.end() + atom_match = IDENT.match(core, atom_start) + if atom_match: + atom_end = atom_match.end() + while atom_end < len(core) and core[atom_end] == ".": + segment = IDENT.match(core, atom_end + 1) + if not segment: + break + atom_end = segment.end() + if atom_end < len(core) and core[atom_end] == "(": + close = matching_paren(core, atom_end) + if close is not None: + atom_end = close + 1 + atom = convert_type(core[atom_start:atom_end]) + out.append(f"comptime<{atom}>") + index = atom_end + continue + + match = IDENT.match(core, index) + if match: + name_end = match.end() + while name_end < len(core) and core[name_end] == ".": + segment = IDENT.match(core, name_end + 1) + if not segment: + break + name_end = segment.end() + name = core[index:name_end] + if name_end < len(core) and core[name_end] in "(<": + opener = core[name_end] + close = matching_paren(core, name_end) + if close is not None: + inner = core[name_end + 1 : close] + converted = [convert_type(part) for part in split_top_level(inner)] + mapping_arrow = top_level_fat_arrow(inner) + if name == "mapping" and mapping_arrow is not None: + key = convert_type(inner[:mapping_arrow]).strip() + value = convert_type(inner[mapping_arrow + 2 :]).strip() + out.append(f"mapping({key} => {value})") + elif name == "mapping" and len(converted) == 2: + out.append(f"mapping({converted[0]} => {converted[1]})") + elif name == "function": + out.append(f"function({','.join(converted)})") + elif name == "returns": + out.append(f"returns ({','.join(converted)})") + else: + out.append(f"{name}<{','.join(converted)}>") + index = close + 1 + continue + out.append(name) + index = name_end + continue + + if core[index] == "(": + close = matching_paren(core, index) + if close is not None: + inner = core[index + 1 : close] + out.append("(" + ",".join(convert_type(part) for part in split_top_level(inner)) + ")") + index = close + 1 + continue + out.append(core[index]) + index += 1 + return leading + "".join(out) + trailing + + +def top_level_fat_arrow(text: str) -> int | None: + paren = bracket = angle = 0 + index = 0 + while index + 1 < len(text): + char = text[index] + if char == "(": + paren += 1 + elif char == ")": + paren -= 1 + elif char == "[": + bracket += 1 + elif char == "]": + bracket -= 1 + elif text[index : index + 2] == "=>" and paren == bracket == angle == 0: + return index + elif char == "<": + angle += 1 + elif char == ">" and angle and (index == 0 or text[index - 1] not in "=-"): + angle -= 1 + index += 1 + return None + + +def find_top_level_colon(text: str) -> int | None: + paren = bracket = angle = 0 + for index, char in enumerate(text): + if char == "(": + paren += 1 + elif char == ")": + paren -= 1 + elif char == "[": + bracket += 1 + elif char == "]": + bracket -= 1 + elif char == "<": + angle += 1 + elif char == ">" and angle and (index == 0 or text[index - 1] not in "=-"): + angle -= 1 + elif char == ":" and paren == bracket == angle == 0: + return index + return None + + +def convert_predicate(text: str) -> str: + stripped = text.strip() + colon = find_top_level_colon(stripped) + if colon is None: + return stripped + subject = convert_type(stripped[:colon]) + class_ref = stripped[colon + 1 :].strip() + match = re.fullmatch(r"([A-Za-z_][A-Za-z0-9_.]*)(?:\((.*)\))?", class_ref, re.S) + if match and match.group(2) is not None: + args = ",".join(convert_type(part) for part in split_top_level(match.group(2))) + class_ref = f"{match.group(1)}<{args}>" + return f"{subject}: {class_ref}" + + +def convert_predicates(text: str) -> str: + return ", ".join(convert_predicate(part) for part in split_top_level(text)) + + +def convert_params(text: str) -> str: + converted: list[str] = [] + for part in split_top_level(text): + colon = find_top_level_colon(part) + if colon is None: + converted.append(part) + else: + converted.append(part[: colon + 1] + convert_type(part[colon + 1 :])) + return ",".join(converted) + + +def convert_imports(source: str) -> str: + pattern = re.compile( + r"\bimport\s+(@?[A-Za-z_][A-Za-z0-9_.]*)\.\{([^{}]+)\}\s*;" + ) + + def selected(match: re.Match[str]) -> str: + path, names = match.groups() + names = names.strip() + if names == "*": + return f"import * from {path};" + return f"import {{{names}}} from {path};" + + source = pattern.sub(selected, source) + source = re.sub( + r"\bimport\s+(@?[A-Za-z_][A-Za-z0-9_.]*)\s+as\s+([A-Za-z_][A-Za-z0-9_]*)\s*;", + r"import * as \2 from \1;", + source, + ) + return source + + +DATA = re.compile( + r"^(?P[ \t]*)data\s+(?P[A-Za-z_][A-Za-z0-9_]*)" + r"(?:\((?P[^()\n]*)\))?\s*(?:=\s*(?P.*?))?;(?P[ \t]*)$", + re.M | re.S, +) + + +def convert_ctor(ctor: str) -> str: + match = re.fullmatch(r"(\s*[A-Za-z_][A-Za-z0-9_]*\s*)\((.*)\)(\s*)", ctor, re.S) + if not match: + return ctor + fields = ",".join(convert_type(part) for part in split_top_level(match.group(2))) + return f"{match.group(1)}({fields}){match.group(3)}" + + +def convert_data(source: str) -> str: + def replacement(match: re.Match[str]) -> str: + indent = match.group("indent") + name = match.group("name") + params = match.group("params") + body = match.group("body") + generic = "" if params is None else f"<{params}>" + if body is None: + return f"{indent}enum {name}{generic} {{}}{match.group('tail')}" + ctors = split_top_level(body, "|") + converted = ",".join(convert_ctor(ctor) for ctor in ctors) + return f"{indent}enum {name}{generic} {{{converted}}}{match.group('tail')}" + + return DATA.sub(replacement, source) + + +def parse_legacy_class_header(line: str) -> str | None: + match = re.match( + r"^(?P\s*)(?:forall\s+(?P[^.\n]+)\s*\.\s*)?" + r"(?:(?P.*?)\s*=>\s*)?class\s+" + r"(?P[A-Za-z_][A-Za-z0-9_]*)\s*:\s*" + r"(?P[A-Za-z_][A-Za-z0-9_]*)" + r"(?:\((?P.*)\))?\s*(?P\{.*)$", + line, + ) + if not match: + return None + params = [match.group("subject")] + if match.group("args"): + params.extend(part.strip() for part in split_top_level(match.group("args"))) + result = f"{match.group('indent')}trait {match.group('class')}<{','.join(params)}>" + if match.group("constraints"): + result += f" where {convert_predicates(match.group('constraints'))}" + return result + " " + match.group("rest") + + +def split_impl_head(text: str) -> tuple[str, str, str | None] | None: + colon = find_top_level_colon(text) + if colon is None: + return None + subject = text[:colon].strip() + class_ref = text[colon + 1 :].strip() + match = re.fullmatch(r"([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?", class_ref, re.S) + if not match: + return None + return subject, match.group(1), match.group(2) + + +def parse_legacy_impl_header(line: str) -> str | None: + match = re.match( + r"^(?P\s*)(?:forall\s+(?P[^.\n]+)\s*\.\s*)?" + r"(?:(?P.*?)\s*=>\s*)?" + r"(?Pdefault\s+)?instance\s+(?P.*?)\s*(?P\{.*)$", + line, + ) + if not match: + return None + parsed = split_impl_head(match.group("head")) + if parsed is None: + return None + subject, class_name, args = parsed + head_args = [convert_type(subject)] + if args is not None: + head_args.extend(convert_type(part) for part in split_top_level(args)) + prefix = "default impl" if match.group("default") else "impl" + vars_text = match.group("vars") + generics = "" + if vars_text: + generics = "<" + ",".join(vars_text.replace(",", " ").split()) + ">" + result = ( + f"{match.group('indent')}{prefix}{generics} {class_name}" + f"<{','.join(head_args)}>" + ) + if match.group("constraints"): + result += f" where {convert_predicates(match.group('constraints'))}" + return result + " " + match.group("rest") + + +FUNCTION_PREFIX = re.compile( + r"^(?P\s*)" + r"(?:(?Pforall\s+(?P[^.\n]+)\s*\.\s*))?" + r"(?:(?P.*?)\s*=>\s*)?" + r"(?P(?:(?:public|payable)\s+)*)function\s+" + r"(?P[A-Za-z_][A-Za-z0-9_]*)" +) + + +def parse_legacy_function_header(line: str, inherited_vars: str | None = None) -> str | None: + match = FUNCTION_PREFIX.match(line) + if not match: + return None + cursor = match.end() + if cursor >= len(line) or line[cursor] != "(": + return None + params_end = matching_paren(line, cursor) + if params_end is None: + return None + params_text = line[cursor + 1 : params_end] + tail = line[params_end + 1 :].lstrip() + suffix_match = re.match(r"(?P(?:(?:public|payable)\s+)*)", tail) + assert suffix_match is not None + suffix = suffix_match.group("mods") + tail = tail[suffix_match.end() :] + ret: str | None = None + if tail.startswith("->"): + tail = tail[2:].lstrip() + boundary = None + paren = bracket = angle = 0 + for index, char in enumerate(tail): + if char == "(": + paren += 1 + elif char == ")": + paren -= 1 + elif char == "[": + bracket += 1 + elif char == "]": + bracket -= 1 + elif char == "<": + angle += 1 + elif char == ">" and angle: + angle -= 1 + elif char in "{;" and paren == bracket == angle == 0: + boundary = index + break + if boundary is None: + return None + ret = tail[:boundary].strip() + end = tail[boundary:] + elif tail.startswith(("{", ";")): + end = tail + else: + return None + # Already-canonical headers do not need reconstruction. + if not match.group("forall") and ret is None and not match.group("prefix"): + return None + params = "(" + convert_params(params_text) + ")" + vars_text = match.group("vars") or inherited_vars + generics = "" + if vars_text: + generics = "<" + ",".join(vars_text.replace(",", " ").split()) + ">" + modifiers = (match.group("prefix") + suffix).split() + modifier_text = "" if not modifiers else " " + " ".join(dict.fromkeys(modifiers)) + result = f"{match.group('indent')}function {match.group('name')}{generics}{params}{modifier_text}" + if ret is not None: + converted_ret = convert_type(ret) + result += " returns " + ("()" if converted_ret.strip() == "()" else f"({converted_ret})") + if match.group("constraints"): + result += f" where {convert_predicates(match.group('constraints'))}" + return result + " " + end + + +def brace_delta(line: str) -> int: + # Good enough for source fixtures: braces in comments/string literals do + # not occur on assembly boundary lines in the migrated corpus. + return line.count("{") - line.count("}") + + +def convert_headers(source: str) -> str: + # Legacy `forall ... . constraints =>` prefixes may span one or more + # lines. Coalesce just those prefixes so the structural header parsers can + # see the complete declaration, then restore the declaration indentation. + source = re.sub( + r"(?m)^(?P[ \t]*)forall\s+(?P[^.\n]+)\s*\.\s*\n" + r"(?:(?P[^\n]+?)\s*=>\s*\n)?" + r"(?P
[ \t]*(?:function|class|instance|default\s+instance)\b)", + lambda m: ( + f"{m.group('indent')}forall {m.group('vars')} . " + + (f"{m.group('constraints').strip()} => " if m.group("constraints") else "") + + m.group("header").lstrip() + ), + source, + ) + source = re.sub( + r"(?m)^(?P[ \t]*)forall\s+(?P[^.\n]+)\s*\.\s*" + r"(?P[^\n=]+?)\s*=>\s*\n" + r"(?P
[ \t]*(?:function|class|instance|default\s+instance)\b)", + lambda m: ( + f"{m.group('indent')}forall {m.group('vars')} . " + f"{m.group('constraints').strip()} => {m.group('header').lstrip()}" + ), + source, + ) + lines = source.splitlines(keepends=True) + output: list[str] = [] + assembly_depth = 0 + pending_forall: str | None = None + for original in lines: + newline = "\n" if original.endswith("\n") else "" + line = original[:-1] if newline else original + in_assembly = assembly_depth > 0 + if not in_assembly: + forall_only = re.match(r"^\s*forall\s+([^.\n]+)\s*\.\s*$", line) + if forall_only: + pending_forall = forall_only.group(1) + continue + converted = ( + parse_legacy_class_header(line) + or parse_legacy_impl_header(line) + or parse_legacy_function_header(line, pending_forall) + ) + if converted is not None: + line = converted + pending_forall = None + elif line.strip() and not line.strip().startswith("//"): + pending_forall = None + if not in_assembly and re.search(r"\bassembly(?:\s*\([^)]*\))?\s*\{", line): + assembly_depth = max(0, brace_delta(line)) + elif in_assembly: + assembly_depth = max(0, assembly_depth + brace_delta(line)) + output.append(line + newline) + return "".join(output) + + +def convert_signature_types(source: str) -> str: + # A second pass over canonicalized function headers converts every + # parameter/return type, including headers whose return was `()` and thus + # looked canonical enough to the legacy-header pass. + lines = source.splitlines(keepends=True) + output: list[str] = [] + assembly_depth = 0 + for original in lines: + newline = "\n" if original.endswith("\n") else "" + line = original[:-1] if newline else original + if assembly_depth == 0: + match = re.match( + r"^(?P\s*)function\s+(?P[A-Za-z_][A-Za-z0-9_]*)" + r"(?P<[^>]+>)?", + line, + ) + if match: + params_start = match.end() + if params_start < len(line) and line[params_start] == "(": + params_end = matching_paren(line, params_start) + if params_end is not None: + params = convert_params(line[params_start + 1 : params_end]) + tail = line[params_end + 1 :] + returns = re.search(r"\breturns\s*\(", tail) + if returns: + ret_start = tail.find("(", returns.start()) + ret_end = matching_paren(tail, ret_start) + if ret_end is not None: + ret_parts = split_top_level(tail[ret_start + 1 : ret_end]) + ret = ",".join(convert_type(part) for part in ret_parts) + tail = tail[: ret_start + 1] + ret + tail[ret_end:] + line = ( + f"{match.group('indent')}function {match.group('name')}" + f"{match.group('generics') or ''}({params}){tail}" + ) + if assembly_depth == 0 and re.search(r"\bassembly(?:\s*\([^)]*\))?\s*\{", line): + assembly_depth = max(0, brace_delta(line)) + elif assembly_depth: + assembly_depth = max(0, assembly_depth + brace_delta(line)) + output.append(line + newline) + return "".join(output) + + +def convert_match_body(body: str) -> str: + # Legacy arms start at `|` and are separated by the next top-level `|` or + # the match body's closing brace. Arm bodies are statements rather than + # expressions, so they may be wrapped in braces without semantic change. + out: list[str] = [] + cursor = 0 + while cursor < len(body): + arm = re.search(r"(?m)^(?P[ \t]*)\|\s*", body[cursor:]) + if arm is None: + out.append(body[cursor:]) + break + start = cursor + arm.start() + marker_end = cursor + arm.end() + out.append(body[cursor:start]) + arrow = body.find("=>", marker_end) + if arrow < 0: + out.append(body[start:]) + break + pattern = body[marker_end:arrow].strip() + body_start = arrow + 2 + paren = bracket = brace = 0 + scan = body_start + next_arm: int | None = None + while scan < len(body): + char = body[scan] + if char == "(": + paren += 1 + elif char == ")": + paren -= 1 + elif char == "[": + bracket += 1 + elif char == "]": + bracket -= 1 + elif char == "{": + brace += 1 + elif char == "}": + brace -= 1 + elif ( + char == "|" + and paren == bracket == brace == 0 + and body[body.rfind("\n", 0, scan) + 1 : scan].strip() == "" + ): + next_arm = scan + break + scan += 1 + arm_end = next_arm if next_arm is not None else len(body) + statements = body[body_start:arm_end] + newline_prefix = statements[: len(statements) - len(statements.lstrip(" \t"))] + statements = statements.strip() + keyword = "default" if pattern == "_" else f"case {pattern}" + indent = arm.group("indent") + if statements.startswith("{") and statements.endswith("}"): + converted = f"{indent}{keyword} {statements}" + elif "\n" in statements: + converted = f"{indent}{keyword} {{\n{statements}\n{indent}}}" + else: + converted = f"{indent}{keyword} {{ {statements} }}" + out.append(converted) + if next_arm is not None: + out.append("\n") + cursor = next_arm + else: + cursor = len(body) + return "".join(out) + + +def convert_match_statements(source: str) -> str: + out: list[str] = [] + cursor = 0 + match_re = re.compile(r"\bmatch\s*(?P\([^\n{}]*\)|[^\n{}]+?)\s*\{") + while True: + match = match_re.search(source, cursor) + if match is None: + out.append(source[cursor:]) + break + # Skip matches nested in an assembly block; Yul switch/match syntax is + # outside this migration. + prefix = source[cursor : match.start()] + if prefix.rfind("assembly") > prefix.rfind("}"): + out.append(source[cursor : match.end()]) + cursor = match.end() + continue + open_brace = match.end() - 1 + depth = 1 + scan = open_brace + 1 + while scan < len(source) and depth: + if source[scan] == "{": + depth += 1 + elif source[scan] == "}": + depth -= 1 + scan += 1 + if depth: + out.append(source[cursor:]) + break + close_brace = scan - 1 + scrutinee = match.group("scrutinee").strip() + if not (scrutinee.startswith("(") and scrutinee.endswith(")")): + scrutinee = f"({scrutinee})" + out.append(source[cursor : match.start()]) + out.append(f"match {scrutinee} {{") + out.append(convert_match_body(source[open_brace + 1 : close_brace])) + out.append("}") + cursor = close_brace + 1 + return "".join(out) + + +def convert_typed_lets_and_fields(source: str) -> str: + lines = source.splitlines(keepends=True) + output: list[str] = [] + assembly_depth = 0 + for original in lines: + newline = "\n" if original.endswith("\n") else "" + line = original[:-1] if newline else original + if assembly_depth == 0: + # Typed local bindings are unambiguous because they begin with let. + let_match = re.match( + r"^(?P\s*let\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*)" + r"(?P.*?)(?P\s*(?:=|:=|;).*)$", + line, + ) + if let_match: + line = let_match.group("prefix") + convert_type(let_match.group("ty")) + let_match.group("tail") + # Contract fields are also line-oriented (`name: Type [= expr];`). + field = re.match( + r"^(?P\s*[A-Za-z_][A-Za-z0-9_]*\s*:\s*)" + r"(?P.*?)(?P\s*(?:=\s*.*)?;\s*)$", + line, + ) + if field and not line.lstrip().startswith(("case ", "default ")): + line = field.group("prefix") + convert_type(field.group("ty")) + field.group("tail") + if assembly_depth == 0 and re.search(r"\bassembly(?:\s*\([^)]*\))?\s*\{", line): + assembly_depth = max(0, brace_delta(line)) + elif assembly_depth: + assembly_depth = max(0, assembly_depth + brace_delta(line)) + output.append(line + newline) + return "".join(output) + + +def convert_constructor_modifiers(source: str) -> str: + pattern = re.compile( + r"(?m)^(?P[ \t]*)(?P(?:(?:public|payable)\s+)+)" + r"(?Pconstructor|fallback)(?P\([^\n]*\))" + ) + + def replacement(match: re.Match[str]) -> str: + mods = " ".join(dict.fromkeys(match.group("mods").split())) + # public is implicit and diagnosed by the new grammar; preserving it + # after the parameters lets negative modifier tests keep their intent. + return ( + f"{match.group('indent')}{match.group('kind')}{match.group('params')}" + f" {mods}" + ) + + source = pattern.sub(replacement, source) + + fallback = re.compile( + r"(?m)^(?P[ \t]*)(?P(?:(?:public|payable)\s+)*)" + r"fallback(?P\([^()\n{}]*\))(?P[^\n{}]*)\{" + ) + + def canonical_fallback(match: re.Match[str]) -> str: + modifiers = [ + word + for word in (match.group("prefix") + " " + match.group("tail")).split() + if word in {"public", "payable"} + ] + modifier_text = "" if not modifiers else " " + " ".join(dict.fromkeys(modifiers)) + return f"{match.group('indent')}fallback{match.group('params')}{modifier_text} {{" + + return fallback.sub(canonical_fallback, source) + + +def _conditional_keyword( + ts, start: int, choices: set[str] +) -> int | None: + """Find a conditional keyword outside nested delimiters.""" + depth = {"(": 0, "[": 0, "{": 0} + closing = {")": "(", "]": "[", "}": "{"} + for index in range(start, len(ts)): + text = ts[index].text + if text in choices and not any(depth.values()): + return index + if text in depth: + depth[text] += 1 + elif text in closing: + opener = closing[text] + if depth[opener]: + depth[opener] -= 1 + elif text in choices: + return index + else: + return None + return None + + +def convert_if_expressions(source: str) -> str: + """Rewrite legacy `if c then x else y` expressions to ternaries.""" + if SOURCE_MIGRATOR is None: + return source + while True: + ts = SOURCE_MIGRATOR.tokens(source) + assembly = SOURCE_MIGRATOR.assembly_ranges(ts) + candidate: tuple[int, int, int, int] | None = None + # The rightmost legacy if is innermost with respect to another legacy + # conditional. Retokenizing after each edit makes nested expressions + # straightforward and keeps source offsets exact. + for index, tok in enumerate(ts): + if tok.text != "if" or SOURCE_MIGRATOR.in_ranges(index, assembly): + continue + then = _conditional_keyword(ts, index + 1, {"then"}) + if then is None: + continue + otherwise = _conditional_keyword(ts, then + 1, {"else"}) + if otherwise is None: + continue + end = _conditional_keyword( + ts, + otherwise + 1, + {";", ",", ")", "]", "}", "then", "else"}, + ) + if end is None: + end = len(ts) + no_end = ts[end].start if end < len(ts) else len(source) + if not source[tok.end : ts[then].start].strip(): + continue + if not source[ts[then].end : ts[otherwise].start].strip(): + continue + if not source[ts[otherwise].end : no_end].strip(): + continue + candidate = (index, then, otherwise, end) + if candidate is None: + return source + index, then, otherwise, end = candidate + condition = source[ts[index].end : ts[then].start].strip() + yes = source[ts[then].end : ts[otherwise].start].strip() + no_end = ts[end].start if end < len(ts) else len(source) + no = source[ts[otherwise].end : no_end].strip() + replacement = f"({condition} ? {yes} : {no})" + source = SOURCE_MIGRATOR.apply_edits( + source, [(ts[index].start, no_end, replacement)] + ) + + +def convert_if_statement_conditions(source: str) -> str: + """Parenthesize non-Yul statement-if conditions.""" + if SOURCE_MIGRATOR is None: + return source + ts = SOURCE_MIGRATOR.tokens(source) + assembly = SOURCE_MIGRATOR.assembly_ranges(ts) + edits: list[tuple[int, int, str]] = [] + for index, tok in enumerate(ts): + if tok.text != "if" or SOURCE_MIGRATOR.in_ranges(index, assembly): + continue + if index + 1 >= len(ts) or ts[index + 1].text == "(": + continue + opening = _conditional_keyword(ts, index + 1, {"{", "then", ";"}) + if opening is None or ts[opening].text != "{" or opening == index + 1: + continue + edits.append((ts[index + 1].start, ts[index + 1].start, "(")) + edits.append((ts[opening - 1].end, ts[opening - 1].end, ")")) + return SOURCE_MIGRATOR.apply_edits(source, edits) + + +def convert_core_walrus(source: str) -> str: + """Use `=` for Core bindings/assignments while preserving Yul `:=`.""" + if SOURCE_MIGRATOR is None: + return source + ts = SOURCE_MIGRATOR.tokens(source) + assembly = SOURCE_MIGRATOR.assembly_ranges(ts) + edits = [ + (tok.start, tok.end, "=") + for index, tok in enumerate(ts) + if tok.text == ":=" and not SOURCE_MIGRATOR.in_ranges(index, assembly) + ] + return SOURCE_MIGRATOR.apply_edits(source, edits) + + +def migrate_source(source: str, *, skip_shared_migrator: bool = False) -> str: + if not SOURCE_MARKER.search(source) and not MATCH_SOURCE_MARKER.search(source): + return source + source = convert_imports(source) + source = convert_data(source) + source = convert_headers(source) + source = convert_signature_types(source) + source = convert_typed_lets_and_fields(source) + source = convert_constructor_modifiers(source) + source = convert_match_statements(source) + source = convert_if_expressions(source) + source = convert_if_statement_conditions(source) + source = convert_core_walrus(source) + # Format templates and nested-comment negative fixtures stay on the local + # structural passes above. Their protected placeholders or deliberately + # malformed tokens are outside the full-source migrator's grammar. + has_nested_block_comment = re.search(r"/\*(?:(?!\*/).)*/\*", source, re.S) is not None + if ( + SOURCE_MIGRATOR is not None + and not skip_shared_migrator + and "{{" not in source + and "}}" not in source + and not has_nested_block_comment + ): + warnings: list[str] = [] + try: + source = SOURCE_MIGRATOR.migrate(source, warnings) + except (ValueError, IndexError): + # The local passes still cover the safe subset. Intentional + # negative fixtures and format-string placeholders can be outside + # the full-source migrator's representable grammar. + pass + return source + + From f023e381e5f3ae9253c629282acd515d6f28b5db Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:15:07 +0900 Subject: [PATCH 004/110] Add canonical syntax migration tools: embedded literal migration Co-authored-by: Codex --- scripts/migrate-embedded-syntax.py | 225 +++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/scripts/migrate-embedded-syntax.py b/scripts/migrate-embedded-syntax.py index 434ead6d..3403fdd9 100644 --- a/scripts/migrate-embedded-syntax.py +++ b/scripts/migrate-embedded-syntax.py @@ -897,3 +897,228 @@ def migrate_source(source: str, *, skip_shared_migrator: bool = False) -> str: return source +def decode_rust_string(content: str) -> str | None: + out: list[str] = [] + index = 0 + escapes = {"n": "\n", "r": "\r", "t": "\t", "0": "\0", "\\": "\\", '"': '"', "'": "'"} + while index < len(content): + if content[index] != "\\": + out.append(content[index]) + index += 1 + continue + index += 1 + if index >= len(content): + return None + char = content[index] + if char in escapes: + out.append(escapes[char]) + index += 1 + elif char == "x" and index + 2 < len(content): + try: + out.append(chr(int(content[index + 1 : index + 3], 16))) + except ValueError: + return None + index += 3 + elif char == "u" and index + 1 < len(content) and content[index + 1] == "{": + close = content.find("}", index + 2) + if close < 0: + return None + try: + out.append(chr(int(content[index + 2 : close].replace("_", ""), 16))) + except ValueError: + return None + index = close + 1 + elif char == "\n": + index += 1 + while index < len(content) and content[index] in " \t\r\n": + index += 1 + else: + # Unknown escapes may be intentionally invalid Rust in compile-fail + # support code; leave that literal untouched. + return None + return "".join(out) + + +def encode_rust_string(content: str) -> str: + out: list[str] = [] + for char in content: + if char == "\\": + out.append("\\\\") + elif char == '"': + out.append('\\"') + elif char == "\n": + out.append("\\n") + elif char == "\r": + out.append("\\r") + elif char == "\t": + out.append("\\t") + elif ord(char) < 0x20 or ord(char) == 0x7F: + out.append(f"\\x{ord(char):02x}") + else: + out.append(char) + return "".join(out) + + +FORMAT_MACRO_PREFIX = re.compile(r"\b(?:format|format_args)!\s*\(\s*$") +FORMAT_PLACEHOLDER = re.compile( + r"(?:[0-9]+|[A-Za-z_][A-Za-z0-9_]*)?(?:[!:].*)?\Z", re.S +) + + +def is_format_macro_literal(text: str, literal_start: int) -> bool: + """Return whether a literal is the format template of a format macro.""" + return FORMAT_MACRO_PREFIX.search(text, 0, literal_start) is not None + + +def decode_format_template(template: str) -> tuple[str, list[tuple[str, str]]] | None: + """Decode literal braces while protecting Rust format placeholders.""" + out: list[str] = [] + placeholders: list[tuple[str, str]] = [] + index = 0 + while index < len(template): + if template.startswith("{{", index): + out.append("{") + index += 2 + continue + if template.startswith("}}", index): + out.append("}") + index += 2 + continue + if template[index] == "{": + close = template.find("}", index + 1) + if close < 0: + out.append("{") + index += 1 + continue + placeholder = template[index : close + 1] + if FORMAT_PLACEHOLDER.fullmatch(template[index + 1 : close]) is None: + out.append("{") + index += 1 + continue + marker_index = len(placeholders) + marker = f"__solcore_format_arg_{marker_index}__" + used_markers = {existing for existing, _ in placeholders} + while marker in template or marker in used_markers: + marker_index += 1 + marker = f"__solcore_format_arg_{marker_index}__" + placeholders.append((marker, placeholder)) + out.append(marker) + index = close + 1 + continue + if template[index] == "}": + out.append("}") + index += 1 + continue + out.append(template[index]) + index += 1 + return "".join(out), placeholders + + +def encode_format_template( + source: str, placeholders: list[tuple[str, str]] +) -> str | None: + """Escape source braces and restore protected Rust format placeholders.""" + if any(source.count(marker) != 1 for marker, _ in placeholders): + return None + template = source.replace("{", "{{").replace("}", "}}") + for marker, placeholder in placeholders: + template = template.replace(marker, placeholder) + return template + + +def migrate_rust_strings(text: str) -> tuple[str, int]: + output: list[str] = [] + cursor = 0 + changed = 0 + opener = re.compile( + r"(?br|r)(?P#{0,16})|(?Pb)?)\"" + ) + while True: + match = opener.search(text, cursor) + if not match: + output.append(text[cursor:]) + break + content_start = match.end() + hashes = match.group("hashes") + if match.group("raw_prefix"): + close = '"' + (hashes or "") + content_end = text.find(close, content_start) + if content_end < 0: + output.append(text[cursor:]) + break + encoded_content = text[content_start:content_end] + decoded = encoded_content + else: + scan = content_start + while scan < len(text): + if text[scan] == "\\": + scan += 2 + continue + if text[scan] == '"': + break + scan += 1 + if scan >= len(text): + output.append(text[cursor:]) + break + close = '"' + content_end = scan + encoded_content = text[content_start:content_end] + decoded = decode_rust_string(encoded_content) + if decoded is None: + output.append(text[cursor : content_end + 1]) + cursor = content_end + 1 + continue + output.append(text[cursor:content_start]) + prefix = text[: match.start()] + preserved_region = prefix.rfind(PRESERVE_LITERALS_BEGIN_MARKER) > prefix.rfind( + PRESERVE_LITERALS_END_MARKER + ) + preserve_next = PRESERVE_NEXT_LITERAL_MARKER in text[cursor : match.start()] + format_template = None + if not (preserved_region or preserve_next) and is_format_macro_literal( + text, match.start() + ): + format_template = decode_format_template(decoded) + if preserved_region or preserve_next: + migrated = decoded + elif format_template is None: + migrated = migrate_source(decoded) + else: + source, placeholders = format_template + migrated_source = migrate_source(source, skip_shared_migrator=True) + migrated = encode_format_template(migrated_source, placeholders) + if migrated is None: + migrated = decoded + changed_literal = migrated != decoded + if changed_literal: + changed += 1 + if not changed_literal: + output.append(encoded_content) + elif match.group("raw_prefix"): + output.append(migrated) + else: + output.append(encode_rust_string(migrated)) + output.append(close) + cursor = content_end + len(close) + return "".join(output), changed + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--write", action="store_true") + parser.add_argument("paths", nargs="+", type=Path) + args = parser.parse_args() + total = 0 + for path in args.paths: + original = path.read_text() + migrated, changed = migrate_rust_strings(original) + if changed: + total += changed + print(f"{path}: {changed} raw string(s)") + if args.write: + path.write_text(migrated) + print(f"changed raw strings: {total}") + + +if __name__ == "__main__": + main() From 54b36b3a0585386a57faadadf3fbe8ca88707f55 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 005/110] Switch the compiler and fixtures to canonical syntax: fuzz extensions Co-authored-by: Codex --- fuzz/corpus/backend/{basic.solc => basic.sol} | 0 fuzz/corpus/frontend/{basic.solc => basic.sol} | 0 fuzz/corpus/parser/{basic.solc => basic.sol} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename fuzz/corpus/backend/{basic.solc => basic.sol} (100%) rename fuzz/corpus/frontend/{basic.solc => basic.sol} (100%) rename fuzz/corpus/parser/{basic.solc => basic.sol} (100%) diff --git a/fuzz/corpus/backend/basic.solc b/fuzz/corpus/backend/basic.sol similarity index 100% rename from fuzz/corpus/backend/basic.solc rename to fuzz/corpus/backend/basic.sol diff --git a/fuzz/corpus/frontend/basic.solc b/fuzz/corpus/frontend/basic.sol similarity index 100% rename from fuzz/corpus/frontend/basic.solc rename to fuzz/corpus/frontend/basic.sol diff --git a/fuzz/corpus/parser/basic.solc b/fuzz/corpus/parser/basic.sol similarity index 100% rename from fuzz/corpus/parser/basic.solc rename to fuzz/corpus/parser/basic.sol From 2e9a69caaae2423528efb31f0be3b4ce79d68fda Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 006/110] Switch the compiler and fixtures to canonical syntax: hir ty fixtures extensions Co-authored-by: Codex --- .../storage-adt-mapping-field-fail/{main.solc => main.sol} | 0 .../storage-adt-recursive-fail/{main.solc => main.sol} | 0 .../storage-adt-recursive-ok/{main.solc => main.sol} | 0 .../storage-body-only-active-ok/{main.solc => main.sol} | 0 .../storage-body-only-active-ok/{types.solc => types.sol} | 0 .../storage-body-only-inactive-fail/{main.solc => main.sol} | 0 .../storage-body-only-inactive-fail/{types.solc => types.sol} | 0 .../storage-body-only-qualified-ok/{main.solc => main.sol} | 0 .../storage-body-only-qualified-ok/{types.solc => types.sol} | 0 .../storage-builtins-unused-ok/{main.solc => main.sol} | 0 .../storage-imported-active-no-marker-ok/{main.solc => main.sol} | 0 .../{types.solc => types.sol} | 0 .../{main.solc => main.sol} | 0 .../{types.solc => types.sol} | 0 .../{main.solc => main.sol} | 0 .../{types.solc => types.sol} | 0 .../storage-nested-reexport-invalid-fail/{api.solc => api.sol} | 0 .../storage-nested-reexport-invalid-fail/{base.solc => base.sol} | 0 .../storage-nested-reexport-invalid-fail/{main.solc => main.sol} | 0 .../{outer.solc => outer.sol} | 0 .../class_method_runtime_body_deferred/{main.solc => main.sol} | 0 .../comptime/frontend_call_classification/{main.solc => main.sol} | 0 .../polymorphic_param_defers_runtime_arg/{main.solc => main.sol} | 0 .../fixtures/ok/comptime/return_params/{main.solc => main.sol} | 0 .../local-class/p4-default-instance/{main.solc => main.sol} | 0 .../corpus/local-class/p4-local-instance/{main.solc => main.sol} | 0 .../local-class/tabled-answer-reuse/{main.solc => main.sol} | 0 .../corpus/local-class/tabled-given-order/{main.solc => main.sol} | 0 .../local-class/tabled-residual-given/{main.solc => main.sol} | 0 .../fixtures/ok/corpus/spec/00answer/{main.solc => main.sol} | 0 .../tests/fixtures/ok/corpus/spec/021not/{main.solc => main.sol} | 0 .../tests/fixtures/ok/corpus/spec/022add/{main.solc => main.sol} | 0 .../fixtures/ok/corpus/spec/024arith/{main.solc => main.sol} | 0 .../fixtures/ok/corpus/spec/031maybe/{main.solc => main.sol} | 0 .../fixtures/ok/corpus/spec/036wildcard/{main.solc => main.sol} | 0 .../tests/fixtures/ok/corpus/spec/041pair/{main.solc => main.sol} | 0 .../fixtures/ok/corpus/spec/042triple/{main.solc => main.sol} | 0 .../tests/fixtures/ok/corpus/spec/047rgb/{main.solc => main.sol} | 0 .../tests/fixtures/ok/corpus/spec/048rgb2/{main.solc => main.sol} | 0 .../tests/fixtures/ok/corpus/spec/049rgb3/{main.solc => main.sol} | 0 .../class_scoped_bounded_variable_pragma/{main.solc => main.sol} | 0 .../solver/class_scoped_patterson_pragma/{main.solc => main.sol} | 0 .../ok/solver/global_coverage_pragma/{main.solc => main.sol} | 0 .../solver/obligation_order_improvement/{main.solc => main.sol} | 0 .../typeck/abstract_data_wildcard_match/{main.solc => main.sol} | 0 .../typeck/bytes_storage_roundtrip_full/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../compiler_private_dispatch_entry_name/{main.solc => main.sol} | 0 .../compound_assignment_uses_class_method/{main.solc => main.sol} | 0 .../constructor_dynamic_string_full/{main.solc => main.sol} | 0 .../ok/typeck/contract_field_access/{main.solc => main.sol} | 0 .../ok/typeck/contract_field_initializer/{main.solc => main.sol} | 0 .../dispatch_field_method_collision/{main.solc => main.sol} | 0 .../dot_constructors_nested_patterns/{main.solc => main.sol} | 0 .../generated_dispatch_explicit_imports/{main.solc => main.sol} | 0 .../import_same_name_ctor_unqualified/{lib.solc => lib.sol} | 0 .../import_same_name_ctor_unqualified/{main.solc => main.sol} | 0 .../ok/typeck/imported_derived_class/{lib.solc => lib.sol} | 0 .../ok/typeck/imported_derived_class/{main.solc => main.sol} | 0 .../ok/typeck/integer_literal_pattern/{main.solc => main.sol} | 0 .../typeck/lambda_expected_function_type/{main.solc => main.sol} | 0 .../ok/typeck/literal_poly_noclass/{main.solc => main.sol} | 0 .../typeck/nested_generic_adt_constructor/{main.solc => main.sol} | 0 .../qualified_and_builtin_bool_patterns/{main.solc => main.sol} | 0 .../typeck/same_name_nullary_ctor_pattern/{main.solc => main.sol} | 0 .../ok/typeck/self_recursive_data/{main.solc => main.sol} | 0 .../ok/typeck/std_universe_eq_ord/{main.solc => main.sol} | 0 .../fixtures/ok/typeck/std_word_minmax/{main.solc => main.sol} | 0 .../storage_mapping_compound_add_uint256/{main.solc => main.sol} | 0 .../storage_mapping_compound_add_word/{main.solc => main.sol} | 0 .../typeck/storage_word_assignment_full/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../fixtures/ok/typeck/yul_keccak256/{main.solc => main.sol} | 0 .../ok/yul_polymorphic_terminators/{main.solc => main.sol} | 0 .../fixtures/solver/derived_abi_imported/{abi.solc => abi.sol} | 0 .../fixtures/solver/derived_abi_imported/{main.solc => main.sol} | 0 .../solver/derived_abi_imported/{types.solc => types.sol} | 0 .../solver/derived_abi_imported_inactive/{abi.solc => abi.sol} | 0 .../derived_abi_imported_inactive/{generic.solc => generic.sol} | 0 .../solver/derived_abi_imported_inactive/{main.solc => main.sol} | 0 .../derived_abi_imported_inactive/{types.solc => types.sol} | 0 .../solver/derived_reexport_visibility/{api.solc => api.sol} | 0 .../solver/derived_reexport_visibility/{base.solc => base.sol} | 0 .../derived_reexport_visibility/{classes.solc => classes.sol} | 0 .../solver/derived_reexport_visibility/{main.solc => main.sol} | 0 .../solver/derived_storage_imported/{main.solc => main.sol} | 0 .../{storage_support.solc => storage_support.sol} | 0 .../solver/derived_storage_imported/{types.solc => types.sol} | 0 .../{generic.solc => generic.sol} | 0 .../derived_storage_imported_inactive/{main.solc => main.sol} | 0 .../{storage_support.solc => storage_support.sol} | 0 .../derived_storage_imported_inactive/{types.solc => types.sol} | 0 .../derived_storage_reexport_visibility/{api.solc => api.sol} | 0 .../derived_storage_reexport_visibility/{main.solc => main.sol} | 0 .../{storage_support.solc => storage_support.sol} | 0 .../derived_storage_reexport_visibility/{types.solc => types.sol} | 0 96 files changed, 0 insertions(+), 0 deletions(-) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/{api.solc => api.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/{base.solc => base.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/{outer.solc => outer.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/comptime/return_params/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/{lib.solc => lib.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/{lib.solc => lib.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported/{abi.solc => abi.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/{abi.solc => abi.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/{generic.solc => generic.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/{api.solc => api.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/{base.solc => base.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/{classes.solc => classes.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported/{storage_support.solc => storage_support.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/{generic.solc => generic.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/{storage_support.solc => storage_support.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/{types.solc => types.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/{api.solc => api.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/{main.solc => main.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/{storage_support.solc => storage_support.sol} (100%) rename crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/{types.solc => types.sol} (100%) diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/api.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/api.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/api.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/api.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.sol diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.solc b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.solc rename to crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.sol diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.solc b/crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.solc rename to crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.solc b/crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.solc rename to crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.solc b/crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.solc rename to crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.solc b/crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.solc rename to crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.solc b/crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.solc rename to crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.solc b/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.solc rename to crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.solc b/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.solc rename to crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.solc b/crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.solc rename to crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.solc b/crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.solc rename to crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.solc b/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.solc b/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.solc b/crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.solc rename to crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.sol diff --git a/crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.solc b/crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.solc rename to crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.solc b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.solc rename to crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/api.solc b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/api.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/api.solc rename to crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/api.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.solc b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.solc rename to crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.solc b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.solc rename to crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.solc b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.solc rename to crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/api.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/api.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/api.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/api.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.sol diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.solc b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.sol similarity index 100% rename from crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.solc rename to crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.sol From e378cc65c2e5809620e8c58561fa0af45ba8d2eb Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 007/110] Switch the compiler and fixtures to canonical syntax: nameres fixtures extensions Co-authored-by: Codex --- crates/nameres/tests/fixtures/ok/alias/{main.solc => main.sol} | 0 crates/nameres/tests/fixtures/ok/alias/{util.solc => util.sol} | 0 crates/nameres/tests/fixtures/ok/cycle/{a.solc => a.sol} | 0 crates/nameres/tests/fixtures/ok/cycle/{b.solc => b.sol} | 0 crates/nameres/tests/fixtures/ok/cycle/{main.solc => main.sol} | 0 .../fixtures/ok/external/extroot/{extmod.solc => extmod.sol} | 0 crates/nameres/tests/fixtures/ok/external/{main.solc => main.sol} | 0 .../tests/fixtures/ok/local_std_subpath/{main.solc => main.sol} | 0 .../tests/fixtures/ok/local_std_subpath/std/a/{b.solc => b.sol} | 0 crates/nameres/tests/fixtures/ok/plain/{main.solc => main.sol} | 0 crates/nameres/tests/fixtures/ok/plain/{util.solc => util.sol} | 0 crates/nameres/tests/fixtures/ok/reexport_chain/{a.solc => a.sol} | 0 crates/nameres/tests/fixtures/ok/reexport_chain/{b.solc => b.sol} | 0 .../tests/fixtures/ok/reexport_chain/{main.solc => main.sol} | 0 .../tests/fixtures/ok/selective_hiding/{main.solc => main.sol} | 0 .../tests/fixtures/ok/selective_hiding/{util.solc => util.sol} | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename crates/nameres/tests/fixtures/ok/alias/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/alias/{util.solc => util.sol} (100%) rename crates/nameres/tests/fixtures/ok/cycle/{a.solc => a.sol} (100%) rename crates/nameres/tests/fixtures/ok/cycle/{b.solc => b.sol} (100%) rename crates/nameres/tests/fixtures/ok/cycle/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/external/extroot/{extmod.solc => extmod.sol} (100%) rename crates/nameres/tests/fixtures/ok/external/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/local_std_subpath/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/{b.solc => b.sol} (100%) rename crates/nameres/tests/fixtures/ok/plain/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/plain/{util.solc => util.sol} (100%) rename crates/nameres/tests/fixtures/ok/reexport_chain/{a.solc => a.sol} (100%) rename crates/nameres/tests/fixtures/ok/reexport_chain/{b.solc => b.sol} (100%) rename crates/nameres/tests/fixtures/ok/reexport_chain/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/selective_hiding/{main.solc => main.sol} (100%) rename crates/nameres/tests/fixtures/ok/selective_hiding/{util.solc => util.sol} (100%) diff --git a/crates/nameres/tests/fixtures/ok/alias/main.solc b/crates/nameres/tests/fixtures/ok/alias/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/alias/main.solc rename to crates/nameres/tests/fixtures/ok/alias/main.sol diff --git a/crates/nameres/tests/fixtures/ok/alias/util.solc b/crates/nameres/tests/fixtures/ok/alias/util.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/alias/util.solc rename to crates/nameres/tests/fixtures/ok/alias/util.sol diff --git a/crates/nameres/tests/fixtures/ok/cycle/a.solc b/crates/nameres/tests/fixtures/ok/cycle/a.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/cycle/a.solc rename to crates/nameres/tests/fixtures/ok/cycle/a.sol diff --git a/crates/nameres/tests/fixtures/ok/cycle/b.solc b/crates/nameres/tests/fixtures/ok/cycle/b.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/cycle/b.solc rename to crates/nameres/tests/fixtures/ok/cycle/b.sol diff --git a/crates/nameres/tests/fixtures/ok/cycle/main.solc b/crates/nameres/tests/fixtures/ok/cycle/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/cycle/main.solc rename to crates/nameres/tests/fixtures/ok/cycle/main.sol diff --git a/crates/nameres/tests/fixtures/ok/external/extroot/extmod.solc b/crates/nameres/tests/fixtures/ok/external/extroot/extmod.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/external/extroot/extmod.solc rename to crates/nameres/tests/fixtures/ok/external/extroot/extmod.sol diff --git a/crates/nameres/tests/fixtures/ok/external/main.solc b/crates/nameres/tests/fixtures/ok/external/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/external/main.solc rename to crates/nameres/tests/fixtures/ok/external/main.sol diff --git a/crates/nameres/tests/fixtures/ok/local_std_subpath/main.solc b/crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/local_std_subpath/main.solc rename to crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol diff --git a/crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.solc b/crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.solc rename to crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol diff --git a/crates/nameres/tests/fixtures/ok/plain/main.solc b/crates/nameres/tests/fixtures/ok/plain/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/plain/main.solc rename to crates/nameres/tests/fixtures/ok/plain/main.sol diff --git a/crates/nameres/tests/fixtures/ok/plain/util.solc b/crates/nameres/tests/fixtures/ok/plain/util.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/plain/util.solc rename to crates/nameres/tests/fixtures/ok/plain/util.sol diff --git a/crates/nameres/tests/fixtures/ok/reexport_chain/a.solc b/crates/nameres/tests/fixtures/ok/reexport_chain/a.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/reexport_chain/a.solc rename to crates/nameres/tests/fixtures/ok/reexport_chain/a.sol diff --git a/crates/nameres/tests/fixtures/ok/reexport_chain/b.solc b/crates/nameres/tests/fixtures/ok/reexport_chain/b.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/reexport_chain/b.solc rename to crates/nameres/tests/fixtures/ok/reexport_chain/b.sol diff --git a/crates/nameres/tests/fixtures/ok/reexport_chain/main.solc b/crates/nameres/tests/fixtures/ok/reexport_chain/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/reexport_chain/main.solc rename to crates/nameres/tests/fixtures/ok/reexport_chain/main.sol diff --git a/crates/nameres/tests/fixtures/ok/selective_hiding/main.solc b/crates/nameres/tests/fixtures/ok/selective_hiding/main.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/selective_hiding/main.solc rename to crates/nameres/tests/fixtures/ok/selective_hiding/main.sol diff --git a/crates/nameres/tests/fixtures/ok/selective_hiding/util.solc b/crates/nameres/tests/fixtures/ok/selective_hiding/util.sol similarity index 100% rename from crates/nameres/tests/fixtures/ok/selective_hiding/util.solc rename to crates/nameres/tests/fixtures/ok/selective_hiding/util.sol From 8b70a573675fcc99709598147fcf8568824d34cc Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 008/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test diagnostics extensions Co-authored-by: Codex --- .../fail/test/diagnostics/{parse-error.solc => parse-error.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/fail/test/diagnostics/{parse-error.solc => parse-error.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.solc b/crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.solc rename to crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.sol From 636707214c36f0b049a2b46f8dd2467911347012 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 009/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples extensions Co-authored-by: Codex --- .../fail/test/examples/{Convertible.solc => Convertible.sol} | 0 .../test/examples/cases/{BadInstance.solc => BadInstance.sol} | 0 .../corpus/fail/test/examples/cases/{DupFun.solc => DupFun.sol} | 0 .../corpus/fail/test/examples/cases/{Enum.solc => Enum.sol} | 0 .../fixtures/corpus/fail/test/examples/cases/{Eq.solc => Eq.sol} | 0 .../corpus/fail/test/examples/cases/{Filter.solc => Filter.sol} | 0 .../corpus/fail/test/examples/cases/{GetSet.solc => GetSet.sol} | 0 .../test/examples/cases/{GoodInstance.solc => GoodInstance.sol} | 0 .../cases/{IncompleteInstDef.solc => IncompleteInstDef.sol} | 0 .../fail/test/examples/cases/{Invokable.solc => Invokable.sol} | 0 .../fail/test/examples/cases/{KindTest.solc => KindTest.sol} | 0 .../fail/test/examples/cases/{PairMatch1.solc => PairMatch1.sol} | 0 .../fail/test/examples/cases/{PairMatch2.solc => PairMatch2.sol} | 0 .../corpus/fail/test/examples/cases/{Ref.solc => Ref.sol} | 0 .../test/examples/cases/{SillyReturn.solc => SillyReturn.sol} | 0 .../test/examples/cases/{SimpleInvoke.solc => SimpleInvoke.sol} | 0 .../test/examples/cases/{StructMembers.solc => StructMembers.sol} | 0 .../fail/test/examples/cases/{add-moritz.solc => add-moritz.sol} | 0 ...ray-elem-no-storagecopy.solc => array-elem-no-storagecopy.sol} | 0 .../{array-push-no-canstore.solc => array-push-no-canstore.sol} | 0 .../cases/{arraylit-bad-target.solc => arraylit-bad-target.sol} | 0 .../cases/{arraylit-mixed-types.solc => arraylit-mixed-types.sol} | 0 .../cases/{asm-assign-no-return.solc => asm-assign-no-return.sol} | 0 .../cases/{asm-assign-non-word.solc => asm-assign-non-word.sol} | 0 .../cases/{asm-let-no-return.solc => asm-let-no-return.sol} | 0 .../test/examples/cases/{bound-minimal.solc => bound-minimal.sol} | 0 .../examples/cases/{bound-only-test.solc => bound-only-test.sol} | 0 .../cases/{bug-spec-generic-let.solc => bug-spec-generic-let.sol} | 0 .../test/examples/cases/{catenable-err.solc => catenable-err.sol} | 0 .../{class-return-type-miss.solc => class-return-type-miss.sol} | 0 ...ass-type-name-collision.solc => class-type-name-collision.sol} | 0 .../corpus/fail/test/examples/cases/{comp.solc => comp.sol} | 0 .../test/examples/cases/{complexproxy.solc => complexproxy.sol} | 0 .../cases/{compose_desugared.solc => compose_desugared.sol} | 0 .../test/examples/cases/{const-array.solc => const-array.sol} | 0 ...ype-escapes-fail.solc => contract-local-type-escapes-fail.sol} | 0 .../test/examples/cases/{default-inst.solc => default-inst.sol} | 0 ...default-instance-missing.solc => default-instance-missing.sol} | 0 .../{default-instance-weak.solc => default-instance-weak.sol} | 0 .../cases/{derive-unknown-class.solc => derive-unknown-class.sol} | 0 .../fail/test/examples/cases/{dispatch.solc => dispatch.sol} | 0 ...on-no-context-fail.solc => dot-expression-no-context-fail.sol} | 0 ...pression-unknown-fail.solc => dot-expression-unknown-fail.sol} | 0 ...duplicated-contract-name.solc => duplicated-contract-name.sol} | 0 .../cases/{duplicated-type-name.solc => duplicated-type-name.sol} | 0 .../cases/{fallback-with-args.solc => fallback-with-args.sol} | 0 .../cases/{fallback-with-return.solc => fallback-with-return.sol} | 0 .../test/examples/cases/{field-access.solc => field-access.sol} | 0 .../test/examples/cases/{for-let-post.solc => for-let-post.sol} | 0 ...generic-manual-no-pragma.solc => generic-manual-no-pragma.sol} | 0 ...neric-product-no-pragma.solc => generic-product-no-pragma.sol} | 0 .../{generic-sum-no-pragma.solc => generic-sum-no-pragma.sol} | 0 .../test/examples/cases/{index-example.solc => index-example.sol} | 0 ...alid-member.solc => instance-closure-error-invalid-member.sol} | 0 ...ce-context-wrong-kind.solc => instance-context-wrong-kind.sol} | 0 .../cases/{instance-wrong-sig.solc => instance-wrong-sig.sol} | 0 .../corpus/fail/test/examples/cases/{joinErr.solc => joinErr.sol} | 0 .../corpus/fail/test/examples/cases/{listeq.solc => listeq.sol} | 0 .../fail/test/examples/cases/{mainproxy.solc => mainproxy.sol} | 0 ...match-compiler-undef-asm.solc => match-compiler-undef-asm.sol} | 0 .../cases/{missing-instance.solc => missing-instance.sol} | 0 .../examples/cases/{nano-desugared.solc => nano-desugared.sol} | 0 .../fail/test/examples/cases/{noconstr.solc => noconstr.sol} | 0 ...overlap-synonym-detected.solc => overlap-synonym-detected.sol} | 0 ...synonym-missed-order.solc => overlap-synonym-missed-order.sol} | 0 ...-two-synonyms.solc => overlap-synonym-missed-two-synonyms.sol} | 0 .../cases/{overlapping-heads.solc => overlapping-heads.sol} | 0 .../test/examples/cases/{patterson-bug.solc => patterson-bug.sol} | 0 ...yable-toplevel-function.solc => payable-toplevel-function.sol} | 0 ...ma_merge_fail_coverage.solc => pragma_merge_fail_coverage.sol} | 0 ..._merge_fail_patterson.solc => pragma_merge_fail_patterson.sol} | 0 .../cases/{pragma_merge_import.solc => pragma_merge_import.sol} | 0 .../cases/{pragma_merge_verify.solc => pragma_merge_verify.sol} | 0 .../corpus/fail/test/examples/cases/{proxy1.solc => proxy1.sol} | 0 .../cases/{public-constructor.solc => public-constructor.sol} | 0 .../examples/cases/{public-fallback.solc => public-fallback.sol} | 0 ...blic-top-level-function.solc => public-top-level-function.sol} | 0 .../cases/{reference-encoding.solc => reference-encoding.sol} | 0 .../examples/cases/{reference-test.solc => reference-test.sol} | 0 .../fail/test/examples/cases/{reference.solc => reference.sol} | 0 .../cases/{references-daniel.solc => references-daniel.sol} | 0 ...ontract-method.solc => require-annotation-contract-method.sol} | 0 ...tion-missing-both.solc => require-annotation-missing-both.sol} | 0 ...on-missing-param.solc => require-annotation-missing-param.sol} | 0 ...-missing-return.solc => require-annotation-missing-return.sol} | 0 ...quire-annotation-mutual.solc => require-annotation-mutual.sol} | 0 .../cases/{return-fun-bad-arity.solc => return-fun-bad-arity.sol} | 0 .../cases/{return-fun-bad-param.solc => return-fun-bad-param.sol} | 0 .../{return-fun-bad-return.solc => return-fun-bad-return.sol} | 0 .../cases/{return-fun-bad-sig.solc => return-fun-bad-sig.sol} | 0 .../cases/{return-fun-not-fun.solc => return-fun-not-fun.sol} | 0 .../fail/test/examples/cases/{signature.solc => signature.sol} | 0 .../test/examples/cases/{simpleIfExpr.solc => simpleIfExpr.sol} | 0 .../test/examples/cases/{simpleIfStmt.solc => simpleIfStmt.sol} | 0 .../fail/test/examples/cases/{skolem-let.solc => skolem-let.sol} | 0 ...mapping-field-fail.solc => storage-adt-mapping-field-fail.sol} | 0 .../test/examples/cases/{string-const.solc => string-const.sol} | 0 .../test/examples/cases/{subject-index.solc => subject-index.sol} | 0 .../cases/{subject-reduction.solc => subject-reduction.sol} | 0 .../{subsumption-constraint.solc => subsumption-constraint.sol} | 0 .../cases/{subsumption-test.solc => subsumption-test.sol} | 0 .../{super-class-cycle-fail.solc => super-class-cycle-fail.sol} | 0 ...per-class-recursive-arg.solc => super-class-recursive-arg.sol} | 0 .../{synonym-arity-mismatch.solc => synonym-arity-mismatch.sol} | 0 .../cases/{synonym-long-cycle.solc => synonym-long-cycle.sol} | 0 .../cases/{synonym-recursive.solc => synonym-recursive.sol} | 0 .../{synonym-self-recursive.solc => synonym-self-recursive.sol} | 0 .../cases/{tabled-answer-reuse.solc => tabled-answer-reuse.sol} | 0 .../cases/{tabled-cycle-fail.solc => tabled-cycle-fail.sol} | 0 ...ed-left-recursive-fail.solc => tabled-left-recursive-fail.sol} | 0 .../cases/{tabled-mutual-chain.solc => tabled-mutual-chain.sol} | 0 .../cases/{toplevel-constructor.solc => toplevel-constructor.sol} | 0 .../cases/{toplevel-fallback.solc => toplevel-fallback.sol} | 0 .../cases/{unbound-instance-var.solc => unbound-instance-var.sol} | 0 .../{unconstrained-instance.solc => unconstrained-instance.sol} | 0 .../examples/cases/{user-op-lambda.solc => user-op-lambda.sol} | 0 .../fail/test/examples/cases/{vartyped.solc => vartyped.sol} | 0 .../examples/cases/{weird-error-foo.solc => weird-error-foo.sol} | 0 .../fail/test/examples/cases/{weirdfoo.solc => weirdfoo.sol} | 0 .../corpus/fail/test/examples/cases/{xref.solc => xref.sol} | 0 ...lti-return-arity-fail.solc => yul-multi-return-arity-fail.sol} | 0 .../fail/test/examples/comptime/{OneOne.solc => OneOne.sol} | 0 .../{ct_param_poly_runtime.solc => ct_param_poly_runtime.sol} | 0 .../comptime/{ct_param_runtime.solc => ct_param_runtime.sol} | 0 .../fail/test/examples/comptime/{fromInt.solc => fromInt.sol} | 0 .../fail/test/examples/comptime/{fromInt2.solc => fromInt2.sol} | 0 .../fail/test/examples/comptime/{fromInt3.solc => fromInt3.sol} | 0 .../fail/test/examples/comptime/{fromLit.solc => fromLit.sol} | 0 .../{string-mem-runtime-fail.solc => string-mem-runtime-fail.sol} | 0 .../corpus/fail/test/examples/dispatch/{fib.solc => fib.sol} | 0 .../fail/test/examples/invokable/{021nid.solc => 021nid.sol} | 0 .../examples/invokable/{022nid-invoke.solc => 022nid-invoke.sol} | 0 .../fail/test/examples/invokable/{024lamid.solc => 024lamid.sol} | 0 .../invokable/{025lamid-invoke.solc => 025lamid-invoke.sol} | 0 .../test/examples/invokable/{026capture.solc => 026capture.sol} | 0 .../test/examples/invokable/{027retfun.solc => 027retfun.sol} | 0 .../test/examples/invokable/{028modifier.solc => 028modifier.sol} | 0 .../fail/test/examples/invokable/{031enum.solc => 031enum.sol} | 0 .../corpus/fail/test/examples/pragmas/{bound.solc => bound.sol} | 0 .../fail/test/examples/spec/{010answer.solc => 010answer.sol} | 0 .../corpus/fail/test/examples/spec/{011id.solc => 011id.sol} | 0 .../corpus/fail/test/examples/spec/{012nid.solc => 012nid.sol} | 0 .../corpus/fail/test/examples/spec/{013comp.solc => 013comp.sol} | 0 .../fail/test/examples/spec/{027sstore.solc => 027sstore.sol} | 0 .../test/examples/spec/{051expreturn.solc => 051expreturn.sol} | 0 .../fail/test/examples/spec/{051negBool.solc => 051negBool.sol} | 0 .../fail/test/examples/spec/{052negPair.solc => 052negPair.sol} | 0 .../fail/test/examples/spec/{052return.solc => 052return.sol} | 0 .../fail/test/examples/spec/{053return.solc => 053return.sol} | 0 .../examples/spec/{101struct1Field.solc => 101struct1Field.sol} | 0 .../test/examples/spec/{102uintField.solc => 102uintField.sol} | 0 .../examples/spec/{103struct3Fields.solc => 103struct3Fields.sol} | 0 .../examples/spec/{105nestedStruct.solc => 105nestedStruct.sol} | 0 .../examples/spec/{111storageStruct.solc => 111storageStruct.sol} | 0 .../spec/{112ContractStorage.solc => 112ContractStorage.sol} | 0 .../fail/test/examples/spec/{113counter.solc => 113counter.sol} | 0 .../examples/spec/{131constructor.solc => 131constructor.sol} | 0 .../fail/test/examples/spec/{135cons3.solc => 135cons3.sol} | 0 .../fail/test/examples/spec/{StorageLib.solc => StorageLib.sol} | 0 .../examples/spec/attic/{051expreturn.solc => 051expreturn.sol} | 0 .../test/examples/spec/attic/{052return.solc => 052return.sol} | 0 .../test/examples/spec/attic/{053return.solc => 053return.sol} | 0 162 files changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/fail/test/examples/{Convertible.solc => Convertible.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{BadInstance.solc => BadInstance.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{DupFun.solc => DupFun.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{Enum.solc => Enum.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{Eq.solc => Eq.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{Filter.solc => Filter.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{GetSet.solc => GetSet.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{GoodInstance.solc => GoodInstance.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{IncompleteInstDef.solc => IncompleteInstDef.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{Invokable.solc => Invokable.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{KindTest.solc => KindTest.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{PairMatch1.solc => PairMatch1.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{PairMatch2.solc => PairMatch2.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{Ref.solc => Ref.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{SillyReturn.solc => SillyReturn.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{SimpleInvoke.solc => SimpleInvoke.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{StructMembers.solc => StructMembers.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{add-moritz.solc => add-moritz.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{array-elem-no-storagecopy.solc => array-elem-no-storagecopy.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{array-push-no-canstore.solc => array-push-no-canstore.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{arraylit-bad-target.solc => arraylit-bad-target.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{arraylit-mixed-types.solc => arraylit-mixed-types.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{asm-assign-no-return.solc => asm-assign-no-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{asm-assign-non-word.solc => asm-assign-non-word.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{asm-let-no-return.solc => asm-let-no-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{bound-minimal.solc => bound-minimal.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{bound-only-test.solc => bound-only-test.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{bug-spec-generic-let.solc => bug-spec-generic-let.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{catenable-err.solc => catenable-err.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{class-return-type-miss.solc => class-return-type-miss.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{class-type-name-collision.solc => class-type-name-collision.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{comp.solc => comp.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{complexproxy.solc => complexproxy.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{compose_desugared.solc => compose_desugared.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{const-array.solc => const-array.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{contract-local-type-escapes-fail.solc => contract-local-type-escapes-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{default-inst.solc => default-inst.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{default-instance-missing.solc => default-instance-missing.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{default-instance-weak.solc => default-instance-weak.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{derive-unknown-class.solc => derive-unknown-class.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{dispatch.solc => dispatch.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{dot-expression-no-context-fail.solc => dot-expression-no-context-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{dot-expression-unknown-fail.solc => dot-expression-unknown-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{duplicated-contract-name.solc => duplicated-contract-name.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{duplicated-type-name.solc => duplicated-type-name.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{fallback-with-args.solc => fallback-with-args.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{fallback-with-return.solc => fallback-with-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{field-access.solc => field-access.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{for-let-post.solc => for-let-post.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{generic-manual-no-pragma.solc => generic-manual-no-pragma.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{generic-product-no-pragma.solc => generic-product-no-pragma.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{generic-sum-no-pragma.solc => generic-sum-no-pragma.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{index-example.solc => index-example.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{instance-closure-error-invalid-member.solc => instance-closure-error-invalid-member.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{instance-context-wrong-kind.solc => instance-context-wrong-kind.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{instance-wrong-sig.solc => instance-wrong-sig.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{joinErr.solc => joinErr.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{listeq.solc => listeq.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{mainproxy.solc => mainproxy.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{match-compiler-undef-asm.solc => match-compiler-undef-asm.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{missing-instance.solc => missing-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{nano-desugared.solc => nano-desugared.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{noconstr.solc => noconstr.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{overlap-synonym-detected.solc => overlap-synonym-detected.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{overlap-synonym-missed-order.solc => overlap-synonym-missed-order.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{overlap-synonym-missed-two-synonyms.solc => overlap-synonym-missed-two-synonyms.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{overlapping-heads.solc => overlapping-heads.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{patterson-bug.solc => patterson-bug.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{payable-toplevel-function.solc => payable-toplevel-function.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{pragma_merge_fail_coverage.solc => pragma_merge_fail_coverage.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{pragma_merge_fail_patterson.solc => pragma_merge_fail_patterson.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{pragma_merge_import.solc => pragma_merge_import.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{pragma_merge_verify.solc => pragma_merge_verify.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{proxy1.solc => proxy1.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{public-constructor.solc => public-constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{public-fallback.solc => public-fallback.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{public-top-level-function.solc => public-top-level-function.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{reference-encoding.solc => reference-encoding.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{reference-test.solc => reference-test.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{reference.solc => reference.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{references-daniel.solc => references-daniel.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{require-annotation-contract-method.solc => require-annotation-contract-method.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{require-annotation-missing-both.solc => require-annotation-missing-both.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{require-annotation-missing-param.solc => require-annotation-missing-param.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{require-annotation-missing-return.solc => require-annotation-missing-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{require-annotation-mutual.solc => require-annotation-mutual.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{return-fun-bad-arity.solc => return-fun-bad-arity.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{return-fun-bad-param.solc => return-fun-bad-param.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{return-fun-bad-return.solc => return-fun-bad-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{return-fun-bad-sig.solc => return-fun-bad-sig.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{return-fun-not-fun.solc => return-fun-not-fun.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{signature.solc => signature.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{simpleIfExpr.solc => simpleIfExpr.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{simpleIfStmt.solc => simpleIfStmt.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{skolem-let.solc => skolem-let.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{storage-adt-mapping-field-fail.solc => storage-adt-mapping-field-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{string-const.solc => string-const.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{subject-index.solc => subject-index.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{subject-reduction.solc => subject-reduction.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{subsumption-constraint.solc => subsumption-constraint.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{subsumption-test.solc => subsumption-test.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{super-class-cycle-fail.solc => super-class-cycle-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{super-class-recursive-arg.solc => super-class-recursive-arg.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{synonym-arity-mismatch.solc => synonym-arity-mismatch.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{synonym-long-cycle.solc => synonym-long-cycle.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{synonym-recursive.solc => synonym-recursive.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{synonym-self-recursive.solc => synonym-self-recursive.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{tabled-answer-reuse.solc => tabled-answer-reuse.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{tabled-cycle-fail.solc => tabled-cycle-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{tabled-left-recursive-fail.solc => tabled-left-recursive-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{tabled-mutual-chain.solc => tabled-mutual-chain.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{toplevel-constructor.solc => toplevel-constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{toplevel-fallback.solc => toplevel-fallback.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{unbound-instance-var.solc => unbound-instance-var.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{unconstrained-instance.solc => unconstrained-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{user-op-lambda.solc => user-op-lambda.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{vartyped.solc => vartyped.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{weird-error-foo.solc => weird-error-foo.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{weirdfoo.solc => weirdfoo.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{xref.solc => xref.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/cases/{yul-multi-return-arity-fail.solc => yul-multi-return-arity-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{OneOne.solc => OneOne.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{ct_param_poly_runtime.solc => ct_param_poly_runtime.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{ct_param_runtime.solc => ct_param_runtime.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{fromInt.solc => fromInt.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{fromInt2.solc => fromInt2.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{fromInt3.solc => fromInt3.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{fromLit.solc => fromLit.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/{string-mem-runtime-fail.solc => string-mem-runtime-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/{fib.solc => fib.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{021nid.solc => 021nid.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{022nid-invoke.solc => 022nid-invoke.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{024lamid.solc => 024lamid.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{025lamid-invoke.solc => 025lamid-invoke.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{026capture.solc => 026capture.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{027retfun.solc => 027retfun.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{028modifier.solc => 028modifier.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/{031enum.solc => 031enum.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/{bound.solc => bound.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{010answer.solc => 010answer.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{011id.solc => 011id.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{012nid.solc => 012nid.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{013comp.solc => 013comp.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{027sstore.solc => 027sstore.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{051expreturn.solc => 051expreturn.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{051negBool.solc => 051negBool.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{052negPair.solc => 052negPair.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{052return.solc => 052return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{053return.solc => 053return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{101struct1Field.solc => 101struct1Field.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{102uintField.solc => 102uintField.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{103struct3Fields.solc => 103struct3Fields.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{105nestedStruct.solc => 105nestedStruct.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{111storageStruct.solc => 111storageStruct.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{112ContractStorage.solc => 112ContractStorage.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{113counter.solc => 113counter.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{131constructor.solc => 131constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{135cons3.solc => 135cons3.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/{StorageLib.solc => StorageLib.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/{051expreturn.solc => 051expreturn.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/{052return.solc => 052return.sol} (100%) rename crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/{053return.solc => 053return.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-contract-name.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-contract-name.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-contract-name.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-contract-name.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weird-error-foo.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weird-error-foo.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weird-error-foo.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weird-error-foo.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.sol diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.solc b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.solc rename to crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.sol From e7b341a5c61e04626fd987f230e629b5a3a80230 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 010/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test imports extensions Co-authored-by: Codex --- .../{select_alias_tail_fail.solc => select_alias_tail_fail.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/fail/test/imports/{select_alias_tail_fail.solc => select_alias_tail_fail.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.solc b/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.solc rename to crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.sol From 651a96f17fa99b042788e58875747a4847198828 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 011/110] Switch the compiler and fixtures to canonical syntax: parser corpus known diagnostic gaps test diagnostics extensions Co-authored-by: Codex --- .../{duplicate-definition.solc => duplicate-definition.sol} | 0 .../diagnostics/{missing-signature.solc => missing-signature.sol} | 0 .../{not-polymorphic-enough.solc => not-polymorphic-enough.sol} | 0 .../test/diagnostics/{type-mismatch.solc => type-mismatch.sol} | 0 .../test/diagnostics/{undefined-name.solc => undefined-name.sol} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/{duplicate-definition.solc => duplicate-definition.sol} (100%) rename crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/{missing-signature.solc => missing-signature.sol} (100%) rename crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/{not-polymorphic-enough.solc => not-polymorphic-enough.sol} (100%) rename crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/{type-mismatch.solc => type-mismatch.sol} (100%) rename crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/{undefined-name.solc => undefined-name.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.solc b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.solc rename to crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.sol diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/missing-signature.solc b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/missing-signature.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/missing-signature.solc rename to crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/missing-signature.sol diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.solc b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.solc rename to crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.sol diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.solc b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.solc rename to crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.sol diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.solc b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.solc rename to crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.sol From ee14960fbc793a926fe0db328a36eb9575200b51 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 012/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std ABIGeneric.sol extensions Co-authored-by: Codex --- .../fixtures/corpus/ok/std/{ABIGeneric.solc => ABIGeneric.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{ABIGeneric.solc => ABIGeneric.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.solc b/crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.solc rename to crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.sol From aa8b812a5cdb3515620a9d70be0946078665183b Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 013/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std Generic.sol extensions Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/{Generic.solc => Generic.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{Generic.solc => Generic.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/Generic.solc b/crates/parser/tests/fixtures/corpus/ok/std/Generic.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/Generic.solc rename to crates/parser/tests/fixtures/corpus/ok/std/Generic.sol From d5f4521523713064ab69cbb0487557332927d799 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 014/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std StorageGeneric.sol extensions Co-authored-by: Codex --- .../corpus/ok/std/{StorageGeneric.solc => StorageGeneric.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{StorageGeneric.solc => StorageGeneric.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.solc b/crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.solc rename to crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.sol From 8111207b3cc03dabe00ae9a2d0ce6d3b4660f2f4 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 015/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std dispatch.sol extensions Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/{dispatch.solc => dispatch.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{dispatch.solc => dispatch.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/dispatch.solc b/crates/parser/tests/fixtures/corpus/ok/std/dispatch.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/dispatch.solc rename to crates/parser/tests/fixtures/corpus/ok/std/dispatch.sol From 15346b5a0ad45eaeaa1f085ebd3913a913ce70cb Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 016/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std eip712.sol extensions Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/{eip712.solc => eip712.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{eip712.solc => eip712.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/eip712.solc b/crates/parser/tests/fixtures/corpus/ok/std/eip712.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/eip712.solc rename to crates/parser/tests/fixtures/corpus/ok/std/eip712.sol From 2c348d84bc7fa7b296058c1d4586f07c68c5dfd0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 017/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std eip7951.sol extensions Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/{eip7951.solc => eip7951.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{eip7951.solc => eip7951.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/eip7951.solc b/crates/parser/tests/fixtures/corpus/ok/std/eip7951.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/eip7951.solc rename to crates/parser/tests/fixtures/corpus/ok/std/eip7951.sol From 90f1ac9166f9c327def64149ab0d8e0a92dd24a2 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 018/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std opcodes.sol extensions Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/{opcodes.solc => opcodes.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{opcodes.solc => opcodes.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/opcodes.solc b/crates/parser/tests/fixtures/corpus/ok/std/opcodes.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/opcodes.solc rename to crates/parser/tests/fixtures/corpus/ok/std/opcodes.sol From 1078b87fb4611beb586190d949724f46c73da0c0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 019/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std std.sol extensions Co-authored-by: Codex --- crates/parser/tests/fixtures/corpus/ok/std/{std.solc => std.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/std/{std.solc => std.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/std.solc b/crates/parser/tests/fixtures/corpus/ok/std/std.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/std/std.solc rename to crates/parser/tests/fixtures/corpus/ok/std/std.sol From c98b908fb432f4aa599620275bda417074d978f4 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 020/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples extensions Co-authored-by: Codex --- .../ok/test/examples/cases/{Ackermann.solc => Ackermann.sol} | 0 .../corpus/ok/test/examples/cases/{Add1.solc => Add1.sol} | 0 .../corpus/ok/test/examples/cases/{BoolNot.solc => BoolNot.sol} | 0 .../corpus/ok/test/examples/cases/{Compose.solc => Compose.sol} | 0 .../corpus/ok/test/examples/cases/{Compose3.solc => Compose3.sol} | 0 .../corpus/ok/test/examples/cases/{CondExp.solc => CondExp.sol} | 0 .../test/examples/cases/{DuplicateFun.solc => DuplicateFun.sol} | 0 .../test/examples/cases/{EitherModule.solc => EitherModule.sol} | 0 .../corpus/ok/test/examples/cases/{EqQual.solc => EqQual.sol} | 0 .../corpus/ok/test/examples/cases/{EvenOdd.solc => EvenOdd.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{Foo.solc => Foo.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{Id.solc => Id.sol} | 0 .../ok/test/examples/cases/{ListModule.solc => ListModule.sol} | 0 .../corpus/ok/test/examples/cases/{Logic.solc => Logic.sol} | 0 .../ok/test/examples/cases/{MatchCall.solc => MatchCall.sol} | 0 .../corpus/ok/test/examples/cases/{Memory1.solc => Memory1.sol} | 0 .../corpus/ok/test/examples/cases/{Memory2.solc => Memory2.sol} | 0 .../corpus/ok/test/examples/cases/{Mutuals.solc => Mutuals.sol} | 0 .../corpus/ok/test/examples/cases/{NegPair.solc => NegPair.sol} | 0 .../corpus/ok/test/examples/cases/{Option.solc => Option.sol} | 0 .../corpus/ok/test/examples/cases/{Pair.solc => Pair.sol} | 0 .../corpus/ok/test/examples/cases/{Peano.solc => Peano.sol} | 0 .../ok/test/examples/cases/{PeanoMatch.solc => PeanoMatch.sol} | 0 .../corpus/ok/test/examples/cases/{RefDeref.solc => RefDeref.sol} | 0 .../test/examples/cases/{SimpleLambda.solc => SimpleLambda.sol} | 0 .../ok/test/examples/cases/{SingleFun.solc => SingleFun.sol} | 0 .../corpus/ok/test/examples/cases/{Uncurry.solc => Uncurry.sol} | 0 .../ok/test/examples/cases/{abigeneric.solc => abigeneric.sol} | 0 .../test/examples/cases/{another-subst.solc => another-subst.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{app.solc => app.sol} | 0 .../corpus/ok/test/examples/cases/{array.solc => array.sol} | 0 .../cases/{asm-let-bool-lit.solc => asm-let-bool-lit.sol} | 0 .../examples/cases/{asm-let-uninit.solc => asm-let-uninit.sol} | 0 .../cases/{asm-match-tuple-read.solc => asm-match-tuple-read.sol} | 0 ...match-tuple-write-read.solc => asm-match-tuple-write-read.sol} | 0 .../corpus/ok/test/examples/cases/{assembly.solc => assembly.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{bal.solc => bal.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{bar.solc => bar.sol} | 0 .../corpus/ok/test/examples/cases/{bitwise.solc => bitwise.sol} | 0 .../ok/test/examples/cases/{bool-elim.solc => bool-elim.sol} | 0 .../cases/{bound-merge-case.solc => bound-merge-case.sol} | 0 .../cases/{bound-with-pragma.solc => bound-with-pragma.sol} | 0 ...d-nontail-return.solc => bug-call-expected-nontail-return.sol} | 0 ...efault-inst-shadow.solc => bug-import-default-inst-shadow.sol} | 0 .../cases/{bug-rep-name-capture.solc => bug-rep-name-capture.sol} | 0 .../ok/test/examples/cases/{catch-all.solc => catch-all.sol} | 0 .../test/examples/cases/{class-context.solc => class-context.sol} | 0 .../examples/cases/{clone-deriving.solc => clone-deriving.sol} | 0 .../cases/{closure-capture-only.solc => closure-capture-only.sol} | 0 .../{closure-free-bound-test.solc => closure-free-bound-test.sol} | 0 .../{closure-free-var-local.solc => closure-free-var-local.sol} | 0 .../cases/{closure-free-var-std.solc => closure-free-var-std.sol} | 0 .../cases/{closure-free-var.solc => closure-free-var.sol} | 0 .../corpus/ok/test/examples/cases/{closure.solc => closure.sol} | 0 .../ok/test/examples/cases/{comparisons.solc => comparisons.sol} | 0 .../corpus/ok/test/examples/cases/{compose0.solc => compose0.sol} | 0 .../cases/{compound-operators.solc => compound-operators.sol} | 0 .../corpus/ok/test/examples/cases/{const.solc => const.sol} | 0 ...ned-instance-context.solc => constrained-instance-context.sol} | 0 .../cases/{constrained-instance.solc => constrained-instance.sol} | 0 .../{constructor-weak-args.solc => constructor-weak-args.sol} | 0 .../{contract-local-derive.solc => contract-local-derive.sol} | 0 ...ocal-type-same-name.solc => contract-local-type-same-name.sol} | 0 .../ok/test/examples/cases/{copytomem.solc => copytomem.sol} | 0 .../{cyclical-defs-inferred.solc => cyclical-defs-inferred.sol} | 0 .../test/examples/cases/{cyclical-defs.solc => cyclical-defs.sol} | 0 .../cases/{derive-custom-hash.solc => derive-custom-hash.sol} | 0 .../cases/{derive-eq-action.solc => derive-eq-action.sol} | 0 .../examples/cases/{derive-eq-enum.solc => derive-eq-enum.sol} | 0 .../examples/cases/{derive-eq-pair.solc => derive-eq-pair.sol} | 0 .../{derive-generic-excluded.solc => derive-generic-excluded.sol} | 0 .../cases/{derive-generic-sum.solc => derive-generic-sum.sol} | 0 ...rive-universe-instances.solc => derive-universe-instances.sol} | 0 .../cases/{deriving-empty-type.solc => deriving-empty-type.sol} | 0 ...ignment-context.solc => dot-expression-assignment-context.sol} | 0 ...-call-arg-context.solc => dot-expression-call-arg-context.sol} | 0 ...expression-constructor.solc => dot-expression-constructor.sol} | 0 ...pression-match-return.solc => dot-expression-match-return.sol} | 0 ...sion-nested-context.solc => dot-expression-nested-context.sol} | 0 .../{dot-pattern-constructor.solc => dot-pattern-constructor.sol} | 0 ...nested-constructor.solc => dot-pattern-nested-constructor.sol} | 0 ...t-primitive-constructor.solc => dot-primitive-constructor.sol} | 0 .../ok/test/examples/cases/{empty-asm.solc => empty-asm.sol} | 0 .../corpus/ok/test/examples/cases/{encoder.solc => encoder.sol} | 0 .../corpus/ok/test/examples/cases/{encoder1.solc => encoder1.sol} | 0 .../{false-redundant-warning.solc => false-redundant-warning.sol} | 0 ...d-helper-cxt-collision.solc => field-helper-cxt-collision.sol} | 0 .../cases/{field-name-error.solc => field-name-error.sol} | 0 .../ok/test/examples/cases/{foo-class.solc => foo-class.sol} | 0 .../examples/cases/{for-body-shadow.solc => for-body-shadow.sol} | 0 .../ok/test/examples/cases/{for-break.solc => for-break.sol} | 0 .../test/examples/cases/{for-continue.solc => for-continue.sol} | 0 .../examples/cases/{for-empty-init.solc => for-empty-init.sol} | 0 .../examples/cases/{for-init-shadow.solc => for-init-shadow.sol} | 0 .../examples/cases/{for-inner-block.solc => for-inner-block.sol} | 0 .../corpus/ok/test/examples/cases/{for-let.solc => for-let.sol} | 0 .../corpus/ok/test/examples/cases/{for-loop.solc => for-loop.sol} | 0 .../examples/cases/{for-multi-init.solc => for-multi-init.sol} | 0 .../examples/cases/{for-multi-post.solc => for-multi-post.sol} | 0 .../{fresh-pat-arg-synonym.solc => fresh-pat-arg-synonym.sol} | 0 .../test/examples/cases/{fresh-pat-arg.solc => fresh-pat-arg.sol} | 0 ...fresh-variable-shadowing.solc => fresh-variable-shadowing.sol} | 0 .../ok/test/examples/cases/{if-examples.solc => if-examples.sol} | 0 .../ok/test/examples/cases/{import-std.solc => import-std.sol} | 0 .../ok/test/examples/cases/{inc-closure.solc => inc-closure.sol} | 0 .../{instance-closure-error.solc => instance-closure-error.sol} | 0 .../cases/{instance-synonym-int.solc => instance-synonym-int.sol} | 0 .../cases/{instance-synonym.solc => instance-synonym.sol} | 0 .../examples/cases/{invokable-issue.solc => invokable-issue.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{ixa.solc => ixa.sol} | 0 .../corpus/ok/test/examples/cases/{join.solc => join.sol} | 0 .../corpus/ok/test/examples/cases/{listid.solc => listid.sol} | 0 .../corpus/ok/test/examples/cases/{ltimp.solc => ltimp.sol} | 0 .../corpus/ok/test/examples/cases/{ltproxy.solc => ltproxy.sol} | 0 .../test/examples/cases/{match-bitwise.solc => match-bitwise.sol} | 0 .../ok/test/examples/cases/{match-yul.solc => match-yul.sol} | 0 .../corpus/ok/test/examples/cases/{memory.solc => memory.sol} | 0 .../ok/test/examples/cases/{mod-example.solc => mod-example.sol} | 0 .../corpus/ok/test/examples/cases/{modifier.solc => modifier.sol} | 0 .../corpus/ok/test/examples/cases/{modulo.solc => modulo.sol} | 0 .../cases/{monomorphic-require.solc => monomorphic-require.sol} | 0 .../corpus/ok/test/examples/cases/{morefun.solc => morefun.sol} | 0 .../cases/{mptc-both-templates.solc => mptc-both-templates.sol} | 0 .../cases/{mptc-chain-phantom.solc => mptc-chain-phantom.sol} | 0 ...-guard-extras-concrete.solc => mptc-guard-extras-concrete.sol} | 0 .../cases/{mptc-multi-instance.solc => mptc-multi-instance.sol} | 0 .../cases/{mptc-nop-mainty-free.solc => mptc-nop-mainty-free.sol} | 0 .../{mptc-partial-instance.solc => mptc-partial-instance.sol} | 0 .../cases/{mptc-template-a-only.solc => mptc-template-a-only.sol} | 0 .../cases/{mptc-template-b-only.solc => mptc-template-b-only.sol} | 0 .../cases/{multi-stmt-var-leaf.solc => multi-stmt-var-leaf.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{nid.solc => nid.sol} | 0 .../ok/test/examples/cases/{noclosure.solc => noclosure.sol} | 0 .../corpus/ok/test/examples/cases/{notif.solc => notif.sol} | 0 .../corpus/ok/test/examples/cases/{option2.solc => option2.sol} | 0 .../corpus/ok/test/examples/cases/{pair-bug.solc => pair-bug.sol} | 0 .../corpus/ok/test/examples/cases/{pars.solc => pars.sol} | 0 .../{phantom-type-return-con.solc => phantom-type-return-con.sol} | 0 .../examples/cases/{polymatch-error.solc => polymatch-error.sol} | 0 .../cases/{polymorphic-require.solc => polymorphic-require.sol} | 0 .../cases/{pragma_merge_base.solc => pragma_merge_base.sol} | 0 .../{pragma_test_patterson.solc => pragma_test_patterson.sol} | 0 .../test/examples/cases/{proxy-desugar.solc => proxy-desugar.sol} | 0 .../corpus/ok/test/examples/cases/{proxy.solc => proxy.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{rec.solc => rec.sol} | 0 .../examples/cases/{redundant-match.solc => redundant-match.sol} | 0 .../{reference-encoding-good.solc => reference-encoding-good.sol} | 0 ...reference-encoding-good1.solc => reference-encoding-good1.sol} | 0 .../cases/{return-fun-adder.solc => return-fun-adder.sol} | 0 .../cases/{return-fun-const.solc => return-fun-const.sol} | 0 .../test/examples/cases/{return-fun-eq.solc => return-fun-eq.sol} | 0 .../cases/{return-fun-instance.solc => return-fun-instance.sol} | 0 ...tructor-qualifier.solc => same-name-constructor-qualifier.sol} | 0 .../examples/cases/{simpleDiscount.solc => simpleDiscount.sol} | 0 .../corpus/ok/test/examples/cases/{simpleid.solc => simpleid.sol} | 0 .../test/examples/cases/{single-lambda.solc => single-lambda.sol} | 0 .../corpus/ok/test/examples/cases/{snds.solc => snds.sol} | 0 .../cases/{spec-fail-ungrounded.solc => spec-fail-ungrounded.sol} | 0 ...age-adt-recursive-fail.solc => storage-adt-recursive-fail.sol} | 0 ...storage-adt-recursive-ok.solc => storage-adt-recursive-ok.sol} | 0 .../examples/cases/{strange-unbound.solc => strange-unbound.sol} | 0 .../cases/{sum-match-default.solc => sum-match-default.sol} | 0 .../cases/{super-class-cycle.solc => super-class-cycle.sol} | 0 .../examples/cases/{super-class-num.solc => super-class-num.sol} | 0 .../ok/test/examples/cases/{super-class.solc => super-class.sol} | 0 .../test/examples/cases/{synonym-basic.solc => synonym-basic.sol} | 0 .../cases/{synonym-in-function.solc => synonym-in-function.sol} | 0 .../examples/cases/{synonym-nested.solc => synonym-nested.sol} | 0 .../test/examples/cases/{synonym-param.solc => synonym-param.sol} | 0 .../{tabled-default-instance.solc => tabled-default-instance.sol} | 0 .../cases/{tabled-given-order.solc => tabled-given-order.sol} | 0 .../{tabled-residual-given.solc => tabled-residual-given.sol} | 0 .../fixtures/corpus/ok/test/examples/cases/{td.solc => td.sol} | 0 .../corpus/ok/test/examples/cases/{tiamat.solc => tiamat.sol} | 0 .../ok/test/examples/cases/{tuple-trick.solc => tuple-trick.sol} | 0 .../corpus/ok/test/examples/cases/{tuva.solc => tuva.sol} | 0 .../corpus/ok/test/examples/cases/{tyexp.solc => tyexp.sol} | 0 .../cases/{type-synonym-arg.solc => type-synonym-arg.sol} | 0 .../corpus/ok/test/examples/cases/{typedef.solc => typedef.sol} | 0 .../cases/{ufcs-no-conflict.solc => ufcs-no-conflict.sol} | 0 .../test/examples/cases/{uintdesugared.solc => uintdesugared.sol} | 0 .../ok/test/examples/cases/{undefined.solc => undefined.sol} | 0 .../corpus/ok/test/examples/cases/{unit.solc => unit.sol} | 0 .../cases/{word-match-default.solc => word-match-default.sol} | 0 .../ok/test/examples/cases/{word-match.solc => word-match.sol} | 0 ...break-continue-leave.solc => yul-asm-break-continue-leave.sol} | 0 .../cases/{yul-asm-for-body.solc => yul-asm-for-body.sol} | 0 .../cases/{yul-asm-switch-body.solc => yul-asm-switch-body.sol} | 0 .../cases/{yul-deposit-example.solc => yul-deposit-example.sol} | 0 .../corpus/ok/test/examples/cases/{yul-for.solc => yul-for.sol} | 0 .../cases/{yul-function-typing.solc => yul-function-typing.sol} | 0 .../cases/{yul-multi-return.solc => yul-multi-return.sol} | 0 .../ok/test/examples/cases/{yul-return.solc => yul-return.sol} | 0 .../ok/test/examples/comptime/{CondExpr.solc => CondExpr.sol} | 0 .../ok/test/examples/comptime/{CondStmt.solc => CondStmt.sol} | 0 .../corpus/ok/test/examples/comptime/{OneTwo.solc => OneTwo.sol} | 0 .../corpus/ok/test/examples/comptime/{Plus.solc => Plus.sol} | 0 .../corpus/ok/test/examples/comptime/{Size.solc => Size.sol} | 0 .../ok/test/examples/comptime/{StdSize.solc => StdSize.sol} | 0 .../comptime/{comptime_syntax.solc => comptime_syntax.sol} | 0 200 files changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Ackermann.solc => Ackermann.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Add1.solc => Add1.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{BoolNot.solc => BoolNot.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Compose.solc => Compose.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Compose3.solc => Compose3.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{CondExp.solc => CondExp.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{DuplicateFun.solc => DuplicateFun.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{EitherModule.solc => EitherModule.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{EqQual.solc => EqQual.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{EvenOdd.solc => EvenOdd.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Foo.solc => Foo.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Id.solc => Id.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{ListModule.solc => ListModule.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Logic.solc => Logic.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{MatchCall.solc => MatchCall.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Memory1.solc => Memory1.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Memory2.solc => Memory2.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Mutuals.solc => Mutuals.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{NegPair.solc => NegPair.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Option.solc => Option.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Pair.solc => Pair.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Peano.solc => Peano.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{PeanoMatch.solc => PeanoMatch.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{RefDeref.solc => RefDeref.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{SimpleLambda.solc => SimpleLambda.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{SingleFun.solc => SingleFun.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{Uncurry.solc => Uncurry.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{abigeneric.solc => abigeneric.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{another-subst.solc => another-subst.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{app.solc => app.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{array.solc => array.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{asm-let-bool-lit.solc => asm-let-bool-lit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{asm-let-uninit.solc => asm-let-uninit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{asm-match-tuple-read.solc => asm-match-tuple-read.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{asm-match-tuple-write-read.solc => asm-match-tuple-write-read.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{assembly.solc => assembly.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bal.solc => bal.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bar.solc => bar.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bitwise.solc => bitwise.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bool-elim.solc => bool-elim.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bound-merge-case.solc => bound-merge-case.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bound-with-pragma.solc => bound-with-pragma.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bug-call-expected-nontail-return.solc => bug-call-expected-nontail-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bug-import-default-inst-shadow.solc => bug-import-default-inst-shadow.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{bug-rep-name-capture.solc => bug-rep-name-capture.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{catch-all.solc => catch-all.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{class-context.solc => class-context.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{clone-deriving.solc => clone-deriving.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{closure-capture-only.solc => closure-capture-only.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{closure-free-bound-test.solc => closure-free-bound-test.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{closure-free-var-local.solc => closure-free-var-local.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{closure-free-var-std.solc => closure-free-var-std.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{closure-free-var.solc => closure-free-var.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{closure.solc => closure.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{comparisons.solc => comparisons.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{compose0.solc => compose0.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{compound-operators.solc => compound-operators.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{const.solc => const.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{constrained-instance-context.solc => constrained-instance-context.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{constrained-instance.solc => constrained-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{constructor-weak-args.solc => constructor-weak-args.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{contract-local-derive.solc => contract-local-derive.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{contract-local-type-same-name.solc => contract-local-type-same-name.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{copytomem.solc => copytomem.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{cyclical-defs-inferred.solc => cyclical-defs-inferred.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{cyclical-defs.solc => cyclical-defs.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-custom-hash.solc => derive-custom-hash.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-eq-action.solc => derive-eq-action.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-eq-enum.solc => derive-eq-enum.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-eq-pair.solc => derive-eq-pair.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-generic-excluded.solc => derive-generic-excluded.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-generic-sum.solc => derive-generic-sum.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{derive-universe-instances.solc => derive-universe-instances.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{deriving-empty-type.solc => deriving-empty-type.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-expression-assignment-context.solc => dot-expression-assignment-context.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-expression-call-arg-context.solc => dot-expression-call-arg-context.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-expression-constructor.solc => dot-expression-constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-expression-match-return.solc => dot-expression-match-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-expression-nested-context.solc => dot-expression-nested-context.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-pattern-constructor.solc => dot-pattern-constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-pattern-nested-constructor.solc => dot-pattern-nested-constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{dot-primitive-constructor.solc => dot-primitive-constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{empty-asm.solc => empty-asm.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{encoder.solc => encoder.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{encoder1.solc => encoder1.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{false-redundant-warning.solc => false-redundant-warning.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{field-helper-cxt-collision.solc => field-helper-cxt-collision.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{field-name-error.solc => field-name-error.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{foo-class.solc => foo-class.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-body-shadow.solc => for-body-shadow.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-break.solc => for-break.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-continue.solc => for-continue.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-empty-init.solc => for-empty-init.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-init-shadow.solc => for-init-shadow.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-inner-block.solc => for-inner-block.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-let.solc => for-let.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-loop.solc => for-loop.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-multi-init.solc => for-multi-init.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{for-multi-post.solc => for-multi-post.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{fresh-pat-arg-synonym.solc => fresh-pat-arg-synonym.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{fresh-pat-arg.solc => fresh-pat-arg.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{fresh-variable-shadowing.solc => fresh-variable-shadowing.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{if-examples.solc => if-examples.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{import-std.solc => import-std.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{inc-closure.solc => inc-closure.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{instance-closure-error.solc => instance-closure-error.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{instance-synonym-int.solc => instance-synonym-int.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{instance-synonym.solc => instance-synonym.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{invokable-issue.solc => invokable-issue.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{ixa.solc => ixa.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{join.solc => join.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{listid.solc => listid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{ltimp.solc => ltimp.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{ltproxy.solc => ltproxy.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{match-bitwise.solc => match-bitwise.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{match-yul.solc => match-yul.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{memory.solc => memory.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mod-example.solc => mod-example.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{modifier.solc => modifier.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{modulo.solc => modulo.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{monomorphic-require.solc => monomorphic-require.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{morefun.solc => morefun.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-both-templates.solc => mptc-both-templates.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-chain-phantom.solc => mptc-chain-phantom.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-guard-extras-concrete.solc => mptc-guard-extras-concrete.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-multi-instance.solc => mptc-multi-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-nop-mainty-free.solc => mptc-nop-mainty-free.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-partial-instance.solc => mptc-partial-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-template-a-only.solc => mptc-template-a-only.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{mptc-template-b-only.solc => mptc-template-b-only.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{multi-stmt-var-leaf.solc => multi-stmt-var-leaf.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{nid.solc => nid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{noclosure.solc => noclosure.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{notif.solc => notif.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{option2.solc => option2.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{pair-bug.solc => pair-bug.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{pars.solc => pars.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{phantom-type-return-con.solc => phantom-type-return-con.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{polymatch-error.solc => polymatch-error.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{polymorphic-require.solc => polymorphic-require.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{pragma_merge_base.solc => pragma_merge_base.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{pragma_test_patterson.solc => pragma_test_patterson.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{proxy-desugar.solc => proxy-desugar.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{proxy.solc => proxy.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{rec.solc => rec.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{redundant-match.solc => redundant-match.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{reference-encoding-good.solc => reference-encoding-good.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{reference-encoding-good1.solc => reference-encoding-good1.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{return-fun-adder.solc => return-fun-adder.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{return-fun-const.solc => return-fun-const.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{return-fun-eq.solc => return-fun-eq.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{return-fun-instance.solc => return-fun-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{same-name-constructor-qualifier.solc => same-name-constructor-qualifier.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{simpleDiscount.solc => simpleDiscount.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{simpleid.solc => simpleid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{single-lambda.solc => single-lambda.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{snds.solc => snds.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{spec-fail-ungrounded.solc => spec-fail-ungrounded.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{storage-adt-recursive-fail.solc => storage-adt-recursive-fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{storage-adt-recursive-ok.solc => storage-adt-recursive-ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{strange-unbound.solc => strange-unbound.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{sum-match-default.solc => sum-match-default.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{super-class-cycle.solc => super-class-cycle.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{super-class-num.solc => super-class-num.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{super-class.solc => super-class.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{synonym-basic.solc => synonym-basic.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{synonym-in-function.solc => synonym-in-function.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{synonym-nested.solc => synonym-nested.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{synonym-param.solc => synonym-param.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tabled-default-instance.solc => tabled-default-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tabled-given-order.solc => tabled-given-order.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tabled-residual-given.solc => tabled-residual-given.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{td.solc => td.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tiamat.solc => tiamat.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tuple-trick.solc => tuple-trick.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tuva.solc => tuva.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{tyexp.solc => tyexp.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{type-synonym-arg.solc => type-synonym-arg.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{typedef.solc => typedef.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{ufcs-no-conflict.solc => ufcs-no-conflict.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{uintdesugared.solc => uintdesugared.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{undefined.solc => undefined.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{unit.solc => unit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{word-match-default.solc => word-match-default.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{word-match.solc => word-match.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-asm-break-continue-leave.solc => yul-asm-break-continue-leave.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-asm-for-body.solc => yul-asm-for-body.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-asm-switch-body.solc => yul-asm-switch-body.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-deposit-example.solc => yul-deposit-example.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-for.solc => yul-for.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-function-typing.solc => yul-function-typing.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-multi-return.solc => yul-multi-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/cases/{yul-return.solc => yul-return.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{CondExpr.solc => CondExpr.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{CondStmt.solc => CondStmt.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{OneTwo.solc => OneTwo.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{Plus.solc => Plus.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{Size.solc => Size.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{StdSize.solc => StdSize.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{comptime_syntax.solc => comptime_syntax.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.sol From 6fff393118252e2c03d9d92cf8ee94c46c5d7885 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 021/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples extensions Co-authored-by: Codex --- .../ok/test/examples/comptime/{counter.solc => counter.sol} | 0 .../ok/test/examples/comptime/{ct_asm_mem.solc => ct_asm_mem.sol} | 0 .../ok/test/examples/comptime/{ct_asm_ret.solc => ct_asm_ret.sol} | 0 .../test/examples/comptime/{ct_chain_ok.solc => ct_chain_ok.sol} | 0 .../ok/test/examples/comptime/{ct_let_ok.solc => ct_let_ok.sol} | 0 .../examples/comptime/{ct_let_runtime.solc => ct_let_runtime.sol} | 0 .../comptime/{ct_overloaded_bad.solc => ct_overloaded_bad.sol} | 0 .../comptime/{ct_overloaded_ok.solc => ct_overloaded_ok.sol} | 0 .../test/examples/comptime/{ct_param_ok.solc => ct_param_ok.sol} | 0 .../examples/comptime/{ct_runtime_arg.solc => ct_runtime_arg.sol} | 0 .../test/examples/comptime/{erc7201-lit.solc => erc7201-lit.sol} | 0 .../corpus/ok/test/examples/comptime/{fib.solc => fib.sol} | 0 .../corpus/ok/test/examples/comptime/{fib2.solc => fib2.sol} | 0 .../corpus/ok/test/examples/comptime/{fib3.solc => fib3.sol} | 0 .../comptime/{int-untyped-let.solc => int-untyped-let.sol} | 0 .../examples/comptime/{integer-basic.solc => integer-basic.sol} | 0 .../test/examples/comptime/{integer-fib.solc => integer-fib.sol} | 0 .../{integer-from-integer.solc => integer-from-integer.sol} | 0 .../comptime/{integer-lit-class.solc => integer-lit-class.sol} | 0 .../comptime/{integer-lit-cond.solc => integer-lit-cond.sol} | 0 .../comptime/{integer-lit-pat.solc => integer-lit-pat.sol} | 0 .../comptime/{integer-lit-poly.solc => integer-lit-poly.sol} | 0 .../comptime/{integer-lit-safe.solc => integer-lit-safe.sol} | 0 .../{integer-lit-word-site.solc => integer-lit-word-site.sol} | 0 .../test/examples/comptime/{integer-lit.solc => integer-lit.sol} | 0 .../examples/comptime/{match_labels.solc => match_labels.sol} | 0 .../comptime/{string-concat-mem.solc => string-concat-mem.sol} | 0 .../comptime/{string-lit-dedup.solc => string-lit-dedup.sol} | 0 .../comptime/{string-lit-keccak.solc => string-lit-keccak.sol} | 0 .../examples/comptime/{string-lit-len.solc => string-lit-len.sol} | 0 .../examples/comptime/{string-lit-mem.solc => string-lit-mem.sol} | 0 .../examples/comptime/{string-lit-ops.solc => string-lit-ops.sol} | 0 .../{string-param-erasure.solc => string-param-erasure.sol} | 0 .../{string-user-instance.solc => string-user-instance.sol} | 0 .../test/examples/comptime/{uint256-lit.solc => uint256-lit.sol} | 0 .../corpus/ok/test/examples/dispatch/{Revert.solc => Revert.sol} | 0 .../dispatch/{abi_address_array.solc => abi_address_array.sol} | 0 .../examples/dispatch/{abi_array_sum.solc => abi_array_sum.sol} | 0 .../examples/dispatch/{abi_batch_adt.solc => abi_batch_adt.sol} | 0 .../dispatch/{abi_bytes_array.solc => abi_bytes_array.sol} | 0 .../test/examples/dispatch/{abi_dyn_sum.solc => abi_dyn_sum.sol} | 0 .../dispatch/{abi_dyn_sum_return.solc => abi_dyn_sum_return.sol} | 0 .../examples/dispatch/{abi_encode_adt.solc => abi_encode_adt.sol} | 0 .../dispatch/{abi_encode_types.solc => abi_encode_types.sol} | 0 .../dispatch/{abi_sum_roundtrip.solc => abi_sum_roundtrip.sol} | 0 .../ok/test/examples/dispatch/{array_copy.solc => array_copy.sol} | 0 .../examples/dispatch/{array_nested.solc => array_nested.sol} | 0 .../ok/test/examples/dispatch/{array_ops.solc => array_ops.sol} | 0 .../examples/dispatch/{array_string.solc => array_string.sol} | 0 .../ok/test/examples/dispatch/{arraylit.solc => arraylit.sol} | 0 ...asm_break_continue_leave.solc => asm_break_continue_leave.sol} | 0 .../ok/test/examples/dispatch/{assembly.solc => assembly.sol} | 0 .../corpus/ok/test/examples/dispatch/{basic.solc => basic.sol} | 0 .../corpus/ok/test/examples/dispatch/{concat.solc => concat.sol} | 0 .../ok/test/examples/dispatch/{counter.solc => counter.sol} | 0 .../ok/test/examples/dispatch/{deposit.solc => deposit.sol} | 0 .../{derive_contract_local.solc => derive_contract_local.sol} | 0 .../ok/test/examples/dispatch/{derive_ord.solc => derive_ord.sol} | 0 .../ok/test/examples/dispatch/{ecrecover.solc => ecrecover.sol} | 0 .../corpus/ok/test/examples/dispatch/{eip712.solc => eip712.sol} | 0 .../corpus/ok/test/examples/dispatch/{empty.solc => empty.sol} | 0 .../{empty_no_constructor.solc => empty_no_constructor.sol} | 0 .../ok/test/examples/dispatch/{fallback.solc => fallback.sol} | 0 .../ok/test/examples/dispatch/{forloops.solc => forloops.sol} | 0 .../dispatch/{generic_product.solc => generic_product.sol} | 0 .../test/examples/dispatch/{generic_sum.solc => generic_sum.sol} | 0 .../corpus/ok/test/examples/dispatch/{hashes.solc => hashes.sol} | 0 .../corpus/ok/test/examples/dispatch/{memory.solc => memory.sol} | 0 .../ok/test/examples/dispatch/{miniERC20.solc => miniERC20.sol} | 0 .../corpus/ok/test/examples/dispatch/{neg.solc => neg.sol} | 0 .../dispatch/{nonpayable_ctor.solc => nonpayable_ctor.sol} | 0 .../ok/test/examples/dispatch/{ownable.solc => ownable.sol} | 0 .../ok/test/examples/dispatch/{p256verify.solc => p256verify.sol} | 0 .../ok/test/examples/dispatch/{payable.solc => payable.sol} | 0 .../examples/dispatch/{payable_ctor.solc => payable_ctor.sol} | 0 .../corpus/ok/test/examples/dispatch/{slices.solc => slices.sol} | 0 ...ecialise_sum_of_product.solc => specialise_sum_of_product.sol} | 0 .../ok/test/examples/dispatch/{storage.solc => storage.sol} | 0 .../dispatch/{storage_adt_abi.solc => storage_adt_abi.sol} | 0 .../dispatch/{storage_adt_bool.solc => storage_adt_bool.sol} | 0 .../dispatch/{storage_adt_enum.solc => storage_adt_enum.sol} | 0 .../dispatch/{storage_adt_field.solc => storage_adt_field.sol} | 0 .../{storage_adt_mapping.solc => storage_adt_mapping.sol} | 0 .../examples/dispatch/{storage_array.solc => storage_array.sol} | 0 .../{storage_dynamic_field.solc => storage_dynamic_field.sol} | 0 .../ok/test/examples/dispatch/{stringid.solc => stringid.sol} | 0 .../ok/test/examples/dispatch/{stringlit.solc => stringlit.sol} | 0 .../dispatch/{sum_wide_product.solc => sum_wide_product.sol} | 0 .../ok/test/examples/dispatch/{ufcs_array.solc => ufcs_array.sol} | 0 .../corpus/ok/test/examples/dispatch/{weth9.solc => weth9.sol} | 0 .../ok/test/examples/opcodes/{all-shapes.solc => all-shapes.sol} | 0 .../test/examples/opcodes/{terminators.solc => terminators.sol} | 0 .../ok/test/examples/pragmas/{coverage.solc => coverage.sol} | 0 .../ok/test/examples/pragmas/{patterson.solc => patterson.sol} | 0 .../corpus/ok/test/examples/spec/{00answer.solc => 00answer.sol} | 0 .../fixtures/corpus/ok/test/examples/spec/{01id.solc => 01id.sol} | 0 .../corpus/ok/test/examples/spec/{021not.solc => 021not.sol} | 0 .../corpus/ok/test/examples/spec/{022add.solc => 022add.sol} | 0 .../corpus/ok/test/examples/spec/{024arith.solc => 024arith.sol} | 0 .../corpus/ok/test/examples/spec/{02nid.solc => 02nid.sol} | 0 .../corpus/ok/test/examples/spec/{031maybe.solc => 031maybe.sol} | 0 .../test/examples/spec/{032simplejoin.solc => 032simplejoin.sol} | 0 .../corpus/ok/test/examples/spec/{033join.solc => 033join.sol} | 0 .../ok/test/examples/spec/{034cojoin.solc => 034cojoin.sol} | 0 .../ok/test/examples/spec/{035padding.solc => 035padding.sol} | 0 .../ok/test/examples/spec/{036wildcard.solc => 036wildcard.sol} | 0 .../ok/test/examples/spec/{037dwarves.solc => 037dwarves.sol} | 0 .../corpus/ok/test/examples/spec/{038food0.solc => 038food0.sol} | 0 .../corpus/ok/test/examples/spec/{039food.solc => 039food.sol} | 0 .../corpus/ok/test/examples/spec/{041pair.solc => 041pair.sol} | 0 .../ok/test/examples/spec/{042triple.solc => 042triple.sol} | 0 .../ok/test/examples/spec/{043fstsnd.solc => 043fstsnd.sol} | 0 .../corpus/ok/test/examples/spec/{047rgb.solc => 047rgb.sol} | 0 .../corpus/ok/test/examples/spec/{048rgb2.solc => 048rgb2.sol} | 0 .../corpus/ok/test/examples/spec/{049rgb3.solc => 049rgb3.sol} | 0 .../corpus/ok/test/examples/spec/{06comp.solc => 06comp.sol} | 0 .../corpus/ok/test/examples/spec/{09not.solc => 09not.sol} | 0 .../ok/test/examples/spec/{10negBool.solc => 10negBool.sol} | 0 .../ok/test/examples/spec/{11negPair.solc => 11negPair.sol} | 0 .../examples/spec/{120basicCounter.solc => 120basicCounter.sol} | 0 .../ok/test/examples/spec/{121counter.solc => 121counter.sol} | 0 .../ok/test/examples/spec/{122counters.solc => 122counters.sol} | 0 .../spec/{123stackAndStorage.solc => 123stackAndStorage.sol} | 0 .../ok/test/examples/spec/{126nanoerc20.solc => 126nanoerc20.sol} | 0 .../test/examples/spec/{127microerc20.solc => 127microerc20.sol} | 0 .../ok/test/examples/spec/{128minierc20.solc => 128minierc20.sol} | 0 .../examples/spec/{129arraystorage.solc => 129arraystorage.sol} | 0 .../test/examples/spec/{130arrayfield.solc => 130arrayfield.sol} | 0 .../test/examples/spec/{131localindex.solc => 131localindex.sol} | 0 .../examples/spec/{132nestedarray.solc => 132nestedarray.sol} | 0 .../examples/spec/{133arraystring.solc => 133arraystring.sol} | 0 .../ok/test/examples/spec/{135aliaspush.solc => 135aliaspush.sol} | 0 .../ok/test/examples/spec/{136arraylit.solc => 136arraylit.sol} | 0 .../spec/{137arraylitstorage.solc => 137arraylitstorage.sol} | 0 .../ok/test/examples/spec/{903badassign.solc => 903badassign.sol} | 0 .../ok/test/examples/spec/{939badfood.solc => 939badfood.sol} | 0 .../ok/test/examples/spec/{SimpleField.solc => SimpleField.sol} | 0 137 files changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{counter.solc => counter.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_asm_mem.solc => ct_asm_mem.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_asm_ret.solc => ct_asm_ret.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_chain_ok.solc => ct_chain_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_let_ok.solc => ct_let_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_let_runtime.solc => ct_let_runtime.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_overloaded_bad.solc => ct_overloaded_bad.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_overloaded_ok.solc => ct_overloaded_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_param_ok.solc => ct_param_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{ct_runtime_arg.solc => ct_runtime_arg.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{erc7201-lit.solc => erc7201-lit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{fib.solc => fib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{fib2.solc => fib2.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{fib3.solc => fib3.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{int-untyped-let.solc => int-untyped-let.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-basic.solc => integer-basic.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-fib.solc => integer-fib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-from-integer.solc => integer-from-integer.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit-class.solc => integer-lit-class.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit-cond.solc => integer-lit-cond.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit-pat.solc => integer-lit-pat.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit-poly.solc => integer-lit-poly.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit-safe.solc => integer-lit-safe.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit-word-site.solc => integer-lit-word-site.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{integer-lit.solc => integer-lit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{match_labels.solc => match_labels.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-concat-mem.solc => string-concat-mem.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-lit-dedup.solc => string-lit-dedup.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-lit-keccak.solc => string-lit-keccak.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-lit-len.solc => string-lit-len.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-lit-mem.solc => string-lit-mem.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-lit-ops.solc => string-lit-ops.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-param-erasure.solc => string-param-erasure.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{string-user-instance.solc => string-user-instance.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/{uint256-lit.solc => uint256-lit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{Revert.solc => Revert.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_address_array.solc => abi_address_array.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_array_sum.solc => abi_array_sum.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_batch_adt.solc => abi_batch_adt.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_bytes_array.solc => abi_bytes_array.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_dyn_sum.solc => abi_dyn_sum.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_dyn_sum_return.solc => abi_dyn_sum_return.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_encode_adt.solc => abi_encode_adt.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_encode_types.solc => abi_encode_types.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{abi_sum_roundtrip.solc => abi_sum_roundtrip.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{array_copy.solc => array_copy.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{array_nested.solc => array_nested.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{array_ops.solc => array_ops.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{array_string.solc => array_string.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{arraylit.solc => arraylit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{asm_break_continue_leave.solc => asm_break_continue_leave.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{assembly.solc => assembly.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{basic.solc => basic.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{concat.solc => concat.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{counter.solc => counter.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{deposit.solc => deposit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{derive_contract_local.solc => derive_contract_local.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{derive_ord.solc => derive_ord.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{ecrecover.solc => ecrecover.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{eip712.solc => eip712.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{empty.solc => empty.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{empty_no_constructor.solc => empty_no_constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{fallback.solc => fallback.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{forloops.solc => forloops.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{generic_product.solc => generic_product.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{generic_sum.solc => generic_sum.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{hashes.solc => hashes.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{memory.solc => memory.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{miniERC20.solc => miniERC20.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{neg.solc => neg.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{nonpayable_ctor.solc => nonpayable_ctor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{ownable.solc => ownable.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{p256verify.solc => p256verify.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{payable.solc => payable.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{payable_ctor.solc => payable_ctor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{slices.solc => slices.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{specialise_sum_of_product.solc => specialise_sum_of_product.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage.solc => storage.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_adt_abi.solc => storage_adt_abi.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_adt_bool.solc => storage_adt_bool.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_adt_enum.solc => storage_adt_enum.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_adt_field.solc => storage_adt_field.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_adt_mapping.solc => storage_adt_mapping.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_array.solc => storage_array.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{storage_dynamic_field.solc => storage_dynamic_field.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{stringid.solc => stringid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{stringlit.solc => stringlit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{sum_wide_product.solc => sum_wide_product.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{ufcs_array.solc => ufcs_array.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/{weth9.solc => weth9.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/{all-shapes.solc => all-shapes.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/{terminators.solc => terminators.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/{coverage.solc => coverage.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/{patterson.solc => patterson.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{00answer.solc => 00answer.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{01id.solc => 01id.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{021not.solc => 021not.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{022add.solc => 022add.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{024arith.solc => 024arith.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{02nid.solc => 02nid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{031maybe.solc => 031maybe.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{032simplejoin.solc => 032simplejoin.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{033join.solc => 033join.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{034cojoin.solc => 034cojoin.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{035padding.solc => 035padding.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{036wildcard.solc => 036wildcard.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{037dwarves.solc => 037dwarves.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{038food0.solc => 038food0.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{039food.solc => 039food.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{041pair.solc => 041pair.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{042triple.solc => 042triple.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{043fstsnd.solc => 043fstsnd.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{047rgb.solc => 047rgb.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{048rgb2.solc => 048rgb2.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{049rgb3.solc => 049rgb3.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{06comp.solc => 06comp.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{09not.solc => 09not.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{10negBool.solc => 10negBool.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{11negPair.solc => 11negPair.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{120basicCounter.solc => 120basicCounter.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{121counter.solc => 121counter.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{122counters.solc => 122counters.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{123stackAndStorage.solc => 123stackAndStorage.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{126nanoerc20.solc => 126nanoerc20.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{127microerc20.solc => 127microerc20.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{128minierc20.solc => 128minierc20.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{129arraystorage.solc => 129arraystorage.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{130arrayfield.solc => 130arrayfield.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{131localindex.solc => 131localindex.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{132nestedarray.solc => 132nestedarray.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{133arraystring.solc => 133arraystring.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{135aliaspush.solc => 135aliaspush.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{136arraylit.solc => 136arraylit.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{137arraylitstorage.solc => 137arraylitstorage.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{903badassign.solc => 903badassign.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{939badfood.solc => 939badfood.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/examples/spec/{SimpleField.solc => SimpleField.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.solc b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.solc rename to crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.sol From a9fc096999b46adaa58d24d949ea508bbc43bab7 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 022/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test imports extensions Co-authored-by: Codex --- .../corpus/ok/test/imports/{alias_dup.solc => alias_dup.sol} | 0 ...ias_hides_original_fail.solc => alias_hides_original_fail.sol} | 0 ...alified_constr_fail.solc => alias_unqualified_constr_fail.sol} | 0 ...s_unqualified_fun_fail.solc => alias_unqualified_fun_fail.sol} | 0 ...unqualified_type_fail.solc => alias_unqualified_type_fail.sol} | 0 .../tests/fixtures/corpus/ok/test/imports/{ambA.solc => ambA.sol} | 0 .../tests/fixtures/corpus/ok/test/imports/{ambB.solc => ambB.sol} | 0 .../corpus/ok/test/imports/{amb_main.solc => amb_main.sol} | 0 .../fixtures/corpus/ok/test/imports/{amb_ok.solc => amb_ok.sol} | 0 .../corpus/ok/test/imports/{boolalias.solc => boolalias.sol} | 0 .../imports/{boolalias_open_fail.solc => boolalias_open_fail.sol} | 0 .../ok/test/imports/{boolaliastype.solc => boolaliastype.sol} | 0 .../imports/{boolconselect_fail.solc => boolconselect_fail.sol} | 0 .../test/imports/{boolconselect_ok.solc => boolconselect_ok.sol} | 0 .../fixtures/corpus/ok/test/imports/{booldef.solc => booldef.sol} | 0 .../corpus/ok/test/imports/{boolmain.solc => boolmain.sol} | 0 .../ok/test/imports/{boolqualified.solc => boolqualified.sol} | 0 .../imports/{boolqualifiedtype.solc => boolqualifiedtype.sol} | 0 .../corpus/ok/test/imports/{boolselect.solc => boolselect.sol} | 0 .../fixtures/corpus/ok/test/imports/{cycleA.solc => cycleA.sol} | 0 .../fixtures/corpus/ok/test/imports/{cycleB.solc => cycleB.sol} | 0 .../corpus/ok/test/imports/{cycle_main.solc => cycle_main.sol} | 0 .../test/imports/{dot_context_expr.solc => dot_context_expr.sol} | 0 .../corpus/ok/test/imports/{dot_left.solc => dot_left.sol} | 0 .../corpus/ok/test/imports/{dot_right.solc => dot_right.sol} | 0 .../corpus/ok/test/imports/{dupqual_a.solc => dupqual_a.sol} | 0 .../corpus/ok/test/imports/{dupqual_b.solc => dupqual_b.sol} | 0 .../ok/test/imports/{dupqual_main.solc => dupqual_main.sol} | 0 .../imports/{dupqual_module_main.solc => dupqual_module_main.sol} | 0 .../{export_item_dup_fail.solc => export_item_dup_fail.sol} | 0 .../{export_module_dup_fail.solc => export_module_dup_fail.sol} | 0 .../{external_lib_alias_main.solc => external_lib_alias_main.sol} | 0 .../imports/{external_lib_main.solc => external_lib_main.sol} | 0 ...ternal_lib_missing_fail.solc => external_lib_missing_fail.sol} | 0 .../corpus/ok/test/imports/extlib/math/{api.solc => api.sol} | 0 .../ok/test/imports/extlib/math/internals/{add.solc => add.sol} | 0 .../corpus/ok/test/imports/extlib/{util.solc => util.sol} | 0 .../tests/fixtures/corpus/ok/test/imports/{foo.solc => foo.sol} | 0 .../fixtures/corpus/ok/test/imports/foo/{bar.solc => bar.sol} | 0 .../fixtures/corpus/ok/test/imports/foo/bar/{baz.solc => baz.sol} | 0 .../corpus/ok/test/imports/{glob_amb_a.solc => glob_amb_a.sol} | 0 .../corpus/ok/test/imports/{glob_amb_b.solc => glob_amb_b.sol} | 0 .../imports/{glob_amb_main_fail.solc => glob_amb_main_fail.sol} | 0 .../imports/{glob_export_mixed.solc => glob_export_mixed.sol} | 0 .../imports/{glob_hiding_amb_ok.solc => glob_hiding_amb_ok.sol} | 0 .../ok/test/imports/{glob_import_dup.solc => glob_import_dup.sol} | 0 .../imports/{glob_import_hiding.solc => glob_import_hiding.sol} | 0 ...ding_unknown_fail.solc => glob_import_hiding_unknown_fail.sol} | 0 .../imports/{glob_import_mixed.solc => glob_import_mixed.sol} | 0 .../ok/test/imports/{glob_import_ok.solc => glob_import_ok.sol} | 0 .../fixtures/corpus/ok/test/imports/{globlib.solc => globlib.sol} | 0 .../{hidden_ctor_dot_fail.solc => hidden_ctor_dot_fail.sol} | 0 .../{hidden_ctor_expr_fail.solc => hidden_ctor_expr_fail.sol} | 0 .../ok/test/imports/{hidden_ctor_lib.solc => hidden_ctor_lib.sol} | 0 ...nonexhaustive_fail.solc => hidden_ctor_nonexhaustive_fail.sol} | 0 ...hidden_ctor_pattern_fail.solc => hidden_ctor_pattern_fail.sol} | 0 .../{hidden_ctor_wildcard_ok.solc => hidden_ctor_wildcard_ok.sol} | 0 .../imports/{import_std_minimal.solc => import_std_minimal.sol} | 0 .../fixtures/corpus/ok/test/imports/{leak_a.solc => leak_a.sol} | 0 .../fixtures/corpus/ok/test/imports/{leak_b.solc => leak_b.sol} | 0 .../corpus/ok/test/imports/{leak_main.solc => leak_main.sol} | 0 .../fixtures/corpus/ok/test/imports/mirror/{api.solc => api.sol} | 0 .../corpus/ok/test/imports/mirror/{helper.solc => helper.sol} | 0 .../imports/{module_name_shadow.solc => module_name_shadow.sol} | 0 ...ualified_constructor.solc => module_qualified_constructor.sol} | 0 ...structor_alias.solc => module_qualified_constructor_alias.sol} | 0 ...ctor_pattern.solc => module_qualified_constructor_pattern.sol} | 0 ...lified_constr_fail.solc => module_unqualified_constr_fail.sol} | 0 ..._unqualified_fun_fail.solc => module_unqualified_fun_fail.sol} | 0 ...nqualified_type_fail.solc => module_unqualified_type_fail.sol} | 0 .../ok/test/imports/{nested_alias.solc => nested_alias.sol} | 0 .../{nested_deep_qualifier.solc => nested_deep_qualifier.sol} | 0 .../{nested_direct_qualifier.solc => nested_direct_qualifier.sol} | 0 .../imports/{nested_foo_and_bar.solc => nested_foo_and_bar.sol} | 0 .../ok/test/imports/{nested_select.solc => nested_select.sol} | 0 .../ok/test/imports/{ns_constr_dup.solc => ns_constr_dup.sol} | 0 .../corpus/ok/test/imports/{ns_cross_ok.solc => ns_cross_ok.sol} | 0 .../{opaque_alias_leak_fail.solc => opaque_alias_leak_fail.sol} | 0 .../imports/{opaque_alias_main.solc => opaque_alias_main.sol} | 0 .../test/imports/{opaque_alias_mid.solc => opaque_alias_mid.sol} | 0 ...lifier_leak_fail.solc => opaque_alias_qualifier_leak_fail.sol} | 0 .../ok/test/imports/{opaque_dep_base.solc => opaque_dep_base.sol} | 0 ...opaque_select_alias_main.solc => opaque_select_alias_main.sol} | 0 .../{opaque_select_alias_mid.solc => opaque_select_alias_mid.sol} | 0 ...t_direct_leak_fail.solc => opaque_select_direct_leak_fail.sol} | 0 ...opaque_select_direct_mid.solc => opaque_select_direct_mid.sol} | 0 .../test/imports/{pragma_scope_lib.solc => pragma_scope_lib.sol} | 0 .../imports/{pragma_scope_main.solc => pragma_scope_main.sol} | 0 .../ok/test/imports/{private_bad_lib.solc => private_bad_lib.sol} | 0 .../test/imports/{private_bad_main.solc => private_bad_main.sol} | 0 .../test/imports/{private_helper_a.solc => private_helper_a.sol} | 0 .../imports/{private_helper_main.solc => private_helper_main.sol} | 0 ...r_expr_hidden_fail.solc => reexport_ctor_expr_hidden_fail.sol} | 0 .../{reexport_ctor_expr_ok.solc => reexport_ctor_expr_ok.sol} | 0 ...export_ctor_hidden_fail.solc => reexport_ctor_hidden_fail.sol} | 0 .../imports/{reexport_ctor_mid.solc => reexport_ctor_mid.sol} | 0 .../{reexport_ctor_pattern.solc => reexport_ctor_pattern.sol} | 0 .../ok/test/imports/reexport_items/pkg/{api.solc => api.sol} | 0 .../ok/test/imports/reexport_items/pkg/{util.solc => util.sol} | 0 .../imports/{reexport_items_main.solc => reexport_items_main.sol} | 0 .../ok/test/imports/reexport_module/pkg/{api.solc => api.sol} | 0 .../imports/reexport_module/pkg/{api_alias.solc => api_alias.sol} | 0 .../ok/test/imports/reexport_module/pkg/{util.solc => util.sol} | 0 ...port_module_alias_main.solc => reexport_module_alias_main.sol} | 0 .../{reexport_module_main.solc => reexport_module_main.sol} | 0 ...port_select_alias_main.solc => reexport_select_alias_main.sol} | 0 ...elect_alias_wrapper.solc => reexport_select_alias_wrapper.sol} | 0 .../{reexport_select_base.solc => reexport_select_base.sol} | 0 .../{reexport_select_main.solc => reexport_select_main.sol} | 0 .../{reexport_select_wrapper.solc => reexport_select_wrapper.sol} | 0 .../ok/test/imports/rootcheck/nested/{main.solc => main.sol} | 0 .../test/imports/rootcheck/nested/{provider.solc => provider.sol} | 0 .../{relative_and_lib_main.solc => relative_and_lib_main.sol} | 0 .../ok/test/imports/rootcheck/{provider.solc => provider.sol} | 0 .../{select_alias_item_ok.solc => select_alias_item_ok.sol} | 0 .../{select_alias_multi_ok.solc => select_alias_multi_ok.sol} | 0 .../ok/test/imports/{select_dup_item.solc => select_dup_item.sol} | 0 .../corpus/ok/test/imports/{select_fail.solc => select_fail.sol} | 0 .../imports/{select_hiding_fail.solc => select_hiding_fail.sol} | 0 .../test/imports/{select_hiding_ok.solc => select_hiding_ok.sol} | 0 .../corpus/ok/test/imports/{select_ok.solc => select_ok.sol} | 0 .../imports/{select_shadow_local.solc => select_shadow_local.sol} | 0 .../{select_shadow_param_ok.solc => select_shadow_param_ok.sol} | 0 .../ok/test/imports/{select_unknown.solc => select_unknown.sol} | 0 ...e_unqualified_fun_ok.solc => selective_unqualified_fun_ok.sol} | 0 .../corpus/ok/test/imports/{selectlib.solc => selectlib.sol} | 0 .../corpus/ok/test/imports/{selfcycle.solc => selfcycle.sol} | 0 .../test/imports/{strict_open_fail.solc => strict_open_fail.sol} | 0 .../{symlink_identity_fail.solc => symlink_identity_fail.sol} | 0 .../corpus/ok/test/imports/symlink_impl/{api.solc => api.sol} | 0 .../imports/{transitive_dep_base.solc => transitive_dep_base.sol} | 0 ...sitive_dep_main_module.solc => transitive_dep_main_module.sol} | 0 ...sitive_dep_main_select.solc => transitive_dep_main_select.sol} | 0 .../imports/{transitive_dep_mid.solc => transitive_dep_mid.sol} | 0 .../test/imports/{type_collision_a.solc => type_collision_a.sol} | 0 .../test/imports/{type_collision_b.solc => type_collision_b.sol} | 0 .../imports/{type_collision_main.solc => type_collision_main.sol} | 0 .../{unordered_imports_lib.solc => unordered_imports_lib.sol} | 0 .../{unordered_imports_main.solc => unordered_imports_main.sol} | 0 .../corpus/ok/test/imports/vendor/math/{api.solc => api.sol} | 0 .../ok/test/imports/vendor/math/{helper.solc => helper.sol} | 0 .../fixtures/corpus/ok/test/imports/{wildA.solc => wildA.sol} | 0 .../fixtures/corpus/ok/test/imports/{wildB.solc => wildB.sol} | 0 .../corpus/ok/test/imports/{wild_main.solc => wild_main.sol} | 0 .../{wrapper_shadow_success.solc => wrapper_shadow_success.sol} | 0 145 files changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{alias_dup.solc => alias_dup.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{alias_hides_original_fail.solc => alias_hides_original_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{alias_unqualified_constr_fail.solc => alias_unqualified_constr_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{alias_unqualified_fun_fail.solc => alias_unqualified_fun_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{alias_unqualified_type_fail.solc => alias_unqualified_type_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{ambA.solc => ambA.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{ambB.solc => ambB.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{amb_main.solc => amb_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{amb_ok.solc => amb_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolalias.solc => boolalias.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolalias_open_fail.solc => boolalias_open_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolaliastype.solc => boolaliastype.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolconselect_fail.solc => boolconselect_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolconselect_ok.solc => boolconselect_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{booldef.solc => booldef.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolmain.solc => boolmain.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolqualified.solc => boolqualified.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolqualifiedtype.solc => boolqualifiedtype.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{boolselect.solc => boolselect.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{cycleA.solc => cycleA.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{cycleB.solc => cycleB.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{cycle_main.solc => cycle_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dot_context_expr.solc => dot_context_expr.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dot_left.solc => dot_left.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dot_right.solc => dot_right.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dupqual_a.solc => dupqual_a.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dupqual_b.solc => dupqual_b.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dupqual_main.solc => dupqual_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{dupqual_module_main.solc => dupqual_module_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{export_item_dup_fail.solc => export_item_dup_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{export_module_dup_fail.solc => export_module_dup_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{external_lib_alias_main.solc => external_lib_alias_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{external_lib_main.solc => external_lib_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{external_lib_missing_fail.solc => external_lib_missing_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/{api.solc => api.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/{add.solc => add.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/{util.solc => util.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{foo.solc => foo.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/foo/{bar.solc => bar.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/{baz.solc => baz.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_amb_a.solc => glob_amb_a.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_amb_b.solc => glob_amb_b.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_amb_main_fail.solc => glob_amb_main_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_export_mixed.solc => glob_export_mixed.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_hiding_amb_ok.solc => glob_hiding_amb_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_import_dup.solc => glob_import_dup.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_import_hiding.solc => glob_import_hiding.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_import_hiding_unknown_fail.solc => glob_import_hiding_unknown_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_import_mixed.solc => glob_import_mixed.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{glob_import_ok.solc => glob_import_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{globlib.solc => globlib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{hidden_ctor_dot_fail.solc => hidden_ctor_dot_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{hidden_ctor_expr_fail.solc => hidden_ctor_expr_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{hidden_ctor_lib.solc => hidden_ctor_lib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{hidden_ctor_nonexhaustive_fail.solc => hidden_ctor_nonexhaustive_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{hidden_ctor_pattern_fail.solc => hidden_ctor_pattern_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{hidden_ctor_wildcard_ok.solc => hidden_ctor_wildcard_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{import_std_minimal.solc => import_std_minimal.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{leak_a.solc => leak_a.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{leak_b.solc => leak_b.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{leak_main.solc => leak_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/{api.solc => api.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/{helper.solc => helper.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_name_shadow.solc => module_name_shadow.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_qualified_constructor.solc => module_qualified_constructor.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_qualified_constructor_alias.solc => module_qualified_constructor_alias.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_qualified_constructor_pattern.solc => module_qualified_constructor_pattern.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_unqualified_constr_fail.solc => module_unqualified_constr_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_unqualified_fun_fail.solc => module_unqualified_fun_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{module_unqualified_type_fail.solc => module_unqualified_type_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{nested_alias.solc => nested_alias.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{nested_deep_qualifier.solc => nested_deep_qualifier.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{nested_direct_qualifier.solc => nested_direct_qualifier.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{nested_foo_and_bar.solc => nested_foo_and_bar.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{nested_select.solc => nested_select.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{ns_constr_dup.solc => ns_constr_dup.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{ns_cross_ok.solc => ns_cross_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_alias_leak_fail.solc => opaque_alias_leak_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_alias_main.solc => opaque_alias_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_alias_mid.solc => opaque_alias_mid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_alias_qualifier_leak_fail.solc => opaque_alias_qualifier_leak_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_dep_base.solc => opaque_dep_base.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_select_alias_main.solc => opaque_select_alias_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_select_alias_mid.solc => opaque_select_alias_mid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_select_direct_leak_fail.solc => opaque_select_direct_leak_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{opaque_select_direct_mid.solc => opaque_select_direct_mid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{pragma_scope_lib.solc => pragma_scope_lib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{pragma_scope_main.solc => pragma_scope_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{private_bad_lib.solc => private_bad_lib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{private_bad_main.solc => private_bad_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{private_helper_a.solc => private_helper_a.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{private_helper_main.solc => private_helper_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_ctor_expr_hidden_fail.solc => reexport_ctor_expr_hidden_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_ctor_expr_ok.solc => reexport_ctor_expr_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_ctor_hidden_fail.solc => reexport_ctor_hidden_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_ctor_mid.solc => reexport_ctor_mid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_ctor_pattern.solc => reexport_ctor_pattern.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/{api.solc => api.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/{util.solc => util.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_items_main.solc => reexport_items_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/{api.solc => api.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/{api_alias.solc => api_alias.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/{util.solc => util.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_module_alias_main.solc => reexport_module_alias_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_module_main.solc => reexport_module_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_select_alias_main.solc => reexport_select_alias_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_select_alias_wrapper.solc => reexport_select_alias_wrapper.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_select_base.solc => reexport_select_base.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_select_main.solc => reexport_select_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{reexport_select_wrapper.solc => reexport_select_wrapper.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/{main.solc => main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/{provider.solc => provider.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/{relative_and_lib_main.solc => relative_and_lib_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/{provider.solc => provider.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_alias_item_ok.solc => select_alias_item_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_alias_multi_ok.solc => select_alias_multi_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_dup_item.solc => select_dup_item.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_fail.solc => select_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_hiding_fail.solc => select_hiding_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_hiding_ok.solc => select_hiding_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_ok.solc => select_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_shadow_local.solc => select_shadow_local.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_shadow_param_ok.solc => select_shadow_param_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{select_unknown.solc => select_unknown.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{selective_unqualified_fun_ok.solc => selective_unqualified_fun_ok.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{selectlib.solc => selectlib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{selfcycle.solc => selfcycle.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{strict_open_fail.solc => strict_open_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{symlink_identity_fail.solc => symlink_identity_fail.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_impl/{api.solc => api.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{transitive_dep_base.solc => transitive_dep_base.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{transitive_dep_main_module.solc => transitive_dep_main_module.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{transitive_dep_main_select.solc => transitive_dep_main_select.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{transitive_dep_mid.solc => transitive_dep_mid.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{type_collision_a.solc => type_collision_a.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{type_collision_b.solc => type_collision_b.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{type_collision_main.solc => type_collision_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{unordered_imports_lib.solc => unordered_imports_lib.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{unordered_imports_main.solc => unordered_imports_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/{api.solc => api.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/{helper.solc => helper.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{wildA.solc => wildA.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{wildB.solc => wildB.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{wild_main.solc => wild_main.sol} (100%) rename crates/parser/tests/fixtures/corpus/ok/test/imports/{wrapper_shadow_success.solc => wrapper_shadow_success.sol} (100%) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_missing_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_missing_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_missing_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_missing_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/foo.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/foo.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/api.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/api.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/api.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/api.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_hidden_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_hidden_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_hidden_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_hidden_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_mid.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_mid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_mid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_mid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/api.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/api.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/api.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/api.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api_alias.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api_alias.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api_alias.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/api_alias.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_impl/api.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_impl/api.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_impl/api.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_impl/api.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/api.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/api.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/api.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/api.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.sol diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.solc b/crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.sol similarity index 100% rename from crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.solc rename to crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.sol From da98bf52720ee95d7f9e2bfb4e8c37b6c61cf15b Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 023/110] Switch the compiler and fixtures to canonical syntax: parser fixtures extensions Co-authored-by: Codex --- .../fixtures/ok/{body_return_min.solc => body_return_min.sol} | 0 .../ok/{comptime_match_label.solc => comptime_match_label.sol} | 0 .../fixtures/ok/{comptime_modifier.solc => comptime_modifier.sol} | 0 ..._fallback.solc => contract_modifiers_constructor_fallback.sol} | 0 .../ok/{dot_ctor_expr_pattern.solc => dot_ctor_expr_pattern.sol} | 0 .../ok/{export_operator_list.solc => export_operator_list.sol} | 0 .../fixtures/ok/{expression_bodied.solc => expression_bodied.sol} | 0 crates/parser/tests/fixtures/ok/{for_loop.solc => for_loop.sol} | 0 ...lias_operator_hiding.solc => import_alias_operator_hiding.sol} | 0 .../ok/{import_external_alias.solc => import_external_alias.sol} | 0 .../ok/{import_mixed_wildcard.solc => import_mixed_wildcard.sol} | 0 ...import_wildcard_selector.solc => import_wildcard_selector.sol} | 0 .../fixtures/ok/{match_arm_block.solc => match_arm_block.sol} | 0 ...match_trailing_semicolon.solc => match_trailing_semicolon.sol} | 0 .../tests/fixtures/ok/{no_diagnostics.solc => no_diagnostics.sol} | 0 ...erators_compound_assign.solc => operators_compound_assign.sol} | 0 .../fixtures/ok/{parser_catchup_h.solc => parser_catchup_h.sol} | 0 .../fixtures/ok/{proxy_expression.solc => proxy_expression.sol} | 0 .../fixtures/ok/{proxy_type_sugar.solc => proxy_type_sugar.sol} | 0 ...3_segment.solc => qualified_constructor_pattern_3_segment.sol} | 0 ...nstructor_patterns.solc => qualified_constructor_patterns.sol} | 0 .../ok/{qualified_type_return.solc => qualified_type_return.sol} | 0 .../fixtures/ok/{tuple_unit_sail.solc => tuple_unit_sail.sol} | 0 23 files changed, 0 insertions(+), 0 deletions(-) rename crates/parser/tests/fixtures/ok/{body_return_min.solc => body_return_min.sol} (100%) rename crates/parser/tests/fixtures/ok/{comptime_match_label.solc => comptime_match_label.sol} (100%) rename crates/parser/tests/fixtures/ok/{comptime_modifier.solc => comptime_modifier.sol} (100%) rename crates/parser/tests/fixtures/ok/{contract_modifiers_constructor_fallback.solc => contract_modifiers_constructor_fallback.sol} (100%) rename crates/parser/tests/fixtures/ok/{dot_ctor_expr_pattern.solc => dot_ctor_expr_pattern.sol} (100%) rename crates/parser/tests/fixtures/ok/{export_operator_list.solc => export_operator_list.sol} (100%) rename crates/parser/tests/fixtures/ok/{expression_bodied.solc => expression_bodied.sol} (100%) rename crates/parser/tests/fixtures/ok/{for_loop.solc => for_loop.sol} (100%) rename crates/parser/tests/fixtures/ok/{import_alias_operator_hiding.solc => import_alias_operator_hiding.sol} (100%) rename crates/parser/tests/fixtures/ok/{import_external_alias.solc => import_external_alias.sol} (100%) rename crates/parser/tests/fixtures/ok/{import_mixed_wildcard.solc => import_mixed_wildcard.sol} (100%) rename crates/parser/tests/fixtures/ok/{import_wildcard_selector.solc => import_wildcard_selector.sol} (100%) rename crates/parser/tests/fixtures/ok/{match_arm_block.solc => match_arm_block.sol} (100%) rename crates/parser/tests/fixtures/ok/{match_trailing_semicolon.solc => match_trailing_semicolon.sol} (100%) rename crates/parser/tests/fixtures/ok/{no_diagnostics.solc => no_diagnostics.sol} (100%) rename crates/parser/tests/fixtures/ok/{operators_compound_assign.solc => operators_compound_assign.sol} (100%) rename crates/parser/tests/fixtures/ok/{parser_catchup_h.solc => parser_catchup_h.sol} (100%) rename crates/parser/tests/fixtures/ok/{proxy_expression.solc => proxy_expression.sol} (100%) rename crates/parser/tests/fixtures/ok/{proxy_type_sugar.solc => proxy_type_sugar.sol} (100%) rename crates/parser/tests/fixtures/ok/{qualified_constructor_pattern_3_segment.solc => qualified_constructor_pattern_3_segment.sol} (100%) rename crates/parser/tests/fixtures/ok/{qualified_constructor_patterns.solc => qualified_constructor_patterns.sol} (100%) rename crates/parser/tests/fixtures/ok/{qualified_type_return.solc => qualified_type_return.sol} (100%) rename crates/parser/tests/fixtures/ok/{tuple_unit_sail.solc => tuple_unit_sail.sol} (100%) diff --git a/crates/parser/tests/fixtures/ok/body_return_min.solc b/crates/parser/tests/fixtures/ok/body_return_min.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/body_return_min.solc rename to crates/parser/tests/fixtures/ok/body_return_min.sol diff --git a/crates/parser/tests/fixtures/ok/comptime_match_label.solc b/crates/parser/tests/fixtures/ok/comptime_match_label.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/comptime_match_label.solc rename to crates/parser/tests/fixtures/ok/comptime_match_label.sol diff --git a/crates/parser/tests/fixtures/ok/comptime_modifier.solc b/crates/parser/tests/fixtures/ok/comptime_modifier.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/comptime_modifier.solc rename to crates/parser/tests/fixtures/ok/comptime_modifier.sol diff --git a/crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.solc b/crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.solc rename to crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.sol diff --git a/crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.solc b/crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.solc rename to crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.sol diff --git a/crates/parser/tests/fixtures/ok/export_operator_list.solc b/crates/parser/tests/fixtures/ok/export_operator_list.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/export_operator_list.solc rename to crates/parser/tests/fixtures/ok/export_operator_list.sol diff --git a/crates/parser/tests/fixtures/ok/expression_bodied.solc b/crates/parser/tests/fixtures/ok/expression_bodied.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/expression_bodied.solc rename to crates/parser/tests/fixtures/ok/expression_bodied.sol diff --git a/crates/parser/tests/fixtures/ok/for_loop.solc b/crates/parser/tests/fixtures/ok/for_loop.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/for_loop.solc rename to crates/parser/tests/fixtures/ok/for_loop.sol diff --git a/crates/parser/tests/fixtures/ok/import_alias_operator_hiding.solc b/crates/parser/tests/fixtures/ok/import_alias_operator_hiding.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/import_alias_operator_hiding.solc rename to crates/parser/tests/fixtures/ok/import_alias_operator_hiding.sol diff --git a/crates/parser/tests/fixtures/ok/import_external_alias.solc b/crates/parser/tests/fixtures/ok/import_external_alias.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/import_external_alias.solc rename to crates/parser/tests/fixtures/ok/import_external_alias.sol diff --git a/crates/parser/tests/fixtures/ok/import_mixed_wildcard.solc b/crates/parser/tests/fixtures/ok/import_mixed_wildcard.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/import_mixed_wildcard.solc rename to crates/parser/tests/fixtures/ok/import_mixed_wildcard.sol diff --git a/crates/parser/tests/fixtures/ok/import_wildcard_selector.solc b/crates/parser/tests/fixtures/ok/import_wildcard_selector.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/import_wildcard_selector.solc rename to crates/parser/tests/fixtures/ok/import_wildcard_selector.sol diff --git a/crates/parser/tests/fixtures/ok/match_arm_block.solc b/crates/parser/tests/fixtures/ok/match_arm_block.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/match_arm_block.solc rename to crates/parser/tests/fixtures/ok/match_arm_block.sol diff --git a/crates/parser/tests/fixtures/ok/match_trailing_semicolon.solc b/crates/parser/tests/fixtures/ok/match_trailing_semicolon.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/match_trailing_semicolon.solc rename to crates/parser/tests/fixtures/ok/match_trailing_semicolon.sol diff --git a/crates/parser/tests/fixtures/ok/no_diagnostics.solc b/crates/parser/tests/fixtures/ok/no_diagnostics.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/no_diagnostics.solc rename to crates/parser/tests/fixtures/ok/no_diagnostics.sol diff --git a/crates/parser/tests/fixtures/ok/operators_compound_assign.solc b/crates/parser/tests/fixtures/ok/operators_compound_assign.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/operators_compound_assign.solc rename to crates/parser/tests/fixtures/ok/operators_compound_assign.sol diff --git a/crates/parser/tests/fixtures/ok/parser_catchup_h.solc b/crates/parser/tests/fixtures/ok/parser_catchup_h.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/parser_catchup_h.solc rename to crates/parser/tests/fixtures/ok/parser_catchup_h.sol diff --git a/crates/parser/tests/fixtures/ok/proxy_expression.solc b/crates/parser/tests/fixtures/ok/proxy_expression.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/proxy_expression.solc rename to crates/parser/tests/fixtures/ok/proxy_expression.sol diff --git a/crates/parser/tests/fixtures/ok/proxy_type_sugar.solc b/crates/parser/tests/fixtures/ok/proxy_type_sugar.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/proxy_type_sugar.solc rename to crates/parser/tests/fixtures/ok/proxy_type_sugar.sol diff --git a/crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.solc b/crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.solc rename to crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.sol diff --git a/crates/parser/tests/fixtures/ok/qualified_constructor_patterns.solc b/crates/parser/tests/fixtures/ok/qualified_constructor_patterns.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/qualified_constructor_patterns.solc rename to crates/parser/tests/fixtures/ok/qualified_constructor_patterns.sol diff --git a/crates/parser/tests/fixtures/ok/qualified_type_return.solc b/crates/parser/tests/fixtures/ok/qualified_type_return.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/qualified_type_return.solc rename to crates/parser/tests/fixtures/ok/qualified_type_return.sol diff --git a/crates/parser/tests/fixtures/ok/tuple_unit_sail.solc b/crates/parser/tests/fixtures/ok/tuple_unit_sail.sol similarity index 100% rename from crates/parser/tests/fixtures/ok/tuple_unit_sail.solc rename to crates/parser/tests/fixtures/ok/tuple_unit_sail.sol From 6c3b893e1ba63f8cc50f67555bc8100f9129efba Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 024/110] Switch the compiler and fixtures to canonical syntax: specialize fixtures extensions Co-authored-by: Codex --- .../fixtures/derived_abi_evidence_replay/{abi.solc => abi.sol} | 0 .../{competitor.solc => competitor.sol} | 0 .../fixtures/derived_abi_evidence_replay/{main.solc => main.sol} | 0 .../derived_abi_evidence_replay/{reexport.solc => reexport.sol} | 0 .../derived_abi_evidence_replay/{types.solc => types.sol} | 0 .../derived_storage_evidence_replay/{main.solc => main.sol} | 0 .../{storage_support.solc => storage_support.sol} | 0 .../derived_storage_evidence_replay/{types.solc => types.sol} | 0 .../storage_field_definition_evidence/{api.solc => api.sol} | 0 .../{competitor.solc => competitor.sol} | 0 .../storage_field_definition_evidence/{lib.solc => lib.sol} | 0 .../storage_field_definition_evidence/{main.solc => main.sol} | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename crates/specialize/tests/fixtures/derived_abi_evidence_replay/{abi.solc => abi.sol} (100%) rename crates/specialize/tests/fixtures/derived_abi_evidence_replay/{competitor.solc => competitor.sol} (100%) rename crates/specialize/tests/fixtures/derived_abi_evidence_replay/{main.solc => main.sol} (100%) rename crates/specialize/tests/fixtures/derived_abi_evidence_replay/{reexport.solc => reexport.sol} (100%) rename crates/specialize/tests/fixtures/derived_abi_evidence_replay/{types.solc => types.sol} (100%) rename crates/specialize/tests/fixtures/derived_storage_evidence_replay/{main.solc => main.sol} (100%) rename crates/specialize/tests/fixtures/derived_storage_evidence_replay/{storage_support.solc => storage_support.sol} (100%) rename crates/specialize/tests/fixtures/derived_storage_evidence_replay/{types.solc => types.sol} (100%) rename crates/specialize/tests/fixtures/storage_field_definition_evidence/{api.solc => api.sol} (100%) rename crates/specialize/tests/fixtures/storage_field_definition_evidence/{competitor.solc => competitor.sol} (100%) rename crates/specialize/tests/fixtures/storage_field_definition_evidence/{lib.solc => lib.sol} (100%) rename crates/specialize/tests/fixtures/storage_field_definition_evidence/{main.solc => main.sol} (100%) diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.solc b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.solc rename to crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.sol diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.solc b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.solc rename to crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.sol diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.solc b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.solc rename to crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/reexport.solc b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/reexport.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_abi_evidence_replay/reexport.solc rename to crates/specialize/tests/fixtures/derived_abi_evidence_replay/reexport.sol diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.solc b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.solc rename to crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.sol diff --git a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.solc b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.solc rename to crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol diff --git a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.solc b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.solc rename to crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.sol diff --git a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.solc b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.sol similarity index 100% rename from crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.solc rename to crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.sol diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/api.solc b/crates/specialize/tests/fixtures/storage_field_definition_evidence/api.sol similarity index 100% rename from crates/specialize/tests/fixtures/storage_field_definition_evidence/api.solc rename to crates/specialize/tests/fixtures/storage_field_definition_evidence/api.sol diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.solc b/crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.sol similarity index 100% rename from crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.solc rename to crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.sol diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.solc b/crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.sol similarity index 100% rename from crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.solc rename to crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.sol diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/main.solc b/crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol similarity index 100% rename from crates/specialize/tests/fixtures/storage_field_definition_evidence/main.solc rename to crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol From 30221a927e61f9eb78bc0b9ea4324ed8c33b76b5 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 025/110] Switch the compiler and fixtures to canonical syntax: standard library extensions Co-authored-by: Codex --- std/{ABIGeneric.solc => ABIGeneric.sol} | 0 std/{Generic.solc => Generic.sol} | 0 std/{StorageGeneric.solc => StorageGeneric.sol} | 0 std/{dispatch.solc => dispatch.sol} | 0 std/{eip712.solc => eip712.sol} | 0 std/{eip7951.solc => eip7951.sol} | 0 std/{opcodes.solc => opcodes.sol} | 0 std/{std.solc => std.sol} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename std/{ABIGeneric.solc => ABIGeneric.sol} (100%) rename std/{Generic.solc => Generic.sol} (100%) rename std/{StorageGeneric.solc => StorageGeneric.sol} (100%) rename std/{dispatch.solc => dispatch.sol} (100%) rename std/{eip712.solc => eip712.sol} (100%) rename std/{eip7951.solc => eip7951.sol} (100%) rename std/{opcodes.solc => opcodes.sol} (100%) rename std/{std.solc => std.sol} (100%) diff --git a/std/ABIGeneric.solc b/std/ABIGeneric.sol similarity index 100% rename from std/ABIGeneric.solc rename to std/ABIGeneric.sol diff --git a/std/Generic.solc b/std/Generic.sol similarity index 100% rename from std/Generic.solc rename to std/Generic.sol diff --git a/std/StorageGeneric.solc b/std/StorageGeneric.sol similarity index 100% rename from std/StorageGeneric.solc rename to std/StorageGeneric.sol diff --git a/std/dispatch.solc b/std/dispatch.sol similarity index 100% rename from std/dispatch.solc rename to std/dispatch.sol diff --git a/std/eip712.solc b/std/eip712.sol similarity index 100% rename from std/eip712.solc rename to std/eip712.sol diff --git a/std/eip7951.solc b/std/eip7951.sol similarity index 100% rename from std/eip7951.solc rename to std/eip7951.sol diff --git a/std/opcodes.solc b/std/opcodes.sol similarity index 100% rename from std/opcodes.solc rename to std/opcodes.sol diff --git a/std/std.solc b/std/std.sol similarity index 100% rename from std/std.solc rename to std/std.sol From d6c4cf27abff3155506571468620decb06d74999 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 026/110] Switch the compiler and fixtures to canonical syntax: tests extensions Co-authored-by: Codex --- tests/e2e/00answer/{main.solc => main.sol} | 0 tests/e2e/01id/{main.solc => main.sol} | 0 tests/e2e/021not/{main.solc => main.sol} | 0 tests/e2e/022add/{main.solc => main.sol} | 0 tests/e2e/024arith/{main.solc => main.sol} | 0 tests/e2e/02nid/{main.solc => main.sol} | 0 tests/e2e/031maybe/{main.solc => main.sol} | 0 tests/e2e/032simplejoin/{main.solc => main.sol} | 0 tests/e2e/033join/{main.solc => main.sol} | 0 tests/e2e/034cojoin/{main.solc => main.sol} | 0 tests/e2e/035padding/{main.solc => main.sol} | 0 tests/e2e/036wildcard/{main.solc => main.sol} | 0 tests/e2e/037dwarves/{main.solc => main.sol} | 0 tests/e2e/038food0/{main.solc => main.sol} | 0 tests/e2e/039food/{main.solc => main.sol} | 0 tests/e2e/041pair/{main.solc => main.sol} | 0 tests/e2e/042triple/{main.solc => main.sol} | 0 tests/e2e/043fstsnd/{main.solc => main.sol} | 0 tests/e2e/047rgb/{main.solc => main.sol} | 0 tests/e2e/048rgb2/{main.solc => main.sol} | 0 tests/e2e/049rgb3/{main.solc => main.sol} | 0 tests/e2e/06comp/{main.solc => main.sol} | 0 tests/e2e/09not/{main.solc => main.sol} | 0 tests/e2e/10negBool/{main.solc => main.sol} | 0 tests/e2e/11negPair/{main.solc => main.sol} | 0 tests/e2e/120basicCounter/{main.solc => main.sol} | 0 tests/e2e/121counter/{main.solc => main.sol} | 0 tests/e2e/122counters/{main.solc => main.sol} | 0 tests/e2e/123stackAndStorage/{main.solc => main.sol} | 0 tests/e2e/126nanoerc20/{main.solc => main.sol} | 0 tests/e2e/127microerc20/{main.solc => main.sol} | 0 tests/e2e/128minierc20/{main.solc => main.sol} | 0 tests/e2e/903badassign/{main.solc => main.sol} | 0 tests/e2e/939badfood/{main.solc => main.sol} | 0 tests/e2e/SimpleField/{main.solc => main.sol} | 0 tests/e2e/abi-address-array/{main.solc => main.sol} | 0 tests/e2e/abi-array-sum/{main.solc => main.sol} | 0 tests/e2e/abi-batch-adt/{main.solc => main.sol} | 0 tests/e2e/abi-boundaries/{main.solc => main.sol} | 0 tests/e2e/abi-bytes-array/{main.solc => main.sol} | 0 tests/e2e/abi-dyn-sum-return/{main.solc => main.sol} | 0 tests/e2e/abi-dyn-sum/{main.solc => main.sol} | 0 tests/e2e/abi-encode-adt/{main.solc => main.sol} | 0 tests/e2e/abi-encode-types/{main.solc => main.sol} | 0 tests/e2e/abi-sum-roundtrip/{main.solc => main.sol} | 0 tests/e2e/arithmetic/{main.solc => main.sol} | 0 tests/e2e/array-copy/{main.solc => main.sol} | 0 tests/e2e/array-literals/{main.solc => main.sol} | 0 tests/e2e/array-nested/{main.solc => main.sol} | 0 tests/e2e/array-ops/{main.solc => main.sol} | 0 tests/e2e/array-string/{main.solc => main.sol} | 0 tests/e2e/arraylit/{main.solc => main.sol} | 0 tests/e2e/asm-break-continue-leave/{main.solc => main.sol} | 0 tests/e2e/assembly/{main.solc => main.sol} | 0 tests/e2e/audit-constructor-suffix/{main.solc => main.sol} | 0 tests/e2e/audit-nested-pair-tail/{main.solc => main.sol} | 0 tests/e2e/basic/{main.solc => main.sol} | 0 tests/e2e/composite-values/{main.solc => main.sol} | 0 .../e2e/compound-assignment-class-method/{main.solc => main.sol} | 0 tests/e2e/concat/{main.solc => main.sol} | 0 tests/e2e/deposit/{main.solc => main.sol} | 0 tests/e2e/derive-class/{main.solc => main.sol} | 0 tests/e2e/derive-contract-local/{main.solc => main.sol} | 0 tests/e2e/derive-ord/{main.solc => main.sol} | 0 tests/e2e/ecrecover/{main.solc => main.sol} | 0 tests/e2e/eip712/{main.solc => main.sol} | 0 tests/e2e/erc7201-comptime/{main.solc => main.sol} | 0 tests/e2e/fallback/{main.solc => main.sol} | 0 tests/e2e/forloops/{main.solc => main.sol} | 0 tests/e2e/generic-product/{main.solc => main.sol} | 0 tests/e2e/generic-sum/{main.solc => main.sol} | 0 tests/e2e/hashes/{main.solc => main.sol} | 0 tests/e2e/ltimp/{ltproxy.solc => ltproxy.sol} | 0 tests/e2e/ltimp/{main.solc => main.sol} | 0 tests/e2e/memory/{main.solc => main.sol} | 0 tests/e2e/mini-erc20/{main.solc => main.sol} | 0 tests/e2e/neg/{main.solc => main.sol} | 0 tests/e2e/nonpayable-ctor/{main.solc => main.sol} | 0 tests/e2e/ownable/{main.solc => main.sol} | 0 tests/e2e/p256verify/{main.solc => main.sol} | 0 tests/e2e/payable-ctor/{main.solc => main.sol} | 0 tests/e2e/payable/{main.solc => main.sol} | 0 tests/e2e/persistent-storage/{main.solc => main.sol} | 0 tests/e2e/raw-vector/{main.solc => main.sol} | 0 tests/e2e/revert-raw/{main.solc => main.sol} | 0 tests/e2e/revert/{main.solc => main.sol} | 0 tests/e2e/slices/{main.solc => main.sol} | 0 tests/e2e/specialise-sum-of-product/{main.solc => main.sol} | 0 tests/e2e/std-word-correctness/{main.solc => main.sol} | 0 tests/e2e/storage-adt-abi/{main.solc => main.sol} | 0 tests/e2e/storage-adt-bool/{main.solc => main.sol} | 0 tests/e2e/storage-adt-enum/{main.solc => main.sol} | 0 tests/e2e/storage-adt-field/{main.solc => main.sol} | 0 tests/e2e/storage-adt-mapping/{main.solc => main.sol} | 0 tests/e2e/storage-adt-recursive-ok/{main.solc => main.sol} | 0 tests/e2e/storage-array/{main.solc => main.sol} | 0 tests/e2e/storage-dynamic-field/{main.solc => main.sol} | 0 tests/e2e/storage-index-order/{main.solc => main.sol} | 0 tests/e2e/storage/{main.solc => main.sol} | 0 tests/e2e/stringlit/{main.solc => main.sol} | 0 tests/e2e/sum-wide-product/{main.solc => main.sol} | 0 tests/e2e/ufcs-array/{main.solc => main.sol} | 0 tests/e2e/weth9/{main.solc => main.sol} | 0 tests/e2e/yul-special-identifiers/{main.solc => main.sol} | 0 104 files changed, 0 insertions(+), 0 deletions(-) rename tests/e2e/00answer/{main.solc => main.sol} (100%) rename tests/e2e/01id/{main.solc => main.sol} (100%) rename tests/e2e/021not/{main.solc => main.sol} (100%) rename tests/e2e/022add/{main.solc => main.sol} (100%) rename tests/e2e/024arith/{main.solc => main.sol} (100%) rename tests/e2e/02nid/{main.solc => main.sol} (100%) rename tests/e2e/031maybe/{main.solc => main.sol} (100%) rename tests/e2e/032simplejoin/{main.solc => main.sol} (100%) rename tests/e2e/033join/{main.solc => main.sol} (100%) rename tests/e2e/034cojoin/{main.solc => main.sol} (100%) rename tests/e2e/035padding/{main.solc => main.sol} (100%) rename tests/e2e/036wildcard/{main.solc => main.sol} (100%) rename tests/e2e/037dwarves/{main.solc => main.sol} (100%) rename tests/e2e/038food0/{main.solc => main.sol} (100%) rename tests/e2e/039food/{main.solc => main.sol} (100%) rename tests/e2e/041pair/{main.solc => main.sol} (100%) rename tests/e2e/042triple/{main.solc => main.sol} (100%) rename tests/e2e/043fstsnd/{main.solc => main.sol} (100%) rename tests/e2e/047rgb/{main.solc => main.sol} (100%) rename tests/e2e/048rgb2/{main.solc => main.sol} (100%) rename tests/e2e/049rgb3/{main.solc => main.sol} (100%) rename tests/e2e/06comp/{main.solc => main.sol} (100%) rename tests/e2e/09not/{main.solc => main.sol} (100%) rename tests/e2e/10negBool/{main.solc => main.sol} (100%) rename tests/e2e/11negPair/{main.solc => main.sol} (100%) rename tests/e2e/120basicCounter/{main.solc => main.sol} (100%) rename tests/e2e/121counter/{main.solc => main.sol} (100%) rename tests/e2e/122counters/{main.solc => main.sol} (100%) rename tests/e2e/123stackAndStorage/{main.solc => main.sol} (100%) rename tests/e2e/126nanoerc20/{main.solc => main.sol} (100%) rename tests/e2e/127microerc20/{main.solc => main.sol} (100%) rename tests/e2e/128minierc20/{main.solc => main.sol} (100%) rename tests/e2e/903badassign/{main.solc => main.sol} (100%) rename tests/e2e/939badfood/{main.solc => main.sol} (100%) rename tests/e2e/SimpleField/{main.solc => main.sol} (100%) rename tests/e2e/abi-address-array/{main.solc => main.sol} (100%) rename tests/e2e/abi-array-sum/{main.solc => main.sol} (100%) rename tests/e2e/abi-batch-adt/{main.solc => main.sol} (100%) rename tests/e2e/abi-boundaries/{main.solc => main.sol} (100%) rename tests/e2e/abi-bytes-array/{main.solc => main.sol} (100%) rename tests/e2e/abi-dyn-sum-return/{main.solc => main.sol} (100%) rename tests/e2e/abi-dyn-sum/{main.solc => main.sol} (100%) rename tests/e2e/abi-encode-adt/{main.solc => main.sol} (100%) rename tests/e2e/abi-encode-types/{main.solc => main.sol} (100%) rename tests/e2e/abi-sum-roundtrip/{main.solc => main.sol} (100%) rename tests/e2e/arithmetic/{main.solc => main.sol} (100%) rename tests/e2e/array-copy/{main.solc => main.sol} (100%) rename tests/e2e/array-literals/{main.solc => main.sol} (100%) rename tests/e2e/array-nested/{main.solc => main.sol} (100%) rename tests/e2e/array-ops/{main.solc => main.sol} (100%) rename tests/e2e/array-string/{main.solc => main.sol} (100%) rename tests/e2e/arraylit/{main.solc => main.sol} (100%) rename tests/e2e/asm-break-continue-leave/{main.solc => main.sol} (100%) rename tests/e2e/assembly/{main.solc => main.sol} (100%) rename tests/e2e/audit-constructor-suffix/{main.solc => main.sol} (100%) rename tests/e2e/audit-nested-pair-tail/{main.solc => main.sol} (100%) rename tests/e2e/basic/{main.solc => main.sol} (100%) rename tests/e2e/composite-values/{main.solc => main.sol} (100%) rename tests/e2e/compound-assignment-class-method/{main.solc => main.sol} (100%) rename tests/e2e/concat/{main.solc => main.sol} (100%) rename tests/e2e/deposit/{main.solc => main.sol} (100%) rename tests/e2e/derive-class/{main.solc => main.sol} (100%) rename tests/e2e/derive-contract-local/{main.solc => main.sol} (100%) rename tests/e2e/derive-ord/{main.solc => main.sol} (100%) rename tests/e2e/ecrecover/{main.solc => main.sol} (100%) rename tests/e2e/eip712/{main.solc => main.sol} (100%) rename tests/e2e/erc7201-comptime/{main.solc => main.sol} (100%) rename tests/e2e/fallback/{main.solc => main.sol} (100%) rename tests/e2e/forloops/{main.solc => main.sol} (100%) rename tests/e2e/generic-product/{main.solc => main.sol} (100%) rename tests/e2e/generic-sum/{main.solc => main.sol} (100%) rename tests/e2e/hashes/{main.solc => main.sol} (100%) rename tests/e2e/ltimp/{ltproxy.solc => ltproxy.sol} (100%) rename tests/e2e/ltimp/{main.solc => main.sol} (100%) rename tests/e2e/memory/{main.solc => main.sol} (100%) rename tests/e2e/mini-erc20/{main.solc => main.sol} (100%) rename tests/e2e/neg/{main.solc => main.sol} (100%) rename tests/e2e/nonpayable-ctor/{main.solc => main.sol} (100%) rename tests/e2e/ownable/{main.solc => main.sol} (100%) rename tests/e2e/p256verify/{main.solc => main.sol} (100%) rename tests/e2e/payable-ctor/{main.solc => main.sol} (100%) rename tests/e2e/payable/{main.solc => main.sol} (100%) rename tests/e2e/persistent-storage/{main.solc => main.sol} (100%) rename tests/e2e/raw-vector/{main.solc => main.sol} (100%) rename tests/e2e/revert-raw/{main.solc => main.sol} (100%) rename tests/e2e/revert/{main.solc => main.sol} (100%) rename tests/e2e/slices/{main.solc => main.sol} (100%) rename tests/e2e/specialise-sum-of-product/{main.solc => main.sol} (100%) rename tests/e2e/std-word-correctness/{main.solc => main.sol} (100%) rename tests/e2e/storage-adt-abi/{main.solc => main.sol} (100%) rename tests/e2e/storage-adt-bool/{main.solc => main.sol} (100%) rename tests/e2e/storage-adt-enum/{main.solc => main.sol} (100%) rename tests/e2e/storage-adt-field/{main.solc => main.sol} (100%) rename tests/e2e/storage-adt-mapping/{main.solc => main.sol} (100%) rename tests/e2e/storage-adt-recursive-ok/{main.solc => main.sol} (100%) rename tests/e2e/storage-array/{main.solc => main.sol} (100%) rename tests/e2e/storage-dynamic-field/{main.solc => main.sol} (100%) rename tests/e2e/storage-index-order/{main.solc => main.sol} (100%) rename tests/e2e/storage/{main.solc => main.sol} (100%) rename tests/e2e/stringlit/{main.solc => main.sol} (100%) rename tests/e2e/sum-wide-product/{main.solc => main.sol} (100%) rename tests/e2e/ufcs-array/{main.solc => main.sol} (100%) rename tests/e2e/weth9/{main.solc => main.sol} (100%) rename tests/e2e/yul-special-identifiers/{main.solc => main.sol} (100%) diff --git a/tests/e2e/00answer/main.solc b/tests/e2e/00answer/main.sol similarity index 100% rename from tests/e2e/00answer/main.solc rename to tests/e2e/00answer/main.sol diff --git a/tests/e2e/01id/main.solc b/tests/e2e/01id/main.sol similarity index 100% rename from tests/e2e/01id/main.solc rename to tests/e2e/01id/main.sol diff --git a/tests/e2e/021not/main.solc b/tests/e2e/021not/main.sol similarity index 100% rename from tests/e2e/021not/main.solc rename to tests/e2e/021not/main.sol diff --git a/tests/e2e/022add/main.solc b/tests/e2e/022add/main.sol similarity index 100% rename from tests/e2e/022add/main.solc rename to tests/e2e/022add/main.sol diff --git a/tests/e2e/024arith/main.solc b/tests/e2e/024arith/main.sol similarity index 100% rename from tests/e2e/024arith/main.solc rename to tests/e2e/024arith/main.sol diff --git a/tests/e2e/02nid/main.solc b/tests/e2e/02nid/main.sol similarity index 100% rename from tests/e2e/02nid/main.solc rename to tests/e2e/02nid/main.sol diff --git a/tests/e2e/031maybe/main.solc b/tests/e2e/031maybe/main.sol similarity index 100% rename from tests/e2e/031maybe/main.solc rename to tests/e2e/031maybe/main.sol diff --git a/tests/e2e/032simplejoin/main.solc b/tests/e2e/032simplejoin/main.sol similarity index 100% rename from tests/e2e/032simplejoin/main.solc rename to tests/e2e/032simplejoin/main.sol diff --git a/tests/e2e/033join/main.solc b/tests/e2e/033join/main.sol similarity index 100% rename from tests/e2e/033join/main.solc rename to tests/e2e/033join/main.sol diff --git a/tests/e2e/034cojoin/main.solc b/tests/e2e/034cojoin/main.sol similarity index 100% rename from tests/e2e/034cojoin/main.solc rename to tests/e2e/034cojoin/main.sol diff --git a/tests/e2e/035padding/main.solc b/tests/e2e/035padding/main.sol similarity index 100% rename from tests/e2e/035padding/main.solc rename to tests/e2e/035padding/main.sol diff --git a/tests/e2e/036wildcard/main.solc b/tests/e2e/036wildcard/main.sol similarity index 100% rename from tests/e2e/036wildcard/main.solc rename to tests/e2e/036wildcard/main.sol diff --git a/tests/e2e/037dwarves/main.solc b/tests/e2e/037dwarves/main.sol similarity index 100% rename from tests/e2e/037dwarves/main.solc rename to tests/e2e/037dwarves/main.sol diff --git a/tests/e2e/038food0/main.solc b/tests/e2e/038food0/main.sol similarity index 100% rename from tests/e2e/038food0/main.solc rename to tests/e2e/038food0/main.sol diff --git a/tests/e2e/039food/main.solc b/tests/e2e/039food/main.sol similarity index 100% rename from tests/e2e/039food/main.solc rename to tests/e2e/039food/main.sol diff --git a/tests/e2e/041pair/main.solc b/tests/e2e/041pair/main.sol similarity index 100% rename from tests/e2e/041pair/main.solc rename to tests/e2e/041pair/main.sol diff --git a/tests/e2e/042triple/main.solc b/tests/e2e/042triple/main.sol similarity index 100% rename from tests/e2e/042triple/main.solc rename to tests/e2e/042triple/main.sol diff --git a/tests/e2e/043fstsnd/main.solc b/tests/e2e/043fstsnd/main.sol similarity index 100% rename from tests/e2e/043fstsnd/main.solc rename to tests/e2e/043fstsnd/main.sol diff --git a/tests/e2e/047rgb/main.solc b/tests/e2e/047rgb/main.sol similarity index 100% rename from tests/e2e/047rgb/main.solc rename to tests/e2e/047rgb/main.sol diff --git a/tests/e2e/048rgb2/main.solc b/tests/e2e/048rgb2/main.sol similarity index 100% rename from tests/e2e/048rgb2/main.solc rename to tests/e2e/048rgb2/main.sol diff --git a/tests/e2e/049rgb3/main.solc b/tests/e2e/049rgb3/main.sol similarity index 100% rename from tests/e2e/049rgb3/main.solc rename to tests/e2e/049rgb3/main.sol diff --git a/tests/e2e/06comp/main.solc b/tests/e2e/06comp/main.sol similarity index 100% rename from tests/e2e/06comp/main.solc rename to tests/e2e/06comp/main.sol diff --git a/tests/e2e/09not/main.solc b/tests/e2e/09not/main.sol similarity index 100% rename from tests/e2e/09not/main.solc rename to tests/e2e/09not/main.sol diff --git a/tests/e2e/10negBool/main.solc b/tests/e2e/10negBool/main.sol similarity index 100% rename from tests/e2e/10negBool/main.solc rename to tests/e2e/10negBool/main.sol diff --git a/tests/e2e/11negPair/main.solc b/tests/e2e/11negPair/main.sol similarity index 100% rename from tests/e2e/11negPair/main.solc rename to tests/e2e/11negPair/main.sol diff --git a/tests/e2e/120basicCounter/main.solc b/tests/e2e/120basicCounter/main.sol similarity index 100% rename from tests/e2e/120basicCounter/main.solc rename to tests/e2e/120basicCounter/main.sol diff --git a/tests/e2e/121counter/main.solc b/tests/e2e/121counter/main.sol similarity index 100% rename from tests/e2e/121counter/main.solc rename to tests/e2e/121counter/main.sol diff --git a/tests/e2e/122counters/main.solc b/tests/e2e/122counters/main.sol similarity index 100% rename from tests/e2e/122counters/main.solc rename to tests/e2e/122counters/main.sol diff --git a/tests/e2e/123stackAndStorage/main.solc b/tests/e2e/123stackAndStorage/main.sol similarity index 100% rename from tests/e2e/123stackAndStorage/main.solc rename to tests/e2e/123stackAndStorage/main.sol diff --git a/tests/e2e/126nanoerc20/main.solc b/tests/e2e/126nanoerc20/main.sol similarity index 100% rename from tests/e2e/126nanoerc20/main.solc rename to tests/e2e/126nanoerc20/main.sol diff --git a/tests/e2e/127microerc20/main.solc b/tests/e2e/127microerc20/main.sol similarity index 100% rename from tests/e2e/127microerc20/main.solc rename to tests/e2e/127microerc20/main.sol diff --git a/tests/e2e/128minierc20/main.solc b/tests/e2e/128minierc20/main.sol similarity index 100% rename from tests/e2e/128minierc20/main.solc rename to tests/e2e/128minierc20/main.sol diff --git a/tests/e2e/903badassign/main.solc b/tests/e2e/903badassign/main.sol similarity index 100% rename from tests/e2e/903badassign/main.solc rename to tests/e2e/903badassign/main.sol diff --git a/tests/e2e/939badfood/main.solc b/tests/e2e/939badfood/main.sol similarity index 100% rename from tests/e2e/939badfood/main.solc rename to tests/e2e/939badfood/main.sol diff --git a/tests/e2e/SimpleField/main.solc b/tests/e2e/SimpleField/main.sol similarity index 100% rename from tests/e2e/SimpleField/main.solc rename to tests/e2e/SimpleField/main.sol diff --git a/tests/e2e/abi-address-array/main.solc b/tests/e2e/abi-address-array/main.sol similarity index 100% rename from tests/e2e/abi-address-array/main.solc rename to tests/e2e/abi-address-array/main.sol diff --git a/tests/e2e/abi-array-sum/main.solc b/tests/e2e/abi-array-sum/main.sol similarity index 100% rename from tests/e2e/abi-array-sum/main.solc rename to tests/e2e/abi-array-sum/main.sol diff --git a/tests/e2e/abi-batch-adt/main.solc b/tests/e2e/abi-batch-adt/main.sol similarity index 100% rename from tests/e2e/abi-batch-adt/main.solc rename to tests/e2e/abi-batch-adt/main.sol diff --git a/tests/e2e/abi-boundaries/main.solc b/tests/e2e/abi-boundaries/main.sol similarity index 100% rename from tests/e2e/abi-boundaries/main.solc rename to tests/e2e/abi-boundaries/main.sol diff --git a/tests/e2e/abi-bytes-array/main.solc b/tests/e2e/abi-bytes-array/main.sol similarity index 100% rename from tests/e2e/abi-bytes-array/main.solc rename to tests/e2e/abi-bytes-array/main.sol diff --git a/tests/e2e/abi-dyn-sum-return/main.solc b/tests/e2e/abi-dyn-sum-return/main.sol similarity index 100% rename from tests/e2e/abi-dyn-sum-return/main.solc rename to tests/e2e/abi-dyn-sum-return/main.sol diff --git a/tests/e2e/abi-dyn-sum/main.solc b/tests/e2e/abi-dyn-sum/main.sol similarity index 100% rename from tests/e2e/abi-dyn-sum/main.solc rename to tests/e2e/abi-dyn-sum/main.sol diff --git a/tests/e2e/abi-encode-adt/main.solc b/tests/e2e/abi-encode-adt/main.sol similarity index 100% rename from tests/e2e/abi-encode-adt/main.solc rename to tests/e2e/abi-encode-adt/main.sol diff --git a/tests/e2e/abi-encode-types/main.solc b/tests/e2e/abi-encode-types/main.sol similarity index 100% rename from tests/e2e/abi-encode-types/main.solc rename to tests/e2e/abi-encode-types/main.sol diff --git a/tests/e2e/abi-sum-roundtrip/main.solc b/tests/e2e/abi-sum-roundtrip/main.sol similarity index 100% rename from tests/e2e/abi-sum-roundtrip/main.solc rename to tests/e2e/abi-sum-roundtrip/main.sol diff --git a/tests/e2e/arithmetic/main.solc b/tests/e2e/arithmetic/main.sol similarity index 100% rename from tests/e2e/arithmetic/main.solc rename to tests/e2e/arithmetic/main.sol diff --git a/tests/e2e/array-copy/main.solc b/tests/e2e/array-copy/main.sol similarity index 100% rename from tests/e2e/array-copy/main.solc rename to tests/e2e/array-copy/main.sol diff --git a/tests/e2e/array-literals/main.solc b/tests/e2e/array-literals/main.sol similarity index 100% rename from tests/e2e/array-literals/main.solc rename to tests/e2e/array-literals/main.sol diff --git a/tests/e2e/array-nested/main.solc b/tests/e2e/array-nested/main.sol similarity index 100% rename from tests/e2e/array-nested/main.solc rename to tests/e2e/array-nested/main.sol diff --git a/tests/e2e/array-ops/main.solc b/tests/e2e/array-ops/main.sol similarity index 100% rename from tests/e2e/array-ops/main.solc rename to tests/e2e/array-ops/main.sol diff --git a/tests/e2e/array-string/main.solc b/tests/e2e/array-string/main.sol similarity index 100% rename from tests/e2e/array-string/main.solc rename to tests/e2e/array-string/main.sol diff --git a/tests/e2e/arraylit/main.solc b/tests/e2e/arraylit/main.sol similarity index 100% rename from tests/e2e/arraylit/main.solc rename to tests/e2e/arraylit/main.sol diff --git a/tests/e2e/asm-break-continue-leave/main.solc b/tests/e2e/asm-break-continue-leave/main.sol similarity index 100% rename from tests/e2e/asm-break-continue-leave/main.solc rename to tests/e2e/asm-break-continue-leave/main.sol diff --git a/tests/e2e/assembly/main.solc b/tests/e2e/assembly/main.sol similarity index 100% rename from tests/e2e/assembly/main.solc rename to tests/e2e/assembly/main.sol diff --git a/tests/e2e/audit-constructor-suffix/main.solc b/tests/e2e/audit-constructor-suffix/main.sol similarity index 100% rename from tests/e2e/audit-constructor-suffix/main.solc rename to tests/e2e/audit-constructor-suffix/main.sol diff --git a/tests/e2e/audit-nested-pair-tail/main.solc b/tests/e2e/audit-nested-pair-tail/main.sol similarity index 100% rename from tests/e2e/audit-nested-pair-tail/main.solc rename to tests/e2e/audit-nested-pair-tail/main.sol diff --git a/tests/e2e/basic/main.solc b/tests/e2e/basic/main.sol similarity index 100% rename from tests/e2e/basic/main.solc rename to tests/e2e/basic/main.sol diff --git a/tests/e2e/composite-values/main.solc b/tests/e2e/composite-values/main.sol similarity index 100% rename from tests/e2e/composite-values/main.solc rename to tests/e2e/composite-values/main.sol diff --git a/tests/e2e/compound-assignment-class-method/main.solc b/tests/e2e/compound-assignment-class-method/main.sol similarity index 100% rename from tests/e2e/compound-assignment-class-method/main.solc rename to tests/e2e/compound-assignment-class-method/main.sol diff --git a/tests/e2e/concat/main.solc b/tests/e2e/concat/main.sol similarity index 100% rename from tests/e2e/concat/main.solc rename to tests/e2e/concat/main.sol diff --git a/tests/e2e/deposit/main.solc b/tests/e2e/deposit/main.sol similarity index 100% rename from tests/e2e/deposit/main.solc rename to tests/e2e/deposit/main.sol diff --git a/tests/e2e/derive-class/main.solc b/tests/e2e/derive-class/main.sol similarity index 100% rename from tests/e2e/derive-class/main.solc rename to tests/e2e/derive-class/main.sol diff --git a/tests/e2e/derive-contract-local/main.solc b/tests/e2e/derive-contract-local/main.sol similarity index 100% rename from tests/e2e/derive-contract-local/main.solc rename to tests/e2e/derive-contract-local/main.sol diff --git a/tests/e2e/derive-ord/main.solc b/tests/e2e/derive-ord/main.sol similarity index 100% rename from tests/e2e/derive-ord/main.solc rename to tests/e2e/derive-ord/main.sol diff --git a/tests/e2e/ecrecover/main.solc b/tests/e2e/ecrecover/main.sol similarity index 100% rename from tests/e2e/ecrecover/main.solc rename to tests/e2e/ecrecover/main.sol diff --git a/tests/e2e/eip712/main.solc b/tests/e2e/eip712/main.sol similarity index 100% rename from tests/e2e/eip712/main.solc rename to tests/e2e/eip712/main.sol diff --git a/tests/e2e/erc7201-comptime/main.solc b/tests/e2e/erc7201-comptime/main.sol similarity index 100% rename from tests/e2e/erc7201-comptime/main.solc rename to tests/e2e/erc7201-comptime/main.sol diff --git a/tests/e2e/fallback/main.solc b/tests/e2e/fallback/main.sol similarity index 100% rename from tests/e2e/fallback/main.solc rename to tests/e2e/fallback/main.sol diff --git a/tests/e2e/forloops/main.solc b/tests/e2e/forloops/main.sol similarity index 100% rename from tests/e2e/forloops/main.solc rename to tests/e2e/forloops/main.sol diff --git a/tests/e2e/generic-product/main.solc b/tests/e2e/generic-product/main.sol similarity index 100% rename from tests/e2e/generic-product/main.solc rename to tests/e2e/generic-product/main.sol diff --git a/tests/e2e/generic-sum/main.solc b/tests/e2e/generic-sum/main.sol similarity index 100% rename from tests/e2e/generic-sum/main.solc rename to tests/e2e/generic-sum/main.sol diff --git a/tests/e2e/hashes/main.solc b/tests/e2e/hashes/main.sol similarity index 100% rename from tests/e2e/hashes/main.solc rename to tests/e2e/hashes/main.sol diff --git a/tests/e2e/ltimp/ltproxy.solc b/tests/e2e/ltimp/ltproxy.sol similarity index 100% rename from tests/e2e/ltimp/ltproxy.solc rename to tests/e2e/ltimp/ltproxy.sol diff --git a/tests/e2e/ltimp/main.solc b/tests/e2e/ltimp/main.sol similarity index 100% rename from tests/e2e/ltimp/main.solc rename to tests/e2e/ltimp/main.sol diff --git a/tests/e2e/memory/main.solc b/tests/e2e/memory/main.sol similarity index 100% rename from tests/e2e/memory/main.solc rename to tests/e2e/memory/main.sol diff --git a/tests/e2e/mini-erc20/main.solc b/tests/e2e/mini-erc20/main.sol similarity index 100% rename from tests/e2e/mini-erc20/main.solc rename to tests/e2e/mini-erc20/main.sol diff --git a/tests/e2e/neg/main.solc b/tests/e2e/neg/main.sol similarity index 100% rename from tests/e2e/neg/main.solc rename to tests/e2e/neg/main.sol diff --git a/tests/e2e/nonpayable-ctor/main.solc b/tests/e2e/nonpayable-ctor/main.sol similarity index 100% rename from tests/e2e/nonpayable-ctor/main.solc rename to tests/e2e/nonpayable-ctor/main.sol diff --git a/tests/e2e/ownable/main.solc b/tests/e2e/ownable/main.sol similarity index 100% rename from tests/e2e/ownable/main.solc rename to tests/e2e/ownable/main.sol diff --git a/tests/e2e/p256verify/main.solc b/tests/e2e/p256verify/main.sol similarity index 100% rename from tests/e2e/p256verify/main.solc rename to tests/e2e/p256verify/main.sol diff --git a/tests/e2e/payable-ctor/main.solc b/tests/e2e/payable-ctor/main.sol similarity index 100% rename from tests/e2e/payable-ctor/main.solc rename to tests/e2e/payable-ctor/main.sol diff --git a/tests/e2e/payable/main.solc b/tests/e2e/payable/main.sol similarity index 100% rename from tests/e2e/payable/main.solc rename to tests/e2e/payable/main.sol diff --git a/tests/e2e/persistent-storage/main.solc b/tests/e2e/persistent-storage/main.sol similarity index 100% rename from tests/e2e/persistent-storage/main.solc rename to tests/e2e/persistent-storage/main.sol diff --git a/tests/e2e/raw-vector/main.solc b/tests/e2e/raw-vector/main.sol similarity index 100% rename from tests/e2e/raw-vector/main.solc rename to tests/e2e/raw-vector/main.sol diff --git a/tests/e2e/revert-raw/main.solc b/tests/e2e/revert-raw/main.sol similarity index 100% rename from tests/e2e/revert-raw/main.solc rename to tests/e2e/revert-raw/main.sol diff --git a/tests/e2e/revert/main.solc b/tests/e2e/revert/main.sol similarity index 100% rename from tests/e2e/revert/main.solc rename to tests/e2e/revert/main.sol diff --git a/tests/e2e/slices/main.solc b/tests/e2e/slices/main.sol similarity index 100% rename from tests/e2e/slices/main.solc rename to tests/e2e/slices/main.sol diff --git a/tests/e2e/specialise-sum-of-product/main.solc b/tests/e2e/specialise-sum-of-product/main.sol similarity index 100% rename from tests/e2e/specialise-sum-of-product/main.solc rename to tests/e2e/specialise-sum-of-product/main.sol diff --git a/tests/e2e/std-word-correctness/main.solc b/tests/e2e/std-word-correctness/main.sol similarity index 100% rename from tests/e2e/std-word-correctness/main.solc rename to tests/e2e/std-word-correctness/main.sol diff --git a/tests/e2e/storage-adt-abi/main.solc b/tests/e2e/storage-adt-abi/main.sol similarity index 100% rename from tests/e2e/storage-adt-abi/main.solc rename to tests/e2e/storage-adt-abi/main.sol diff --git a/tests/e2e/storage-adt-bool/main.solc b/tests/e2e/storage-adt-bool/main.sol similarity index 100% rename from tests/e2e/storage-adt-bool/main.solc rename to tests/e2e/storage-adt-bool/main.sol diff --git a/tests/e2e/storage-adt-enum/main.solc b/tests/e2e/storage-adt-enum/main.sol similarity index 100% rename from tests/e2e/storage-adt-enum/main.solc rename to tests/e2e/storage-adt-enum/main.sol diff --git a/tests/e2e/storage-adt-field/main.solc b/tests/e2e/storage-adt-field/main.sol similarity index 100% rename from tests/e2e/storage-adt-field/main.solc rename to tests/e2e/storage-adt-field/main.sol diff --git a/tests/e2e/storage-adt-mapping/main.solc b/tests/e2e/storage-adt-mapping/main.sol similarity index 100% rename from tests/e2e/storage-adt-mapping/main.solc rename to tests/e2e/storage-adt-mapping/main.sol diff --git a/tests/e2e/storage-adt-recursive-ok/main.solc b/tests/e2e/storage-adt-recursive-ok/main.sol similarity index 100% rename from tests/e2e/storage-adt-recursive-ok/main.solc rename to tests/e2e/storage-adt-recursive-ok/main.sol diff --git a/tests/e2e/storage-array/main.solc b/tests/e2e/storage-array/main.sol similarity index 100% rename from tests/e2e/storage-array/main.solc rename to tests/e2e/storage-array/main.sol diff --git a/tests/e2e/storage-dynamic-field/main.solc b/tests/e2e/storage-dynamic-field/main.sol similarity index 100% rename from tests/e2e/storage-dynamic-field/main.solc rename to tests/e2e/storage-dynamic-field/main.sol diff --git a/tests/e2e/storage-index-order/main.solc b/tests/e2e/storage-index-order/main.sol similarity index 100% rename from tests/e2e/storage-index-order/main.solc rename to tests/e2e/storage-index-order/main.sol diff --git a/tests/e2e/storage/main.solc b/tests/e2e/storage/main.sol similarity index 100% rename from tests/e2e/storage/main.solc rename to tests/e2e/storage/main.sol diff --git a/tests/e2e/stringlit/main.solc b/tests/e2e/stringlit/main.sol similarity index 100% rename from tests/e2e/stringlit/main.solc rename to tests/e2e/stringlit/main.sol diff --git a/tests/e2e/sum-wide-product/main.solc b/tests/e2e/sum-wide-product/main.sol similarity index 100% rename from tests/e2e/sum-wide-product/main.solc rename to tests/e2e/sum-wide-product/main.sol diff --git a/tests/e2e/ufcs-array/main.solc b/tests/e2e/ufcs-array/main.sol similarity index 100% rename from tests/e2e/ufcs-array/main.solc rename to tests/e2e/ufcs-array/main.sol diff --git a/tests/e2e/weth9/main.solc b/tests/e2e/weth9/main.sol similarity index 100% rename from tests/e2e/weth9/main.solc rename to tests/e2e/weth9/main.sol diff --git a/tests/e2e/yul-special-identifiers/main.solc b/tests/e2e/yul-special-identifiers/main.sol similarity index 100% rename from tests/e2e/yul-special-identifiers/main.solc rename to tests/e2e/yul-special-identifiers/main.sol From bd72496db3635ebf844f068bae6628f91b68aab0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 027/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures extensions Co-authored-by: Codex --- .../tests/fixtures/comptime/ct_asm_ret/{main.solc => main.sol} | 0 .../fixtures/comptime/ct_let_runtime/{main.solc => main.sol} | 0 .../fixtures/comptime/ct_overloaded_bad/{main.solc => main.sol} | 0 .../comptime/ct_param_poly_runtime/{main.solc => main.sol} | 0 .../fixtures/comptime/ct_param_runtime/{main.solc => main.sol} | 0 .../fixtures/comptime/ct_runtime_arg/{main.solc => main.sol} | 0 .../comptime/ergo_ct_fuel_infinite/{main.solc => main.sol} | 0 .../comptime/ergo_ct_let_runtime_param/{main.solc => main.sol} | 0 .../hull/assembly_assign_no_return/{main.solc => main.sol} | 0 .../hull/assembly_assign_non_word/{main.solc => main.sol} | 0 .../hull/assembly_multi_return_arity/{main.solc => main.sol} | 0 .../fixtures/hull/ergo_hull_multi_error/{main.solc => main.sol} | 0 .../fixtures/hull/ergo_hull_string_return/{main.solc => main.sol} | 0 .../hull/ergo_hull_word_match_no_default/{main.solc => main.sol} | 0 .../fixtures/hull/non_exhaustive_match/{main.solc => main.sol} | 0 .../fixtures/hull/ok_dispatch_storage/{main.solc => main.sol} | 0 .../hull/ok_guarded_runtime_recursion/{main.solc => main.sol} | 0 crates/uitest/tests/fixtures/nameres/ambiguous/{a.solc => a.sol} | 0 crates/uitest/tests/fixtures/nameres/ambiguous/{b.solc => b.sol} | 0 .../tests/fixtures/nameres/ambiguous/{main.solc => main.sol} | 0 .../fixtures/nameres/clean_undefined_name/{main.solc => main.sol} | 0 .../nameres/duplicate_export_cross_namespace/{a.solc => a.sol} | 0 .../nameres/duplicate_export_cross_namespace/{b.solc => b.sol} | 0 .../duplicate_export_cross_namespace/{main.solc => main.sol} | 0 .../nameres/duplicate_local_declarations/{main.solc => main.sol} | 0 .../nameres/duplicate_qualifier/baz/{bar.solc => bar.sol} | 0 .../nameres/duplicate_qualifier/foo/{bar.solc => bar.sol} | 0 .../fixtures/nameres/duplicate_qualifier/{main.solc => main.sol} | 0 .../fixtures/nameres/duplicate_selector/{main.solc => main.sol} | 0 .../fixtures/nameres/duplicate_selector/{util.solc => util.sol} | 0 .../fixtures/nameres/ergo_dup_data_class/{main.solc => main.sol} | 0 .../fixtures/nameres/ergo_dup_function/{main.solc => main.sol} | 0 .../nameres/ergo_import_module_typo/{helpers.solc => helpers.sol} | 0 .../nameres/ergo_import_module_typo/{main.solc => main.sol} | 0 .../nameres/ergo_import_symbol_typo/{main.solc => main.sol} | 0 .../nameres/ergo_import_symbol_typo/{util.solc => util.sol} | 0 .../nameres/ergo_private_qualified/{main.solc => main.sol} | 0 .../nameres/ergo_private_qualified/{vault.solc => vault.sol} | 0 .../nameres/ergo_typo_did_you_mean/{main.solc => main.sol} | 0 .../fixtures/nameres/ergo_undef_class/{main.solc => main.sol} | 0 .../nameres/ergo_undef_constructor/{main.solc => main.sol} | 0 .../fixtures/nameres/ergo_undef_type/{main.solc => main.sol} | 0 .../fixtures/nameres/ergo_undef_variable/{main.solc => main.sol} | 0 .../nameres/ergo_unqual_ctor_sc0106/{main.solc => main.sol} | 0 .../fixtures/nameres/ergo_value_as_type/{main.solc => main.sol} | 0 .../fixtures/nameres/glob_shadow_local/{lib.solc => lib.sol} | 0 .../fixtures/nameres/glob_shadow_local/{main.solc => main.sol} | 0 .../tests/fixtures/nameres/hidden_ctor/{lib.solc => lib.sol} | 0 .../tests/fixtures/nameres/hidden_ctor/{main.solc => main.sol} | 0 .../uitest/tests/fixtures/nameres/missing/{main.solc => main.sol} | 0 .../selected_import_ambiguity_cross_namespace/{a.solc => a.sol} | 0 .../selected_import_ambiguity_cross_namespace/{b.solc => b.sol} | 0 .../{main.solc => main.sol} | 0 .../{a.solc => a.sol} | 0 .../{b.solc => b.sol} | 0 .../{main.solc => main.sol} | 0 .../nameres/string_type_annotation/{main.solc => main.sol} | 0 .../nameres/undefined_name_namespaces/{main.solc => main.sol} | 0 .../tests/fixtures/nameres/unknown_import/{main.solc => main.sol} | 0 .../tests/fixtures/nameres/unknown_import/{util.solc => util.sol} | 0 .../unqualified_constructor_all_forms/{main.solc => main.sol} | 0 .../nameres/unqualified_ctor_expr/{main.solc => main.sol} | 0 .../nameres/unqualified_ctor_imported/{lib.solc => lib.sol} | 0 .../nameres/unqualified_ctor_imported/{main.solc => main.sol} | 0 .../nameres/unqualified_ctor_pattern/{main.solc => main.sol} | 0 .../unqualified_ctor_pattern_direction/{main.solc => main.sol} | 0 .../nameres/unqualified_ctor_plain_import/{lib.solc => lib.sol} | 0 .../nameres/unqualified_ctor_plain_import/{main.solc => main.sol} | 0 .../fixtures/nameres/unresolved_qualified/{main.solc => main.sol} | 0 .../fixtures/nameres/unresolved_qualified/{util.solc => util.sol} | 0 .../parse/assembly_trailing_semicolon/{main.solc => main.sol} | 0 .../parse/assignment_missing_semicolon/{main.solc => main.sol} | 0 .../parse/body_independent_errors/{main.solc => main.sol} | 0 .../fixtures/parse/body_invalid_token/{main.solc => main.sol} | 0 .../tests/fixtures/parse/bom_only_file/{main.solc => main.sol} | 0 .../fixtures/parse/data_trailing_pipe/{main.solc => main.sol} | 0 .../parse/delimiter_nesting_limit/{main.solc => main.sol} | 0 .../parse/ergo_assembly_unclosed_call/{main.solc => main.sol} | 0 .../parse/ergo_contract_missing_name/{main.solc => main.sol} | 0 .../parse/ergo_function_missing_params/{main.solc => main.sol} | 0 .../fixtures/parse/ergo_hull_empty_match/{main.solc => main.sol} | 0 .../parse/ergo_hull_fallback_args/{main.solc => main.sol} | 0 .../parse/ergo_import_trailing_dot/{main.solc => main.sol} | 0 .../parse/ergo_invalid_token_unicode/{main.solc => main.sol} | 0 .../fixtures/parse/ergo_keyword_as_ident/{main.solc => main.sol} | 0 .../parse/ergo_lambda_missing_parens/{main.solc => main.sol} | 0 .../parse/ergo_missing_semicolon_stmts/{main.solc => main.sol} | 0 .../parse/ergo_pragma_missing_semi/{main.solc => main.sol} | 0 .../parse/ergo_stray_top_level_semi/{main.solc => main.sol} | 0 .../parse/ergo_two_errors_recovery/{main.solc => main.sol} | 0 .../parse/ergo_unclosed_brace_eof/{main.solc => main.sol} | 0 .../parse/ergo_unterminated_block_comment/{main.solc => main.sol} | 0 .../parse/ergo_unterminated_string/{main.solc => main.sol} | 0 .../parse/excessive_conditional_nesting/{main.solc => main.sol} | 0 .../parse/excessive_expression_nesting/{main.solc => main.sol} | 0 .../parse/fallback_with_non_unit_return/{main.solc => main.sol} | 0 .../fixtures/parse/fallback_with_params/{main.solc => main.sol} | 0 .../parse/function_param_recovery/{main.solc => main.sol} | 0 .../parse/function_signature_missing_type/{main.solc => main.sol} | 0 .../fixtures/parse/if_trailing_semicolon/{main.solc => main.sol} | 0 .../parse/import_ctor_group_syntax/{main.solc => main.sol} | 0 .../parse/import_selector_unterminated/{main.solc => main.sol} | 0 .../tests/fixtures/parse/invalid_token/{main.solc => main.sol} | 0 .../parse/keyword_comptime_identifier/{main.solc => main.sol} | 0 .../fixtures/parse/missing_semicolon/{main.solc => main.sol} | 0 .../fixtures/parse/multibyte_eof_string/{main.solc => main.sol} | 0 .../parse/multiple_emitted_errors/{main.solc => main.sol} | 0 .../parse/multiple_errors_continue/{main.solc => main.sol} | 0 .../parse/nullary_ctor_applied_pattern/{main.solc => main.sol} | 0 .../fixtures/parse/pragma_missing_name/{main.solc => main.sol} | 0 .../fixtures/parse/public_constructor/{main.solc => main.sol} | 0 .../tests/fixtures/parse/public_fallback/{main.solc => main.sol} | 0 .../fixtures/parse/public_free_function/{main.solc => main.sol} | 0 .../fixtures/parse/string_bad_escape/{main.solc => main.sol} | 0 .../fixtures/parse/top_level_recovery/{main.solc => main.sol} | 0 .../fixtures/parse/trailing_call_comma/{main.solc => main.sol} | 0 .../parse/trailing_constructor_comma/{main.solc => main.sol} | 0 .../parse/type_alias_missing_equals/{main.solc => main.sol} | 0 .../solver/bounded_variable_condition/{main.solc => main.sol} | 0 .../fixtures/solver/coverage_condition/{main.solc => main.sol} | 0 .../coverage_condition_alias_expansion/{main.solc => main.sol} | 0 .../solver/ergo_ambiguous_defaulting/{main.solc => main.sol} | 0 .../solver/ergo_constraint_escape/{main.solc => main.sol} | 0 .../solver/ergo_contract_no_instance/{main.solc => main.sol} | 0 .../fixtures/solver/ergo_fuel_blowup/{main.solc => main.sol} | 0 .../fixtures/solver/ergo_inst_class_arity/{main.solc => main.sol} | 0 .../solver/ergo_inst_method_sig_mismatch/{main.solc => main.sol} | 0 .../fixtures/solver/ergo_inst_wrong_kind/{main.solc => main.sol} | 0 .../fixtures/solver/ergo_no_instance/{main.solc => main.sol} | 0 .../solver/ergo_overlapping_instances/{main.solc => main.sol} | 0 .../solver/ergo_patterson_violation/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../{pragma_scope_lib.solc => pragma_scope_lib.sol} | 0 .../fixtures/solver/instance_extra_method/{main.solc => main.sol} | 0 .../solver/invalid_default_instance/{main.solc => main.sol} | 0 .../local_given_rigid_var_unsatisfied/{main.solc => main.sol} | 0 .../fixtures/solver/method_extra_forall/{main.solc => main.sol} | 0 .../solver/non_ground_unique_answer/{main.solc => main.sol} | 0 .../noncallable_invokable_constraint/{main.solc => main.sol} | 0 .../fixtures/solver/patterson_condition/{main.solc => main.sol} | 0 .../fixtures/solver/poly_int_defaulting/{main.solc => main.sol} | 0 .../specialize/comptime_evaluation_failed/{main.solc => main.sol} | 0 .../comptime_return_evaluation_failed/{main.solc => main.sol} | 0 .../specialize/ergo_ct_public_param/{main.solc => main.sol} | 0 .../specialize/ergo_free_tyvar_ctor/{main.solc => main.sol} | 0 .../ergo_integer_erasure_branch/{main.solc => main.sol} | 0 .../fixtures/specialize/ergo_poly_entry/{main.solc => main.sol} | 0 .../specialize/free_type_variable/{main.solc => main.sol} | 0 .../fixtures/specialize/integer_erasure/{main.solc => main.sol} | 0 .../non_comptime_unconditional_recursion/{main.solc => main.sol} | 0 .../specialize/polyrec_type_size_fuel/{main.solc => main.sol} | 0 .../typeck/audit_class_as_type_lowering/{main.solc => main.sol} | 0 .../fixtures/typeck/audit_ctor_arity_none/{main.solc => main.sol} | 0 .../typeck/audit_literal_concrete_matrix/{main.solc => main.sol} | 0 .../fixtures/typeck/audit_literal_vs_opt/{main.solc => main.sol} | 0 .../audit_obligation_classification/{main.solc => main.sol} | 0 .../typeck/audit_return_type_name/{main.solc => main.sol} | 0 .../typeck/audit_value_namespace_matrix/{main.solc => main.sol} | 0 .../typeck/audit_value_namespace_matrix/{util.solc => util.sol} | 0 .../fixtures/typeck/call_arg_defined_here/{lib.solc => lib.sol} | 0 .../fixtures/typeck/call_arg_defined_here/{main.solc => main.sol} | 0 .../fixtures/typeck/call_arity_defined_here/{lib.solc => lib.sol} | 0 .../typeck/call_arity_defined_here/{main.solc => main.sol} | 0 .../fixtures/typeck/call_wrong_arity/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../comptime_class_head_method_signature/{main.solc => main.sol} | 0 .../comptime_class_method_runtime_arg/{main.solc => main.sol} | 0 .../contract_field_initializer_mismatch/{main.solc => main.sol} | 0 .../fixtures/typeck/desugar_origin_spans/{main.solc => main.sol} | 0 .../typeck/dispatch_name_collision_full/{main.solc => main.sol} | 0 .../typeck/duplicate_literal_unreachable/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../typeck/ergo_arg_type_mismatch/{main.solc => main.sol} | 0 .../fixtures/typeck/ergo_assign_mismatch/{main.solc => main.sol} | 0 .../typeck/ergo_call_too_few_args/{main.solc => main.sol} | 0 .../typeck/ergo_call_too_many_args/{main.solc => main.sol} | 0 .../typeck/ergo_ct_indirect_escape/{main.solc => main.sol} | 0 .../fixtures/typeck/ergo_ctor_arity_expr/{main.solc => main.sol} | 0 .../typeck/ergo_ctor_arity_pattern/{main.solc => main.sol} | 0 .../typeck/ergo_deep_nested_mismatch/{main.solc => main.sol} | 0 .../typeck/ergo_field_access_non_struct/{main.solc => main.sol} | 0 .../typeck/ergo_forall_tyvar_mismatch/{main.solc => main.sol} | 0 .../typeck/ergo_hull_asm_call_arity/{main.solc => main.sol} | 0 .../typeck/ergo_hull_asm_undefined_var/{main.solc => main.sol} | 0 .../typeck/ergo_if_expr_branch_mismatch/{main.solc => main.sol} | 0 .../typeck/ergo_lambda_body_mismatch/{main.solc => main.sol} | 0 .../typeck/ergo_match_branch_divergence/{main.solc => main.sol} | 0 .../typeck/ergo_multi_independent_errors/{main.solc => main.sol} | 0 .../typeck/ergo_occurs_lambda_msg/{main.solc => main.sol} | 0 .../typeck/ergo_pattern_wrong_type/{main.solc => main.sol} | 0 .../typeck/ergo_recovery_no_cascade/{main.solc => main.sol} | 0 .../typeck/ergo_return_type_mismatch_data/{main.solc => main.sol} | 0 .../typeck/ergo_tuple_arity_mismatch/{main.solc => main.sol} | 0 .../fixtures/typeck/ergo_type_as_value/{main.solc => main.sol} | 0 .../typeck/final_if_branch_mismatch/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../typeck/let_unannotated_literal/{main.solc => main.sol} | 0 .../manual_generic_adt_external_abi/{main.solc => main.sol} | 0 .../fixtures/typeck/match_branch_mismatch/{main.solc => main.sol} | 0 .../typeck/missing_word_abi_evidence/{main.solc => main.sol} | 0 200 files changed, 0 insertions(+), 0 deletions(-) rename crates/uitest/tests/fixtures/comptime/ct_asm_ret/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ct_let_runtime/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ct_param_runtime/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ct_runtime_arg/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/assembly_assign_no_return/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/assembly_assign_non_word/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/ergo_hull_string_return/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/non_exhaustive_match/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/ok_dispatch_storage/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ambiguous/{a.solc => a.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ambiguous/{b.solc => b.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ambiguous/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/clean_undefined_name/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/{a.solc => a.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/{b.solc => b.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_qualifier/baz/{bar.solc => bar.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_qualifier/foo/{bar.solc => bar.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_qualifier/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_selector/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/duplicate_selector/{util.solc => util.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_dup_function/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/{helpers.solc => helpers.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/{util.solc => util.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_private_qualified/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_private_qualified/{vault.solc => vault.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_undef_class/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_undef_type/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_undef_variable/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/ergo_value_as_type/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/glob_shadow_local/{lib.solc => lib.sol} (100%) rename crates/uitest/tests/fixtures/nameres/glob_shadow_local/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/hidden_ctor/{lib.solc => lib.sol} (100%) rename crates/uitest/tests/fixtures/nameres/hidden_ctor/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/missing/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/{a.solc => a.sol} (100%) rename crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/{b.solc => b.sol} (100%) rename crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/{a.solc => a.sol} (100%) rename crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/{b.solc => b.sol} (100%) rename crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/string_type_annotation/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unknown_import/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unknown_import/{util.solc => util.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/{lib.solc => lib.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/{lib.solc => lib.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unresolved_qualified/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/nameres/unresolved_qualified/{util.solc => util.sol} (100%) rename crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/body_independent_errors/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/body_invalid_token/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/bom_only_file/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/data_trailing_pipe/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_function_missing_params/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/ergo_unterminated_string/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/excessive_expression_nesting/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/fallback_with_params/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/function_param_recovery/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/function_signature_missing_type/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/if_trailing_semicolon/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/import_selector_unterminated/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/invalid_token/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/missing_semicolon/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/multibyte_eof_string/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/multiple_emitted_errors/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/multiple_errors_continue/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/pragma_missing_name/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/public_constructor/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/public_fallback/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/public_free_function/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/string_bad_escape/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/top_level_recovery/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/trailing_call_comma/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/trailing_constructor_comma/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/parse/type_alias_missing_equals/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/bounded_variable_condition/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/coverage_condition/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_constraint_escape/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_no_instance/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/ergo_patterson_violation/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/{pragma_scope_lib.solc => pragma_scope_lib.sol} (100%) rename crates/uitest/tests/fixtures/solver/instance_extra_method/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/invalid_default_instance/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/method_extra_forall/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/non_ground_unique_answer/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/patterson_condition/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/solver/poly_int_defaulting/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/ergo_poly_entry/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/free_type_variable/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/integer_erasure/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_obligation_classification/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_return_type_name/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/{util.solc => util.sol} (100%) rename crates/uitest/tests/fixtures/typeck/call_arg_defined_here/{lib.solc => lib.sol} (100%) rename crates/uitest/tests/fixtures/typeck/call_arg_defined_here/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/call_arity_defined_here/{lib.solc => lib.sol} (100%) rename crates/uitest/tests/fixtures/typeck/call_arity_defined_here/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/call_wrong_arity/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/desugar_origin_spans/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ergo_type_as_value/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/let_unannotated_literal/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/match_branch_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/{main.solc => main.sol} (100%) diff --git a/crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.solc b/crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.solc rename to crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.solc b/crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.solc rename to crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.solc b/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.solc rename to crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.solc b/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.solc rename to crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.solc b/crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.solc rename to crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.solc b/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.solc rename to crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.solc b/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.solc rename to crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol diff --git a/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.solc b/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.solc rename to crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol diff --git a/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.solc b/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.solc rename to crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol diff --git a/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.solc b/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.solc rename to crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol diff --git a/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.solc b/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.solc rename to crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.solc b/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.solc rename to crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.solc b/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.solc rename to crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.solc b/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.solc rename to crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol diff --git a/crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.solc b/crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.solc rename to crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol diff --git a/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.solc b/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.solc rename to crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol diff --git a/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.solc b/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.solc rename to crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ambiguous/a.solc b/crates/uitest/tests/fixtures/nameres/ambiguous/a.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ambiguous/a.solc rename to crates/uitest/tests/fixtures/nameres/ambiguous/a.sol diff --git a/crates/uitest/tests/fixtures/nameres/ambiguous/b.solc b/crates/uitest/tests/fixtures/nameres/ambiguous/b.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ambiguous/b.solc rename to crates/uitest/tests/fixtures/nameres/ambiguous/b.sol diff --git a/crates/uitest/tests/fixtures/nameres/ambiguous/main.solc b/crates/uitest/tests/fixtures/nameres/ambiguous/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ambiguous/main.solc rename to crates/uitest/tests/fixtures/nameres/ambiguous/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.solc b/crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.solc rename to crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.solc b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.solc b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.solc b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.solc b/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/baz/bar.solc b/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/baz/bar.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_qualifier/baz/bar.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_qualifier/baz/bar.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/foo/bar.solc b/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/foo/bar.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_qualifier/foo/bar.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_qualifier/foo/bar.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/main.solc b/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_qualifier/main.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_qualifier/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_selector/main.solc b/crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_selector/main.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_selector/util.solc b/crates/uitest/tests/fixtures/nameres/duplicate_selector/util.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/duplicate_selector/util.solc rename to crates/uitest/tests/fixtures/nameres/duplicate_selector/util.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.solc b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.solc rename to crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.solc b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.solc rename to crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.solc b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.solc rename to crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.solc b/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.solc rename to crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.solc b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.solc rename to crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.sol diff --git a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.solc b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.solc rename to crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.solc b/crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.solc rename to crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.sol diff --git a/crates/uitest/tests/fixtures/nameres/hidden_ctor/main.solc b/crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/hidden_ctor/main.solc rename to crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/missing/main.solc b/crates/uitest/tests/fixtures/nameres/missing/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/missing/main.solc rename to crates/uitest/tests/fixtures/nameres/missing/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.solc b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.solc rename to crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.sol diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.solc b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.solc rename to crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.sol diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.solc b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.solc rename to crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.solc b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.solc rename to crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.sol diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.solc b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.solc rename to crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.sol diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.solc b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.solc rename to crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/string_type_annotation/main.solc b/crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/string_type_annotation/main.solc rename to crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.solc b/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.solc rename to crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unknown_import/main.solc b/crates/uitest/tests/fixtures/nameres/unknown_import/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unknown_import/main.solc rename to crates/uitest/tests/fixtures/nameres/unknown_import/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unknown_import/util.solc b/crates/uitest/tests/fixtures/nameres/unknown_import/util.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unknown_import/util.solc rename to crates/uitest/tests/fixtures/nameres/unknown_import/util.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.solc b/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.solc b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.solc rename to crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.solc b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.solc rename to crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.solc b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.sol similarity index 100% rename from crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.solc rename to crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.sol diff --git a/crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/main.solc b/crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/main.solc rename to crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/main.sol diff --git a/crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/main.solc b/crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/main.solc rename to crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/main.sol diff --git a/crates/uitest/tests/fixtures/parse/body_independent_errors/main.solc b/crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/body_independent_errors/main.solc rename to crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol diff --git a/crates/uitest/tests/fixtures/parse/body_invalid_token/main.solc b/crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/body_invalid_token/main.solc rename to crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol diff --git a/crates/uitest/tests/fixtures/parse/bom_only_file/main.solc b/crates/uitest/tests/fixtures/parse/bom_only_file/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/bom_only_file/main.solc rename to crates/uitest/tests/fixtures/parse/bom_only_file/main.sol diff --git a/crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.solc b/crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.solc rename to crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol diff --git a/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.solc b/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.solc rename to crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.solc b/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.solc b/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.solc b/crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.solc b/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.solc b/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.solc b/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.solc b/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.solc b/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.solc b/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.solc b/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.solc b/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.solc b/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.solc b/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.solc b/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.solc b/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol diff --git a/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.solc b/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.solc rename to crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol diff --git a/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.solc b/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.solc rename to crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol diff --git a/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.solc b/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.solc rename to crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol diff --git a/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.solc b/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.solc rename to crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol diff --git a/crates/uitest/tests/fixtures/parse/fallback_with_params/main.solc b/crates/uitest/tests/fixtures/parse/fallback_with_params/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/fallback_with_params/main.solc rename to crates/uitest/tests/fixtures/parse/fallback_with_params/main.sol diff --git a/crates/uitest/tests/fixtures/parse/function_param_recovery/main.solc b/crates/uitest/tests/fixtures/parse/function_param_recovery/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/function_param_recovery/main.solc rename to crates/uitest/tests/fixtures/parse/function_param_recovery/main.sol diff --git a/crates/uitest/tests/fixtures/parse/function_signature_missing_type/main.solc b/crates/uitest/tests/fixtures/parse/function_signature_missing_type/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/function_signature_missing_type/main.solc rename to crates/uitest/tests/fixtures/parse/function_signature_missing_type/main.sol diff --git a/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.solc b/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.solc rename to crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol diff --git a/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.solc b/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.solc rename to crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol diff --git a/crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.solc b/crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.solc rename to crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol diff --git a/crates/uitest/tests/fixtures/parse/invalid_token/main.solc b/crates/uitest/tests/fixtures/parse/invalid_token/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/invalid_token/main.solc rename to crates/uitest/tests/fixtures/parse/invalid_token/main.sol diff --git a/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.solc b/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.solc rename to crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol diff --git a/crates/uitest/tests/fixtures/parse/missing_semicolon/main.solc b/crates/uitest/tests/fixtures/parse/missing_semicolon/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/missing_semicolon/main.solc rename to crates/uitest/tests/fixtures/parse/missing_semicolon/main.sol diff --git a/crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.solc b/crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.solc rename to crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol diff --git a/crates/uitest/tests/fixtures/parse/multiple_emitted_errors/main.solc b/crates/uitest/tests/fixtures/parse/multiple_emitted_errors/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/multiple_emitted_errors/main.solc rename to crates/uitest/tests/fixtures/parse/multiple_emitted_errors/main.sol diff --git a/crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.solc b/crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.solc rename to crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.sol diff --git a/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.solc b/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.solc rename to crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol diff --git a/crates/uitest/tests/fixtures/parse/pragma_missing_name/main.solc b/crates/uitest/tests/fixtures/parse/pragma_missing_name/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/pragma_missing_name/main.solc rename to crates/uitest/tests/fixtures/parse/pragma_missing_name/main.sol diff --git a/crates/uitest/tests/fixtures/parse/public_constructor/main.solc b/crates/uitest/tests/fixtures/parse/public_constructor/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/public_constructor/main.solc rename to crates/uitest/tests/fixtures/parse/public_constructor/main.sol diff --git a/crates/uitest/tests/fixtures/parse/public_fallback/main.solc b/crates/uitest/tests/fixtures/parse/public_fallback/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/public_fallback/main.solc rename to crates/uitest/tests/fixtures/parse/public_fallback/main.sol diff --git a/crates/uitest/tests/fixtures/parse/public_free_function/main.solc b/crates/uitest/tests/fixtures/parse/public_free_function/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/public_free_function/main.solc rename to crates/uitest/tests/fixtures/parse/public_free_function/main.sol diff --git a/crates/uitest/tests/fixtures/parse/string_bad_escape/main.solc b/crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/string_bad_escape/main.solc rename to crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol diff --git a/crates/uitest/tests/fixtures/parse/top_level_recovery/main.solc b/crates/uitest/tests/fixtures/parse/top_level_recovery/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/top_level_recovery/main.solc rename to crates/uitest/tests/fixtures/parse/top_level_recovery/main.sol diff --git a/crates/uitest/tests/fixtures/parse/trailing_call_comma/main.solc b/crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/trailing_call_comma/main.solc rename to crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol diff --git a/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.solc b/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.solc rename to crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol diff --git a/crates/uitest/tests/fixtures/parse/type_alias_missing_equals/main.solc b/crates/uitest/tests/fixtures/parse/type_alias_missing_equals/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/parse/type_alias_missing_equals/main.solc rename to crates/uitest/tests/fixtures/parse/type_alias_missing_equals/main.sol diff --git a/crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.solc b/crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.solc rename to crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol diff --git a/crates/uitest/tests/fixtures/solver/coverage_condition/main.solc b/crates/uitest/tests/fixtures/solver/coverage_condition/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/coverage_condition/main.solc rename to crates/uitest/tests/fixtures/solver/coverage_condition/main.sol diff --git a/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.solc b/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.solc rename to crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.solc b/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.solc b/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.solc b/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.solc b/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.solc b/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.solc b/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.solc b/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_no_instance/main.solc b/crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_no_instance/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.solc b/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol diff --git a/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.solc b/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.solc rename to crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol diff --git a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.solc b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.solc rename to crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol diff --git a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.solc b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.solc rename to crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.sol diff --git a/crates/uitest/tests/fixtures/solver/instance_extra_method/main.solc b/crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/instance_extra_method/main.solc rename to crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol diff --git a/crates/uitest/tests/fixtures/solver/invalid_default_instance/main.solc b/crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/invalid_default_instance/main.solc rename to crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol diff --git a/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.solc b/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.solc rename to crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol diff --git a/crates/uitest/tests/fixtures/solver/method_extra_forall/main.solc b/crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/method_extra_forall/main.solc rename to crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol diff --git a/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.solc b/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.solc rename to crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol diff --git a/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.solc b/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.solc rename to crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol diff --git a/crates/uitest/tests/fixtures/solver/patterson_condition/main.solc b/crates/uitest/tests/fixtures/solver/patterson_condition/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/patterson_condition/main.solc rename to crates/uitest/tests/fixtures/solver/patterson_condition/main.sol diff --git a/crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.solc b/crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.solc rename to crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.solc b/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.solc rename to crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.solc b/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.solc rename to crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.solc b/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.solc rename to crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.solc b/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.solc rename to crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.solc b/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.solc rename to crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.solc b/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.solc rename to crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/free_type_variable/main.solc b/crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/free_type_variable/main.solc rename to crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/integer_erasure/main.solc b/crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/integer_erasure/main.solc rename to crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.solc b/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.solc rename to crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol diff --git a/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.solc b/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.solc rename to crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.solc b/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.solc b/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.solc b/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.solc b/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.solc b/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.solc b/crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.solc b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.solc rename to crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.solc b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.solc rename to crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.sol diff --git a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.solc b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.solc rename to crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.sol diff --git a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.solc b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.solc rename to crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.solc b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.solc rename to crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.sol diff --git a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.solc b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.solc rename to crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.solc b/crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.solc rename to crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.solc b/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.solc rename to crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.solc b/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.solc rename to crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.solc b/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.solc rename to crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.solc b/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.solc rename to crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.solc b/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.solc rename to crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.solc b/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.solc rename to crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.solc b/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.solc rename to crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.solc rename to crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.solc b/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.solc rename to crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.solc b/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.solc rename to crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.solc b/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.solc rename to crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.solc b/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.solc rename to crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol From a31755c727033e8695b4c1a38f55524a4d994fa3 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 028/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures extensions Co-authored-by: Codex --- .../fixtures/typeck/mutual_recursive_data/{main.solc => main.sol} | 0 .../nested_constructor_nonexhaustive/{main.solc => main.sol} | 0 .../typeck/nested_constructor_unreachable/{main.solc => main.sol} | 0 .../typeck/nonexhaustive_contract/{main.solc => main.sol} | 0 .../fixtures/typeck/nonexhaustive_free_fn/{main.solc => main.sol} | 0 .../tests/fixtures/typeck/nonfinal_return/{main.solc => main.sol} | 0 .../typeck/nullary_type_applied_let/{main.solc => main.sol} | 0 .../typeck/nullary_type_applied_signature/{main.solc => main.sol} | 0 .../tests/fixtures/typeck/occurs_check/{main.solc => main.sol} | 0 .../ok_uint256_binops_class_methods/{main.solc => main.sol} | 0 .../fixtures/typeck/return_bool_mismatch/{main.solc => main.sol} | 0 .../shorthand_constructor_ambiguous/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../shorthand_constructor_no_context/{main.solc => main.sol} | 0 .../typeck/shorthand_constructor_no_match/{main.solc => main.sol} | 0 .../{main.solc => main.sol} | 0 .../storage_mapping_compound_add_bool/{main.solc => main.sol} | 0 .../storage_mapping_compound_sub_bool/{main.solc => main.sol} | 0 .../typeck/type_alias_expansion_limit/{main.solc => main.sol} | 0 .../typeck/type_annotation_kind_mismatch/{main.solc => main.sol} | 0 .../typeck/unary_type_unapplied_signature/{main.solc => main.sol} | 0 .../tests/fixtures/typeck/unknown_field/{main.solc => main.sol} | 0 .../fixtures/typeck/unreachable_match_arm/{main.solc => main.sol} | 0 .../visible_manual_std_abi_instances/{main.solc => main.sol} | 0 .../typeck/whole_mapping_private_full/{main.solc => main.sol} | 0 .../typeck/word_literals_nonexhaustive/{main.solc => main.sol} | 0 .../typeck/yul_multi_return_arity/{main.solc => main.sol} | 0 .../typeck/yul_non_word_sail_variable/{main.solc => main.sol} | 0 .../fixtures/typeck/yul_opcode_errors/{main.solc => main.sol} | 0 29 files changed, 0 insertions(+), 0 deletions(-) rename crates/uitest/tests/fixtures/typeck/mutual_recursive_data/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nonfinal_return/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/occurs_check/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/return_bool_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/unknown_field/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/unreachable_match_arm/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/{main.solc => main.sol} (100%) rename crates/uitest/tests/fixtures/typeck/yul_opcode_errors/{main.solc => main.sol} (100%) diff --git a/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.solc b/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.solc rename to crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.solc b/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.solc rename to crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.solc b/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.solc rename to crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.solc b/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.solc rename to crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.solc b/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.solc rename to crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nonfinal_return/main.solc b/crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nonfinal_return/main.solc rename to crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.solc b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.solc rename to crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.solc b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.solc rename to crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/occurs_check/main.solc b/crates/uitest/tests/fixtures/typeck/occurs_check/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/occurs_check/main.solc rename to crates/uitest/tests/fixtures/typeck/occurs_check/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.solc b/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.solc rename to crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.solc b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.solc rename to crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.solc b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.solc rename to crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.solc b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.solc rename to crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.solc b/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.solc rename to crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.solc b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.solc rename to crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.solc b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.solc rename to crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.solc b/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.solc rename to crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.solc b/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.solc rename to crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.solc b/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.solc rename to crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/unknown_field/main.solc b/crates/uitest/tests/fixtures/typeck/unknown_field/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/unknown_field/main.solc rename to crates/uitest/tests/fixtures/typeck/unknown_field/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.solc b/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.solc rename to crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.solc b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.solc rename to crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.solc b/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.solc rename to crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.solc b/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.solc rename to crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.solc b/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.solc rename to crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.solc b/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.solc rename to crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol diff --git a/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.solc b/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol similarity index 100% rename from crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.solc rename to crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol From 4d947a3a85fc60a349cb94da5475df9d6cc0c355 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 029/110] Switch the compiler and fixtures to canonical syntax: yul fixtures extensions Co-authored-by: Codex --- .../tests/fixtures/data_type_storage_full/{main.solc => main.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/yul/tests/fixtures/data_type_storage_full/{main.solc => main.sol} (100%) diff --git a/crates/yul/tests/fixtures/data_type_storage_full/main.solc b/crates/yul/tests/fixtures/data_type_storage_full/main.sol similarity index 100% rename from crates/yul/tests/fixtures/data_type_storage_full/main.solc rename to crates/yul/tests/fixtures/data_type_storage_full/main.sol From 07924315bc06a95df5a9fba2c4f7f00de794057c Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 030/110] Switch the compiler and fixtures to canonical syntax: compiler Co-authored-by: Codex --- crates/compiler/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs index f18a2765..02e9768c 100644 --- a/crates/compiler/src/lib.rs +++ b/crates/compiler/src/lib.rs @@ -415,7 +415,7 @@ mod tests { #[test] fn frontend_diagnostics_are_lowered() { let mut db = TestDb::default(); - let key = load_main_source(&mut db, "function main() -> word { return true; }\n"); + let key = load_main_source(&mut db, "function main() returns (word) { return true; }\n"); let entry = module_id_from_key(&db, &key); let diagnostics = collect_frontend_diagnostics(&db, entry); @@ -432,7 +432,7 @@ mod tests { let mut db = TestDb::default(); let key = load_main_source( &mut db, - "contract Main { public function answer() -> word { return 42; } }\n", + "contract Main { function answer() public returns (word) { return 42; } }\n", ); let entry = module_id_from_key(&db, &key); @@ -449,7 +449,7 @@ mod tests { #[test] fn clean_source_builds_checked_hull() { let mut db = TestDb::default(); - let key = load_main_source(&mut db, "function main() -> word { return 42; }\n"); + let key = load_main_source(&mut db, "function main() returns (word) { return 42; }\n"); let entry = module_id_from_key(&db, &key); let file = db.module_file(entry).expect("entry source"); @@ -465,17 +465,17 @@ mod tests { let mut db = TestDb::default(); let entry_key = load_main_source( &mut db, - "import a; import b;\nfunction main() -> word { return 0; }\n", + "import a; import b;\nfunction main() returns (word) { return 0; }\n", ); insert_main_module( &mut db, "a", - "contract Token { public function main() -> word { return 1; } }\n", + "contract Token { function main() public returns (word) { return 1; } }\n", ); insert_main_module( &mut db, "b", - "contract Token { public function main() -> word { return 2; } }\n", + "contract Token { function main() public returns (word) { return 2; } }\n", ); set_main_module_paths(&mut db, &["main", "a", "b"]); let entry = module_id_from_key(&db, &entry_key); @@ -512,7 +512,7 @@ mod tests { library: LibraryId::Main, logical_path: vec![name.to_owned()], }; - let url = Url::parse(&format!("memory:///main/{name}.solc")).expect("module URL"); + let url = Url::parse(&format!("memory:///main/{name}.sol")).expect("module URL"); let file = SourceFile::new(db, url, Some(source.to_owned())); db.insert_module_file(key, file); } @@ -521,7 +521,7 @@ mod tests { let root = PathBuf::from("/main"); let existing_files = stems .iter() - .map(|stem| root.join(format!("{stem}.solc"))) + .map(|stem| root.join(format!("{stem}.sol"))) .collect::>(); let sibling_stems = BTreeMap::from([(root, stems.iter().map(|stem| (*stem).to_owned()).collect())]); From 0c0d756cf556f7d21b48c1a6745f0a52ac118463 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 031/110] Switch the compiler and fixtures to canonical syntax: driver Co-authored-by: Codex --- crates/driver/src/args.rs | 10 +- crates/driver/src/paths.rs | 6 +- crates/driver/src/standard_json.rs | 12 +- crates/driver/tests/standard_json_cli.rs | 12 +- crates/driver/tests/typeck_cli.rs | 213 ++++++++++++++--------- 5 files changed, 155 insertions(+), 98 deletions(-) diff --git a/crates/driver/src/args.rs b/crates/driver/src/args.rs index 5174eb52..2a3d76f3 100644 --- a/crates/driver/src/args.rs +++ b/crates/driver/src/args.rs @@ -391,6 +391,12 @@ pub(crate) fn parse_args(args: Vec) -> Result { let Some(input) = input else { return Err("missing input file".to_owned()); }; + if input.extension() != Some(OsStr::new("sol")) { + return Err(format!( + "input source file `{}` must use the `.sol` extension", + input.display() + )); + } if emit_yul_object.is_some() && emit_yul.is_none() { return Err("--emit-yul-object requires --emit-yul".to_owned()); } @@ -600,7 +606,7 @@ pub(crate) fn default_diagnostic_width() -> usize { } pub(crate) fn usage_text(program: &str) -> String { - format!("usage: {program} [OPTIONS] \ntry `{program} --help` for more information") + format!("usage: {program} [OPTIONS] \ntry `{program} --help` for more information") } pub(crate) fn help_text(program: &str) -> String { @@ -608,7 +614,7 @@ pub(crate) fn help_text(program: &str) -> String { "\ Solcore Rust driver -Usage: {program} [OPTIONS] [] +Usage: {program} [OPTIONS] [] Options: -f, --file FILE Input source file (alternative to positional input) diff --git a/crates/driver/src/paths.rs b/crates/driver/src/paths.rs index cfb97053..ef2f1554 100644 --- a/crates/driver/src/paths.rs +++ b/crates/driver/src/paths.rs @@ -117,7 +117,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -180,8 +180,8 @@ mod tests { #[test] fn lexical_normalization_removes_dot_and_parent_components() { - let normalized = normalize_lexically(Path::new("alpha/./beta/../gamma/main.solc")); - assert_eq!(normalized, PathBuf::from("alpha/gamma/main.solc")); + let normalized = normalize_lexically(Path::new("alpha/./beta/../gamma/main.sol")); + assert_eq!(normalized, PathBuf::from("alpha/gamma/main.sol")); } #[test] diff --git a/crates/driver/src/standard_json.rs b/crates/driver/src/standard_json.rs index 25069b1f..d57b7d99 100644 --- a/crates/driver/src/standard_json.rs +++ b/crates/driver/src/standard_json.rs @@ -14,7 +14,7 @@ use std::{ use serde_json::{Map, Value, json}; use vfs::{Diagnostic, DiagnosticSeverity, Workspace, WorkspaceFileChange}; -const DEFAULT_ENTRYPOINT: &str = "main.solc"; +const DEFAULT_ENTRYPOINT: &str = "main.sol"; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Stage { @@ -154,10 +154,10 @@ fn validate_source_name(name: &str) -> Result<(), String> { || name.contains('\\') || name.contains(':') || !has_only_normal_components - || path.extension().and_then(|extension| extension.to_str()) != Some("solc") + || path.extension().and_then(|extension| extension.to_str()) != Some("sol") { return Err(format!( - "source name `{name}` must be a relative, traversal-free `.solc` path" + "source name `{name}` must be a relative, traversal-free `.sol` path" )); } Ok(()) @@ -295,7 +295,7 @@ mod tests { #[test] fn rejects_source_paths_that_escape_the_virtual_workspace() { - for source_name in ["../main.solc", "/main.solc", "dir\\main.solc", "main.sol"] { + for source_name in ["../main.sol", "/main.sol", "dir\\main.sol", "main.solc"] { assert!(validate_source_name(source_name).is_err(), "{source_name}"); } } @@ -304,11 +304,11 @@ mod tests { fn defaults_to_main_entrypoint_and_hull_stage() { let request = parse_request(json!({ "language": "Solcore", - "sources": {"main.solc": {"content": "function main() -> word { return 0; }"}}, + "sources": {"main.sol": {"content": "function main() returns (word) { return 0; }"}}, })) .expect("valid request"); - assert_eq!(request.entrypoint, "main.solc"); + assert_eq!(request.entrypoint, "main.sol"); assert_eq!(request.stage, Stage::Hull); } } diff --git a/crates/driver/tests/standard_json_cli.rs b/crates/driver/tests/standard_json_cli.rs index 255ff4e6..fb2f9495 100644 --- a/crates/driver/tests/standard_json_cli.rs +++ b/crates/driver/tests/standard_json_cli.rs @@ -53,9 +53,9 @@ fn standard_json_compiles_checked_hull_without_polluting_stdout() { let output = run_standard_json(json!({ "language": "Solcore", "sources": { - "main.solc": {"content": "function id(x: word) -> word { return x; }\n"} + "main.sol": {"content": "function id(x: word) returns (word) { return x; }\n"} }, - "settings": {"solcore": {"entrypoint": "main.solc", "stage": "hull"}}, + "settings": {"solcore": {"entrypoint": "main.sol", "stage": "hull"}}, })); let response = response(&output); @@ -68,10 +68,10 @@ fn standard_json_loads_multiple_virtual_source_files() { let output = run_standard_json(json!({ "language": "Solcore", "sources": { - "main.solc": {"content": "import helper.{id};\nfunction main() -> word { return id(0); }\n"}, - "helper.solc": {"content": "export { id };\nfunction id(x: word) -> word { return x; }\n"}, + "main.sol": {"content": "import {id} from helper;\nfunction main() returns (word) { return id(0); }\n"}, + "helper.sol": {"content": "export { id };\nfunction id(x: word) returns (word) { return x; }\n"}, }, - "settings": {"solcore": {"entrypoint": "main.solc", "stage": "frontend"}}, + "settings": {"solcore": {"entrypoint": "main.sol", "stage": "frontend"}}, })); let response = response(&output); @@ -82,7 +82,7 @@ fn standard_json_loads_multiple_virtual_source_files() { fn standard_json_reports_request_errors_in_json() { let output = run_standard_json(json!({ "language": "Solcore", - "sources": {"../escape.solc": {"content": "function main() -> word { return 0; }"}}, + "sources": {"../escape.sol": {"content": "function main() returns (word) { return 0; }"}}, })); let response = response(&output); diff --git a/crates/driver/tests/typeck_cli.rs b/crates/driver/tests/typeck_cli.rs index 09acefab..a3f26d5e 100644 --- a/crates/driver/tests/typeck_cli.rs +++ b/crates/driver/tests/typeck_cli.rs @@ -64,15 +64,62 @@ fn cli_reports_usage_errors_with_exit_code_2() { assert!(stderr.contains("--help"), "{stderr}"); } +#[test] +fn cli_accepts_sol_input_and_rejects_other_source_extensions() { + let dir = temp_dir("source-extension"); + fs::create_dir_all(&dir).expect("create temp dir"); + let source = "function main() returns (word) { return 0; }\n"; + let sol = dir.join("main.sol"); + let solc = dir.join("main.solc"); + let txt = dir.join("main.txt"); + for input in [&sol, &solc, &txt] { + fs::write(input, source).expect("write source"); + } + + let accepted = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) + .arg(&sol) + .output() + .expect("run driver with .sol input"); + assert!( + accepted.status.success(), + ".sol input failed\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&accepted.stdout), + String::from_utf8_lossy(&accepted.stderr) + ); + + for (option, input) in [(None, &solc), (Some("--file"), &txt)] { + let mut command = Command::new(env!("CARGO_BIN_EXE_solcore-driver")); + if let Some(option) = option { + command.arg(option); + } + let rejected = command + .arg(input) + .output() + .expect("run driver with invalid source extension"); + assert_eq!(rejected.status.code(), Some(2)); + let stderr = String::from_utf8_lossy(&rejected.stderr); + assert!( + stderr.contains("must use the `.sol` extension"), + "stderr:\n{stderr}" + ); + assert!( + stderr.contains(&input.display().to_string()), + "stderr:\n{stderr}" + ); + } + + let _ = fs::remove_dir_all(&dir); +} + #[test] fn cli_trace_reports_pipeline_summaries_without_verbose_intern_events() { let dir = temp_dir("trace-pipeline"); let output_dir = dir.join("artifacts"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, - "contract C { public function main() -> word { return 42; } }\n", + "contract C { function main() public returns (word) { return 42; } }\n", ) .expect("write source"); @@ -117,7 +164,10 @@ fn cli_trace_reports_pipeline_summaries_without_verbose_intern_events() { #[test] fn cli_prints_typeck_mismatch_diagnostic() { - let stderr = driver_stderr("mismatch", "function main() -> word { return true; }\n"); + let stderr = driver_stderr( + "mismatch", + "function main() returns (word) { return true; }\n", + ); assert!(stderr.contains("error[SC0201]"), "stderr:\n{stderr}"); assert_eq!( @@ -126,7 +176,7 @@ fn cli_prints_typeck_mismatch_diagnostic() { "expected one SC0201 diagnostic:\n{stderr}" ); assert!( - stderr.contains("1 | function main() -> word { return true; }"), + stderr.contains("1 | function main() returns (word) { return true; }"), "expected source line in stderr:\n{stderr}" ); assert!( @@ -139,8 +189,8 @@ fn cli_prints_typeck_mismatch_diagnostic() { fn cli_prints_short_diagnostics() { let dir = temp_dir("short-diagnostic"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); - fs::write(&input, "function main() -> word { return true; }\n").expect("write source"); + let input = dir.join("main.sol"); + fs::write(&input, "function main() returns (word) { return true; }\n").expect("write source"); let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) .arg("--color=never") @@ -154,7 +204,7 @@ fn cli_prints_short_diagnostics() { assert_eq!(output.status.code(), Some(1)); let stderr = String::from_utf8_lossy(&output.stderr); assert!( - stderr.contains("main.solc:1:34: error[SC0201]: type mismatch: expected word, found bool"), + stderr.contains("main.sol:1:41: error[SC0201]: type mismatch: expected word, found bool"), "stderr:\n{stderr}" ); assert!( @@ -172,7 +222,7 @@ fn cli_reports_non_utf8_input_path_without_panic() { fs::create_dir_all(&dir).expect("create temp dir"); let root = dir.clone(); let mut raw = dir.into_os_string().into_vec(); - raw.extend_from_slice(b"/bad-\xff.solc"); + raw.extend_from_slice(b"/bad-\xff.sol"); let input = OsString::from_vec(raw); let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) @@ -196,11 +246,11 @@ fn cli_reports_non_utf8_input_path_without_panic() { fn cli_reports_reachable_missing_external_lib_root() { let dir = temp_dir("missing-external-root"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); let missing = dir.join("missing-ext"); fs::write( &input, - "import @pkg.util;\nfunction main() -> word { return 0; }\n", + "import @pkg.util;\nfunction main() returns (word) { return 0; }\n", ) .expect("write source"); @@ -234,11 +284,11 @@ fn cli_reports_reachable_missing_external_lib_root() { fn cli_reports_unreadable_reachable_module_as_io_error() { let dir = temp_dir("invalid-utf8-module"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); - let dependency = dir.join("util.solc"); + let input = dir.join("main.sol"); + let dependency = dir.join("util.sol"); fs::write( &input, - "import util;\nfunction main() -> word { return 0; }\n", + "import util;\nfunction main() returns (word) { return 0; }\n", ) .expect("write source"); fs::write(&dependency, [0xff, 0xfe]).expect("write invalid UTF-8 dependency"); @@ -271,8 +321,8 @@ fn cli_reports_unreadable_reachable_module_as_io_error() { fn cli_accepts_warning_policy_and_diagnostic_rendering_flags() { let dir = temp_dir("warning-policy"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); - fs::write(&input, "function main() -> word { return 0; }\n").expect("write source"); + let input = dir.join("main.sol"); + fs::write(&input, "function main() returns (word) { return 0; }\n").expect("write source"); for policy in ["default", "always", "never", "deny"] { let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) @@ -322,15 +372,16 @@ fn cli_accepts_warning_policy_and_diagnostic_rendering_flags() { fn cli_warning_policy_default_prints_warnings() { let dir = temp_dir("warning-policy-output"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, - r#"data Flag = Off | On; + r#"enum Flag {Off , On} -function pick(x : Flag) -> word { - match x { - | _ => return 0; - | Flag.Off => return 1; +function pick(x : Flag) returns (word) { + match (x) { + case Flag.Off { return 0; } + case Flag.Off { return 1; } + default { return 0; } } } "#, @@ -389,15 +440,15 @@ function pick(x : Flag) -> word { fn cli_prints_solver_diagnostic_with_obligation_span() { let stderr = driver_stderr( "solver", - r#"forall a . class a:C {} -forall a . a:C => function use(x : a) -> word { return 0; } -function main(x : word) -> word { return use(x); } + r#"trait C {} +function use(x : a) returns (word) where a: C { return 0; } +function main(x : word) returns (word) { return use(x); } "#, ); assert!(stderr.contains("error[SC0207]"), "stderr:\n{stderr}"); assert!( - stderr.contains("3 | function main(x : word) -> word { return use(x); }"), + stderr.contains("3 | function main(x : word) returns (word) { return use(x); }"), "expected source line in stderr:\n{stderr}" ); assert!( @@ -407,23 +458,23 @@ function main(x : word) -> word { return use(x); } } #[test] -fn cli_prints_instance_soundness_diagnostic_with_head_span() { +fn cli_prints_impl_soundness_diagnostic_with_head_span() { let stderr = driver_stderr( - "instance-soundness", - r#"data Box(a) = Box(word); -forall a b . class a:MyClass(b) {} -forall a b . instance Box(a):MyClass(b) {} + "impl-soundness", + r#"enum Box {Box(word)} +trait MyClass {} +impl MyClass,b> {} "#, ); assert!(stderr.contains("error[SC0212]"), "stderr:\n{stderr}"); assert!( - stderr.contains("3 | forall a b . instance Box(a):MyClass(b) {}"), - "expected instance source line in stderr:\n{stderr}" + stderr.contains("3 | impl MyClass,b> {}"), + "expected impl source line in stderr:\n{stderr}" ); assert!( - stderr.contains("^^^^^^^^^^^^^^^^^ instance head does not determine these variables"), - "expected instance head caret label in stderr:\n{stderr}" + stderr.contains("^^^^^^^^^^^^^^^^^ impl head does not determine these variables"), + "expected impl head caret label in stderr:\n{stderr}" ); } @@ -433,14 +484,14 @@ fn cli_uses_root_override_for_main_library() { let nested = dir.join("nested"); fs::create_dir_all(&nested).expect("create temp dirs"); fs::write( - dir.join("lib.solc"), - "export { value };\nfunction value() -> word { return 5; }\n", + dir.join("lib.sol"), + "export { value };\nfunction value() returns (word) { return 5; }\n", ) .expect("write lib"); - let input = nested.join("main.solc"); + let input = nested.join("main.sol"); fs::write( &input, - "import lib.lib;\nfunction main() -> word { return lib.value(); }\n", + "import lib.lib;\nfunction main() returns (word) { return lib.value(); }\n", ) .expect("write source"); @@ -469,7 +520,7 @@ fn cli_uses_explicit_std_root() { fs::create_dir_all(&std_root).expect("create std dir"); fs::create_dir_all(&input_dir).expect("create input dir"); write_fake_std(&std_root); - let input = input_dir.join("main.solc"); + let input = input_dir.join("main.sol"); write_fake_std_importer(&input); let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) @@ -494,9 +545,9 @@ fn cli_uses_explicit_std_root() { fn cli_rejects_missing_std_root_with_actionable_configuration_help() { let dir = temp_dir("missing-std-root"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); let missing = dir.join("missing-std"); - fs::write(&input, "function main() -> word { return 0; }\n").expect("write source"); + fs::write(&input, "function main() returns (word) { return 0; }\n").expect("write source"); let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) .arg("--std-root") @@ -529,17 +580,17 @@ fn cli_normalizes_parent_components_before_deriving_the_entry_module() { let src = dir.join("src"); fs::create_dir_all(&src).expect("create source directory"); fs::write( - src.join("util.solc"), - "export { value }; function value() -> word { return 9; }\n", + src.join("util.sol"), + "export { value }; function value() returns (word) { return 9; }\n", ) .expect("write utility module"); - let input = src.join("main.solc"); + let input = src.join("main.sol"); fs::write( &input, - "import util; function main() -> word { return util.value(); }\n", + "import util; function main() returns (word) { return util.value(); }\n", ) .expect("write source"); - let spelled_with_parent = src.join("..").join("src").join("main.solc"); + let spelled_with_parent = src.join("..").join("src").join("main.sol"); let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) .arg("--root") @@ -566,7 +617,7 @@ fn copied_binary_resolves_std_next_to_current_exe() { let copied_driver = dir.join("solcore-driver"); fs::copy(env!("CARGO_BIN_EXE_solcore-driver"), &copied_driver).expect("copy driver"); write_fake_std(&dir.join("std")); - let input = input_dir.join("main.solc"); + let input = input_dir.join("main.sol"); write_fake_std_importer(&input); let output = Command::new(&copied_driver) @@ -589,14 +640,14 @@ fn copied_binary_resolves_std_next_to_current_exe() { fn cli_emits_yul_to_stdout_and_hull_to_file() { let dir = temp_dir("emit-backends"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); let output_dir = dir.join("artifacts"); let hull_output = output_dir.join("main.hull"); fs::write( &input, r#" contract C { - public function main() -> word { + function main() public returns (word) { return 42; } } @@ -648,10 +699,10 @@ contract C { fn cli_emits_sonatina_to_stdout_and_output_dir() { let dir = temp_dir("emit-sonatina"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); let output_dir = dir.join("artifacts"); let sonatina_output = output_dir.join("main.sonatina"); - fs::write(&input, "function main() -> word { return 42; }\n").expect("write source"); + fs::write(&input, "function main() returns (word) { return 42; }\n").expect("write source"); let stdout_output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) .arg("--emit-sonatina") @@ -692,8 +743,8 @@ fn cli_emits_sonatina_to_stdout_and_output_dir() { fn cli_rejects_multiple_backend_stdout_targets() { let dir = temp_dir("multiple-backend-stdout"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); - fs::write(&input, "function main() -> word { return 42; }\n").expect("write source"); + let input = dir.join("main.sol"); + fs::write(&input, "function main() returns (word) { return 42; }\n").expect("write source"); for (first, second) in [ ("--emit-hull", "--emit-yul"), @@ -727,14 +778,14 @@ fn cli_rejects_multiple_backend_stdout_targets() { fn cli_emits_abi_to_output_dir() { let dir = temp_dir("emit-abi"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); let output_dir = dir.join("abi"); let abi_output = output_dir.join("C.abi"); fs::write( &input, r#" contract C { - public function main() -> word { + function main() public returns (word) { return 42; } } @@ -770,14 +821,14 @@ fn cli_abi_ignores_reachable_external_library_contracts() { let output_dir = dir.join("abi"); fs::create_dir_all(&external).expect("create external root"); fs::write( - external.join("token.solc"), - "contract ExternalToken { public function main() -> word { return 7; } }\n", + external.join("token.sol"), + "contract ExternalToken { function main() public returns (word) { return 7; } }\n", ) .expect("write external module"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, - "import @pkg.token; contract Local { public function main() -> word { return 1; } }\n", + "import @pkg.token; contract Local { function main() public returns (word) { return 1; } }\n", ) .expect("write main module"); @@ -809,19 +860,19 @@ fn cli_abi_rejects_colliding_local_contract_filenames_before_writing() { let output_dir = dir.join("abi"); fs::create_dir_all(&dir).expect("create temp dir"); fs::write( - dir.join("a.solc"), - "contract Token { public function main() -> word { return 1; } }\n", + dir.join("a.sol"), + "contract Token { function main() public returns (word) { return 1; } }\n", ) .expect("write first module"); fs::write( - dir.join("b.solc"), - "contract Token { public function main() -> word { return 2; } }\n", + dir.join("b.sol"), + "contract Token { function main() public returns (word) { return 2; } }\n", ) .expect("write second module"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, - "import a; import b; function main() -> word { return 0; }\n", + "import a; import b; function main() returns (word) { return 0; }\n", ) .expect("write main module"); @@ -851,13 +902,13 @@ fn cli_abi_rejects_colliding_local_contract_filenames_before_writing() { fn cli_renders_backend_diagnostics_with_stable_codes() { let dir = temp_dir("backend-diagnostic"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, r#" -import std.{string}; +import {string} from std; contract C { - public function main() -> string { + function main() public returns (string) { return "nope"; } } @@ -892,15 +943,15 @@ contract C { fn cli_partial_evaluation_fuel_is_configurable() { let dir = temp_dir("configurable-pe-fuel"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, r#" -import std.{*}; -function g2() -> word { return 1; } -function g1() -> word { return g2() + g2(); } -function g0() -> word { return g1() + g1(); } -contract C { function main() -> word { return g0(); } } +import * from std; +function g2() returns (word) { return 1; } +function g1() returns (word) { return g2() + g2(); } +function g0() returns (word) { return g1() + g1(); } +contract C { function main() returns (word) { return g0(); } } "#, ) .expect("write source"); @@ -949,16 +1000,16 @@ contract C { function main() -> word { return g0(); } } fn cli_emit_yul_requires_one_top_level_object_or_selection() { let dir = temp_dir("emit-yul-multi-object"); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write( &input, r#" contract A { - public function main() -> word { return 1; } + function main() public returns (word) { return 1; } } contract B { - public function main() -> word { return 2; } + function main() public returns (word) { return 2; } } "#, ) @@ -1005,7 +1056,7 @@ contract B { fn driver_stderr(label: &str, source: &str) -> String { let dir = temp_dir(label); fs::create_dir_all(&dir).expect("create temp dir"); - let input = dir.join("main.solc"); + let input = dir.join("main.sol"); fs::write(&input, source).expect("write source"); let output = Command::new(env!("CARGO_BIN_EXE_solcore-driver")) @@ -1022,8 +1073,8 @@ fn driver_stderr(label: &str, source: &str) -> String { fn write_fake_std(std_root: &Path) { fs::create_dir_all(std_root).expect("create fake std root"); fs::write( - std_root.join("std.solc"), - "export { solcoreTempStdValue };\nfunction solcoreTempStdValue() -> word { return 7; }\n", + std_root.join("std.sol"), + "export { solcoreTempStdValue };\nfunction solcoreTempStdValue() returns (word) { return 7; }\n", ) .expect("write fake std"); } @@ -1031,7 +1082,7 @@ fn write_fake_std(std_root: &Path) { fn write_fake_std_importer(path: &Path) { fs::write( path, - "import std;\nfunction main() -> word { return std.solcoreTempStdValue(); }\n", + "import std;\nfunction main() returns (word) { return std.solcoreTempStdValue(); }\n", ) .expect("write fake std importer"); } From 7d04a2c42733eb25d3e556275cca24a9da7ce477 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 032/110] Switch the compiler and fixtures to canonical syntax: fuzz Co-authored-by: Codex --- fuzz/corpus/backend/basic.sol | 2 +- fuzz/corpus/frontend/basic.sol | 2 +- fuzz/corpus/parser/basic.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fuzz/corpus/backend/basic.sol b/fuzz/corpus/backend/basic.sol index 50fb803b..12e4cfae 100644 --- a/fuzz/corpus/backend/basic.sol +++ b/fuzz/corpus/backend/basic.sol @@ -1 +1 @@ -function id(x: word) -> word { return x; } +function id(x: word) returns (word) { return x; } diff --git a/fuzz/corpus/frontend/basic.sol b/fuzz/corpus/frontend/basic.sol index d92b95a4..337b66d0 100644 --- a/fuzz/corpus/frontend/basic.sol +++ b/fuzz/corpus/frontend/basic.sol @@ -1 +1 @@ -function main() -> word { return 0; } +function main() returns (word) { return 0; } diff --git a/fuzz/corpus/parser/basic.sol b/fuzz/corpus/parser/basic.sol index 50fb803b..12e4cfae 100644 --- a/fuzz/corpus/parser/basic.sol +++ b/fuzz/corpus/parser/basic.sol @@ -1 +1 @@ -function id(x: word) -> word { return x; } +function id(x: word) returns (word) { return x; } From 88c4d4c3c4ad34fa2561151913d432beaf7ba123 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 033/110] Switch the compiler and fixtures to canonical syntax: hir Co-authored-by: Codex --- crates/hir/src/diag/code.rs | 4 +-- crates/hir/src/diag/tests.rs | 10 ++++---- crates/hir/src/lib.rs | 12 ++++----- crates/hir/src/nameres/diagnostic.rs | 4 +-- crates/hir/src/sema/ty.rs | 37 +++++++++++++--------------- 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/crates/hir/src/diag/code.rs b/crates/hir/src/diag/code.rs index da2a1f3b..0d1490ac 100644 --- a/crates/hir/src/diag/code.rs +++ b/crates/hir/src/diag/code.rs @@ -490,11 +490,11 @@ impl DiagnosticCode { ), DiagnosticCodeAlias::new( Self::TYPECK_INCOMPLETE_METHOD_SIGNATURE, - "SC0221 covers incomplete method signatures and invalid instance method signatures.", + "SC0221 covers incomplete method signatures and invalid impl method signatures.", ), DiagnosticCodeAlias::new( Self::TYPECK_CLASS_AS_TYPE, - "SC0229 covers class-as-type errors and generated dispatch type collisions.", + "SC0229 covers trait-as-type errors and generated dispatch type collisions.", ), DiagnosticCodeAlias::new( Self::TYPECK_NON_EXHAUSTIVE_MATCH, diff --git a/crates/hir/src/diag/tests.rs b/crates/hir/src/diag/tests.rs index 27336c50..c4f0320a 100644 --- a/crates/hir/src/diag/tests.rs +++ b/crates/hir/src/diag/tests.rs @@ -35,7 +35,7 @@ impl crate::Db for TestDb { } fn source_file(db: &TestDb, name: &str, content: Option<&str>) -> SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid url"); + let url = format!("memory:///{name}.sol").parse().expect("valid url"); SourceFile::new(db, url, content.map(ToOwned::to_owned)) } @@ -244,7 +244,7 @@ fn render_skips_contentless_def_labels_before_absolute_resolution() { #[test] fn render_decodes_file_urls_in_human_and_short_formats() { let db = TestDb::default(); - let file = file_source_file(&db, "/tmp/Solcore Project/日本語/main.solc", "missing\n"); + let file = file_source_file(&db, "/tmp/Solcore Project/日本語/main.sol", "missing\n"); let diagnostic = Diagnostic::error("undefined name") .with_primary_label_span(root_span(file, 0, 7), Some("not found")); @@ -252,7 +252,7 @@ fn render_decodes_file_urls_in_human_and_short_formats() { let short = diagnostic.render_short(&db); for rendered in [human, short] { - assert!(rendered.contains("/tmp/Solcore Project/日本語/main.solc")); + assert!(rendered.contains("/tmp/Solcore Project/日本語/main.sol")); assert!(!rendered.contains("%20")); assert!(!rendered.contains("%E6")); } @@ -261,7 +261,7 @@ fn render_decodes_file_urls_in_human_and_short_formats() { #[test] fn render_decodes_memory_urls_in_human_and_short_formats() { let db = TestDb::default(); - let url = url::Url::parse("memory:///Solcore%20Project/%E6%97%A5%E6%9C%AC%E8%AA%9E/main.solc") + let url = url::Url::parse("memory:///Solcore%20Project/%E6%97%A5%E6%9C%AC%E8%AA%9E/main.sol") .expect("valid memory URL"); let file = SourceFile::new(&db, url, Some("missing\n".to_owned())); let diagnostic = Diagnostic::error("undefined name") @@ -271,7 +271,7 @@ fn render_decodes_memory_urls_in_human_and_short_formats() { let short = diagnostic.render_short(&db); for rendered in [human, short] { - assert!(rendered.contains("/Solcore Project/日本語/main.solc")); + assert!(rendered.contains("/Solcore Project/日本語/main.sol")); assert!(!rendered.contains("memory:///")); assert!(!rendered.contains("%20")); assert!(!rendered.contains("%E6")); diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index dc644872..692e2a8a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -36,7 +36,7 @@ pub mod visit; /// Solcore's virtual VFS paths are platform-neutral even though they are /// represented as `file:` URLs. Native builds prefer /// [`url::Url::to_file_path`], then decode a local URL directly when the native -/// conversion rejects a drive-less URL such as `file:///main/main.solc` on +/// conversion rejects a drive-less URL such as `file:///main/main.sol` on /// Windows. The `url` crate cfg-gates its native conversion API off for /// `wasm32-unknown-unknown`, so wasm builds use the direct form as well. pub fn url_to_file_path(url: &url::Url) -> Option { @@ -93,10 +93,10 @@ mod url_to_file_path_tests { #[test] fn virtual_file_urls_are_platform_neutral() { for (url, expected) in [ - ("file:///main/main.solc", "/main/main.solc"), - ("file:///std/std.solc", "/std/std.solc"), - ("file:///ext/math/lib.solc", "/ext/math/lib.solc"), - ("file:///main/space%20name.solc", "/main/space name.solc"), + ("file:///main/main.sol", "/main/main.sol"), + ("file:///std/std.sol", "/std/std.sol"), + ("file:///ext/math/lib.sol", "/ext/math/lib.sol"), + ("file:///main/space%20name.sol", "/main/space name.sol"), ] { let url = url::Url::parse(url).expect("virtual file URL"); assert_eq!( @@ -109,7 +109,7 @@ mod url_to_file_path_tests { #[test] fn direct_file_url_decoding_rejects_a_remote_host() { - let remote = url::Url::parse("file://server/main/file.solc").expect("remote URL"); + let remote = url::Url::parse("file://server/main/file.sol").expect("remote URL"); assert!(decoded_local_file_url_path(&remote).is_none()); } diff --git a/crates/hir/src/nameres/diagnostic.rs b/crates/hir/src/nameres/diagnostic.rs index 54630baa..b3d82b4a 100644 --- a/crates/hir/src/nameres/diagnostic.rs +++ b/crates/hir/src/nameres/diagnostic.rs @@ -180,9 +180,9 @@ impl NameresDiagnostic { diagnostic } NameresDiagnostic::UndefinedClass { name, span } => { - Diagnostic::error(format!("undefined class: {name}")) + Diagnostic::error(format!("undefined trait: {name}")) .with_code(DiagnosticCode::NAMERES_UNDEFINED_CLASS) - .with_primary_label_span(span.clone(), Some("undefined class")) + .with_primary_label_span(span.clone(), Some("undefined trait")) } NameresDiagnostic::UnqualifiedConstructor { name, diff --git a/crates/hir/src/sema/ty.rs b/crates/hir/src/sema/ty.rs index aa48f368..882da7b8 100644 --- a/crates/hir/src/sema/ty.rs +++ b/crates/hir/src/sema/ty.rs @@ -358,7 +358,7 @@ impl<'db> Ty<'db> { name } else { format!( - "{name}({})", + "{name}<{}>", args.iter() .map(|arg| arg.display(db)) .collect::>() @@ -372,7 +372,7 @@ impl<'db> Ty<'db> { .map(|param| param.display(db)) .collect::>() .join(", "); - format!("({params}) -> {}", ret.display(db)) + format!("function({params}) returns ({})", ret.display(db)) } TyKind::Tuple(elems) => { if elems.is_empty() { @@ -388,7 +388,7 @@ impl<'db> Ty<'db> { ) } } - TyKind::Comptime(inner) => format!("comptime {}", inner.display(db)), + TyKind::Comptime(inner) => format!("comptime<{}>", inner.display(db)), } } } @@ -431,19 +431,15 @@ impl<'db> Pred<'db> { PredKind::InClass { class, main, args } => { let class = match class { ClassId::Builtin(class) => class.name().to_owned(), - ClassId::User(def) => { - format!( - "class:{}", - def.name(db) - .unwrap_or_else(|| format!("{:?}", def.kind(db))) - ) - } + ClassId::User(def) => def + .name(db) + .unwrap_or_else(|| format!("{:?}", def.kind(db))), }; if args.is_empty() { - format!("{}:{class}", main.display(db)) + format!("{}: {class}", main.display(db)) } else { format!( - "{}:{class}({})", + "{}: {class}<{}>", main.display(db), args.iter() .map(|arg| arg.display(db)) @@ -479,20 +475,21 @@ impl<'db> TyScheme<'db> { .iter() .map(|pred| pred.display(db)) .collect::>(); - let qualified = if preds.is_empty() { - body.ty(db).display(db) - } else { - format!("{} => {}", preds.join(", "), body.ty(db).display(db)) - }; - if self.binder_count(db) == 0 { - qualified + let ty = body.ty(db).display(db); + let mut displayed = if self.binder_count(db) == 0 { + ty } else { let vars = (0..self.binder_count(db)) .map(|_| "_".to_owned()) .collect::>() .join(", "); - format!("forall {vars}. {qualified}") + format!("<{vars}> {ty}") + }; + if !preds.is_empty() { + displayed.push_str(" where "); + displayed.push_str(&preds.join(", ")); } + displayed } } From ff27660895df154dc292931e216f3cd496cc3d17 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 034/110] Switch the compiler and fixtures to canonical syntax: hir ty Co-authored-by: Codex --- crates/hir-ty/src/contract/abi.rs | 14 +- crates/hir-ty/src/contract/dispatch.rs | 4 +- crates/hir-ty/src/display.rs | 56 ++- crates/hir-ty/src/infer/comptime.rs | 6 +- crates/hir-ty/src/infer/diagnostics.rs | 207 +++++---- crates/hir-ty/src/infer/expr.rs | 45 +- crates/hir-ty/src/infer/mod.rs | 2 +- crates/hir-ty/src/infer/obligations.rs | 6 +- crates/hir-ty/src/infer/tests.rs | 559 ++++++++++++------------- 9 files changed, 462 insertions(+), 437 deletions(-) diff --git a/crates/hir-ty/src/contract/abi.rs b/crates/hir-ty/src/contract/abi.rs index 19ede1e4..37b01334 100644 --- a/crates/hir-ty/src/contract/abi.rs +++ b/crates/hir-ty/src/contract/abi.rs @@ -255,7 +255,7 @@ pub(super) fn abi_outputs<'db>( span, "ABI output", &format!( - "{} (calldata(array(t)) is input-only; the target std has no ABIEncode evidence for it)", + "{} (calldata> is input-only; the target std has no ABIEncode evidence for it)", ty.display(db) ), )); @@ -372,7 +372,7 @@ fn abi_type_of<'db>( } /// Returns the element of the one externally supported calldata location: -/// `calldata(array(t))`. Both wrappers must be the canonical definitions from +/// `calldata>`. Both wrappers must be the canonical definitions from /// `std`; same-named user ADTs must not acquire ABI meaning by spelling alone. fn canonical_calldata_array_element<'db>( db: &'db dyn Db, @@ -394,7 +394,7 @@ fn canonical_calldata_array_element<'db>( } = inner.kind(db) else { return Err(format!( - "{} (only calldata(array(t)) has canonical external ABI evidence)", + "{} (only calldata> has canonical external ABI evidence)", inner.display(db) )); }; @@ -566,7 +566,7 @@ fn compiler_owned_generic_sig_string<'db>( } if !abi_evidence.has_derived_abi(user.def) { return Err(format!( - "{name} (compiler-owned ABIAttribs and ABIDecode evidence is not visible from the contract module; add an instance import of its defining module along the re-export path)" + "{name} (compiler-owned ABIAttribs and ABIDecode evidence is not visible from the contract module; import the module containing its defining impl along the re-export path)" )); } let rep = substitute_bound_tys(db, plan.rep, args); @@ -756,13 +756,13 @@ fn canonical_location_abi_name<'db>( } = inner.kind(db) else { return Err(format!( - "{} (only memory(string) and memory(bytes) have canonical ABI evidence)", + "{} (only memory and memory have canonical ABI evidence)", inner.display(db) )); }; if !inner_args.is_empty() { return Err(format!( - "{} (only memory(string) and memory(bytes) have canonical ABI evidence)", + "{} (only memory and memory have canonical ABI evidence)", inner.display(db) )); } @@ -775,7 +775,7 @@ fn canonical_location_abi_name<'db>( return Ok(Some(inner_name)); } Err(format!( - "{} (only memory(string) and memory(bytes) have canonical ABI evidence)", + "{} (only memory and memory have canonical ABI evidence)", inner.display(db) )) } diff --git a/crates/hir-ty/src/contract/dispatch.rs b/crates/hir-ty/src/contract/dispatch.rs index 746fb7d6..9ca0ac58 100644 --- a/crates/hir-ty/src/contract/dispatch.rs +++ b/crates/hir-ty/src/contract/dispatch.rs @@ -303,13 +303,13 @@ pub(crate) fn module_manual_generic_abi_diagnostics<'db>( Some("external ABI evidence must be compiler-owned and canonical"), ) .with_note(format!( - "instance `{}` can override canonical `{class_name}` behavior", + "impl `{}` can override canonical `{class_name}` behavior", instance .name(db) .unwrap_or_else(|| class_name.to_string()) )) .with_help( - "remove the visible manual ABI instance or keep this declaration out of the external ABI", + "remove the visible manual ABI impl or keep this declaration out of the external ABI", ), ); } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 0989f991..09176b7f 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -22,9 +22,15 @@ pub(crate) fn display_ty_source<'db>(db: &'db dyn Db, ty: Ty<'db>, names: &[Stri let name = display_ty_ctor_source(db, *ctor); if args.is_empty() { name + } else if name == "mapping" && args.len() == 2 { + format!( + "mapping({} => {})", + display_ty_source(db, args[0], names), + display_ty_source(db, args[1], names) + ) } else { format!( - "{name}({})", + "{name}<{}>", args.iter() .map(|arg| display_ty_source(db, *arg, names)) .collect::>() @@ -38,7 +44,10 @@ pub(crate) fn display_ty_source<'db>(db: &'db dyn Db, ty: Ty<'db>, names: &[Stri .map(|param| display_ty_source(db, *param, names)) .collect::>() .join(", "); - format!("({params}) -> {}", display_ty_source(db, *ret, names)) + format!( + "function({params}) returns ({})", + display_ty_source(db, *ret, names) + ) } TyKind::Tuple(elems) => { if elems.is_empty() { @@ -54,7 +63,9 @@ pub(crate) fn display_ty_source<'db>(db: &'db dyn Db, ty: Ty<'db>, names: &[Stri ) } } - TyKind::Comptime(inner) => format!("comptime {}", display_ty_source(db, *inner, names)), + TyKind::Comptime(inner) => { + format!("comptime<{}>", display_ty_source(db, *inner, names)) + } } } @@ -87,14 +98,14 @@ pub(crate) fn display_pred_source<'db>( let main = display_ty_source(db, *main, names); let class = display_class_source(db, *class); if args.is_empty() { - format!("{main} : {class}") + format!("{main}: {class}") } else { let args = args .iter() .map(|arg| display_ty_source(db, *arg, names)) .collect::>() .join(", "); - format!("{main} : {class}({args})") + format!("{main}: {class}<{args}>") } } PredKind::Eq { lhs, rhs } => format!( @@ -118,23 +129,32 @@ pub(crate) fn display_type_ref_source<'db>(db: &'db dyn HirDb, ty: TypeRef<'db>) out.push_str(&ident_text(db, qualifier)); out.push('.'); } - out.push_str(&ident_text(db, name)); + let name_text = ident_text(db, name); + out.push_str(&name_text); if !args.atom().is_empty() { - out.push('('); - out.push_str( - &args - .atom() - .iter() - .map(|arg| display_type_ref_source(db, *arg)) - .collect::>() - .join(", "), - ); - out.push(')'); + if name_text == "mapping" && args.atom().len() == 2 { + out.push('('); + out.push_str(&display_type_ref_source(db, args.atom()[0])); + out.push_str(" => "); + out.push_str(&display_type_ref_source(db, args.atom()[1])); + out.push(')'); + } else { + out.push('<'); + out.push_str( + &args + .atom() + .iter() + .map(|arg| display_type_ref_source(db, *arg)) + .collect::>() + .join(", "), + ); + out.push('>'); + } } out } TypeRefKind::Fn { params, ret } => format!( - "({}) -> {}", + "function({}) returns ({})", params .atom() .iter() @@ -144,7 +164,7 @@ pub(crate) fn display_type_ref_source<'db>(db: &'db dyn HirDb, ty: TypeRef<'db>) display_type_ref_source(db, *ret) ), TypeRefKind::Comptime { inner, .. } => { - format!("comptime {}", display_type_ref_source(db, *inner)) + format!("comptime<{}>", display_type_ref_source(db, *inner)) } TypeRefKind::Tuple { elems } => { format!( diff --git a/crates/hir-ty/src/infer/comptime.rs b/crates/hir-ty/src/infer/comptime.rs index 01fa5046..7c83b4c5 100644 --- a/crates/hir-ty/src/infer/comptime.rs +++ b/crates/hir-ty/src/infer/comptime.rs @@ -695,7 +695,7 @@ impl<'db> ComptimeChecker<'db> { let scheme = class_method_scheme_for_entry(self.db, self.entry_module, class, name.to_owned())?; let mut sig = callable_sig_from_semantic_scheme(self.db, method, scheme)?; - let class_name = class.name(self.db).unwrap_or_else(|| "class".to_owned()); + let class_name = class.name(self.db).unwrap_or_else(|| "trait".to_owned()); sig.name = format!("{class_name}.{name}"); Some(sig) } @@ -1019,10 +1019,6 @@ impl<'db> TypeckDiagnosticCollector<'db> { class: ClassDef<'db>, inherited_type_vars: &[hir_nameres::TypeVarBinding<'db>], ) { - if let Some(diagnostic) = implicit_class_head_binder_diagnostic(self.db, class) { - self.diagnostics - .push(AnyDiagnostic::Typeck(diagnostic.lower())); - } let mut type_vars = inherited_type_vars.to_vec(); type_vars.extend(type_var_bindings( class.def_id_value(self.db), diff --git a/crates/hir-ty/src/infer/diagnostics.rs b/crates/hir-ty/src/infer/diagnostics.rs index 62295364..90247717 100644 --- a/crates/hir-ty/src/infer/diagnostics.rs +++ b/crates/hir-ty/src/infer/diagnostics.rs @@ -162,14 +162,14 @@ pub enum TypeckDiagnostic { /// Span of the prior/generated definition source, when available. previous: Option, }, - /// `SC0207`: a class constraint could not be solved. + /// `SC0207`: a trait constraint could not be solved. UnsatisfiedConstraint { /// Source span for the obligation that could not be solved. span: LabelSpan, /// Predicate snapshot. pred: String, }, - /// `SC0208`: more than one non-default instance solved a class constraint. + /// `SC0208`: more than one non-default impl solved a trait constraint. AmbiguousConstraint { /// Source span for the ambiguous obligation. span: LabelSpan, @@ -496,7 +496,7 @@ impl TypeckDiagnostic { .with_code(DiagnosticCode::TYPECK_AMBIGUOUS_INFERENCE_OR_TYPE_CONSTRUCTOR_ARITY) .with_primary_label_span(span.clone(), Some("ambiguous inferred type")) .with_note(scheme.clone()) - .with_help("add a type annotation or a matching instance to fix the ambiguous type variable") + .with_help("add a type annotation or a matching impl to fix the ambiguous type variable") } TypeckDiagnostic::TypeConstructorArity { span, @@ -586,7 +586,7 @@ impl TypeckDiagnostic { } => { let subject = match namespace { ValueNamespace::Type => "type name", - ValueNamespace::Class => "class name", + ValueNamespace::Class => "trait name", ValueNamespace::Module => "module", ValueNamespace::TypeVariable => "type variable", }; @@ -600,9 +600,9 @@ impl TypeckDiagnostic { .with_help("use a constructor or value binding here, not a namespace name") } TypeckDiagnostic::ClassAsType { span, class } => { - Diagnostic::error(format!("class name used as type: `{class}`")) + Diagnostic::error(format!("trait name used as type: `{class}`")) .with_code(DiagnosticCode::TYPECK_CLASS_AS_TYPE) - .with_primary_label_span(span.clone(), Some("class is not a type")) + .with_primary_label_span(span.clone(), Some("trait is not a type")) } TypeckDiagnostic::DuplicateType { span, @@ -618,16 +618,16 @@ impl TypeckDiagnostic { Some("existing definition"), ) } else { - diagnostic.with_note(format!("existing definition: data {name}")) + diagnostic.with_note(format!("existing definition: enum {name}")) }; diagnostic.with_note("rename or remove the duplicate type definition") } TypeckDiagnostic::UnsatisfiedConstraint { span, pred } => { - Diagnostic::error(format!("cannot satisfy class constraint: {pred}")) + Diagnostic::error(format!("cannot satisfy trait constraint: {pred}")) .with_code(DiagnosticCode::TYPECK_UNSATISFIED_CONSTRAINT) .with_primary_label_span(span.clone(), Some("constraint originates here")) - .with_note(format!("no visible instance matches `{pred}`")) - .with_help("add a matching instance or strengthen the surrounding type context") + .with_note(format!("no visible impl matches `{pred}`")) + .with_help("add a matching impl or strengthen the surrounding type context") } TypeckDiagnostic::AmbiguousConstraint { span, @@ -635,22 +635,22 @@ impl TypeckDiagnostic { candidates, } => { let mut diagnostic = Diagnostic::error(format!( - "ambiguous class constraint: {pred}" + "ambiguous trait constraint: {pred}" )) .with_code(DiagnosticCode::TYPECK_AMBIGUOUS_CONSTRAINT) .with_primary_label_span(span.clone(), Some("ambiguous constraint here")) - .with_help("make the type more specific or remove overlapping instances"); + .with_help("make the type more specific or remove overlapping impls"); for candidate in candidates { diagnostic = diagnostic.with_note(candidate.clone()); } diagnostic } TypeckDiagnostic::SolverFuelExhausted { span, pred } => Diagnostic::error(format!( - "cannot solve class constraint `{pred}`: solver exceeded its iteration bound" + "cannot solve trait constraint `{pred}`: solver exceeded its iteration bound" )) .with_code(DiagnosticCode::TYPECK_SOLVER_FUEL_EXHAUSTED) .with_primary_label_span(span.clone(), Some("constraint originates here")) - .with_help("simplify the instance chain or add a more direct instance"), + .with_help("simplify the impl chain or add a more direct impl"), TypeckDiagnostic::NonFinalReturn { span } => { Diagnostic::error("illegal return statement") .with_code(DiagnosticCode::TYPECK_NON_FINAL_RETURN_OR_INVALID_CONSTRUCTOR_PATTERN) @@ -668,22 +668,22 @@ impl TypeckDiagnostic { main, undetermined, } => Diagnostic::error(format!( - "Coverage condition fails for class:\n{class}\n- the type:\n{main}\ndoes not determine:\n{}", + "Coverage condition fails for trait:\n{class}\n- the type:\n{main}\ndoes not determine:\n{}", undetermined.join(", ") )) .with_code(DiagnosticCode::TYPECK_COVERAGE_CONDITION) - .with_primary_label_span(span.clone(), Some("instance head does not determine these variables")), + .with_primary_label_span(span.clone(), Some("impl head does not determine these variables")), TypeckDiagnostic::PattersonCondition { span, head } => Diagnostic::error(format!( - "instance `{head}` does not satisfy the Patterson conditions" + "impl `{head}` does not satisfy the Patterson conditions" )) .with_code(DiagnosticCode::TYPECK_PATTERSON_CONDITION) - .with_primary_label_span(span.clone(), Some("instance head violates Patterson condition")) - .with_note("each instance context must be structurally smaller than the instance head") - .with_help("remove the recursive context, add a more specific instance, or use the Patterson-condition pragma intentionally"), + .with_primary_label_span(span.clone(), Some("impl head violates Patterson condition")) + .with_note("each impl context must be structurally smaller than the impl head") + .with_help("remove the recursive context, add a more specific impl, or use the Patterson-condition pragma intentionally"), TypeckDiagnostic::BoundedVariableCondition { span } => { Diagnostic::error("Bounded variable condition fails!") .with_code(DiagnosticCode::TYPECK_BOUNDED_VARIABLE_CONDITION) - .with_primary_label_span(span.clone(), Some("instance head is missing context variables")) + .with_primary_label_span(span.clone(), Some("impl head is missing context variables")) } TypeckDiagnostic::TypeAliasCycle { span, alias } => { Diagnostic::error(format!("recursive type alias `{alias}`")) @@ -711,10 +711,10 @@ impl TypeckDiagnostic { expected, actual, } => Diagnostic::error(format!( - "class arity mismatch for `{class}`: expected {expected}, got {actual}" + "trait arity mismatch for `{class}`: expected {expected}, got {actual}" )) .with_code(DiagnosticCode::TYPECK_CLASS_ARITY) - .with_primary_label_span(span.clone(), Some("class predicate arity mismatch")), + .with_primary_label_span(span.clone(), Some("trait predicate arity mismatch")), TypeckDiagnostic::OverlappingInstance { instance_span, overlaps_span, @@ -722,34 +722,34 @@ impl TypeckDiagnostic { overlaps, } => { let diagnostic = Diagnostic::error(format!( - "Overlapping instances are not supported\ninstance:\n{instance}\noverlaps with:\n{overlaps}" + "Overlapping impls are not supported\nimpl:\n{instance}\noverlaps with:\n{overlaps}" )) .with_code(DiagnosticCode::TYPECK_OVERLAPPING_INSTANCE) - .with_primary_label_span(instance_span.clone(), Some("overlapping instance")); + .with_primary_label_span(instance_span.clone(), Some("overlapping impl")); if let Some(overlaps_span) = overlaps_span { diagnostic.with_secondary_label_span( overlaps_span.clone(), - Some("previous overlapping instance"), + Some("previous overlapping impl"), ) } else { diagnostic } } TypeckDiagnostic::InvalidDefaultInstance { span, head } => Diagnostic::error(format!( - "Cannot have a default instance whose main argument contains no type variable: {head}" + "Cannot have a default impl whose main argument contains no type variable: {head}" )) .with_code(DiagnosticCode::TYPECK_INVALID_DEFAULT_INSTANCE) - .with_primary_label_span(span.clone(), Some("invalid default instance head")), + .with_primary_label_span(span.clone(), Some("invalid default impl head")), TypeckDiagnostic::IncompleteInstance { span, class, missing, } => Diagnostic::error(format!( - "Incomplete definition for class:\n{class}\nmissing definitions for:\n{}", + "Incomplete definition for trait:\n{class}\nmissing definitions for:\n{}", missing.join(", ") )) .with_code(DiagnosticCode::TYPECK_INCOMPLETE_INSTANCE) - .with_primary_label_span(span.clone(), Some("incomplete instance")), + .with_primary_label_span(span.clone(), Some("incomplete impl")), TypeckDiagnostic::UnknownInstanceMethod { span, name, @@ -761,7 +761,7 @@ impl TypeckDiagnostic { if let Some(class_span) = class_span { diagnostic.with_secondary_label_span( class_span.clone(), - Some("class defined here"), + Some("trait defined here"), ) } else { diagnostic @@ -773,9 +773,9 @@ impl TypeckDiagnostic { .with_code(DiagnosticCode::TYPECK_INCOMPLETE_SIGNATURE) .with_primary_label_span(span.clone(), Some("incomplete signature")) .with_note(format!("signature: {signature}")) - .with_note("annotate every parameter (name : Type) and provide a return type (-> Type)"), + .with_note("annotate every parameter (`name: Type`); add `returns (Type)` for a non-unit result"), TypeckDiagnostic::IncompleteMethodSignature { span, signature } => Diagnostic::error( - "class and instance methods must have complete type signatures", + "trait and impl methods must have complete type signatures", ) .with_code(DiagnosticCode::TYPECK_INCOMPLETE_METHOD_SIGNATURE) .with_primary_label_span(span.clone(), Some("incomplete method signature")) @@ -787,11 +787,11 @@ impl TypeckDiagnostic { reason, } => { Diagnostic::error(format!( - "invalid instance member signature for `{method}`: {reason}" + "invalid impl member signature for `{method}`: {reason}" )) .with_code(DiagnosticCode::TYPECK_INVALID_INSTANCE_METHOD_SIGNATURE) - .with_primary_label_span(span.clone(), Some("invalid instance method signature")) - .with_note("the instance method must match the class method after substituting the instance head") + .with_primary_label_span(span.clone(), Some("invalid impl method signature")) + .with_note("the impl method must match the trait method after substituting the impl head") } TypeckDiagnostic::InvalidConstructorPattern { span, name } => Diagnostic::error(format!( "constructor pattern `{name}` does not resolve to a constructor" @@ -809,10 +809,10 @@ impl TypeckDiagnostic { .with_code(DiagnosticCode::TYPECK_SHORTHAND_CONSTRUCTOR) .with_primary_label_span(span.clone(), Some("shorthand constructor")), TypeckDiagnostic::GenericDeriveConflict { span, ty } => Diagnostic::error(format!( - "type '{ty}' has a manual Generic instance but no 'pragma no-generic-instance-for {ty}'; add the pragma to suppress auto-derivation" + "type '{ty}' has a manual Generic impl but no 'pragma no-generic-instance-for {ty}'; add the pragma to suppress auto-derivation" )) .with_code(DiagnosticCode::TYPECK_GENERIC_DERIVE_CONFLICT) - .with_primary_label_span(span.clone(), Some("manual Generic instance conflicts with auto-derivation")), + .with_primary_label_span(span.clone(), Some("manual Generic impl conflicts with auto-derivation")), TypeckDiagnostic::InvalidDerive { span, ty, @@ -840,7 +840,7 @@ impl TypeckDiagnostic { .with_code(DiagnosticCode::TYPECK_COMPTIME_LET_RUNTIME) .with_primary_label_span(span.clone(), Some("runtime initializer")), TypeckDiagnostic::ComptimeReturnRuntime { span, context } => Diagnostic::error(format!( - "{context}: function annotated '-> comptime' returns a runtime expression" + "{context}: function with a comptime result returns a runtime expression" )) .with_code(DiagnosticCode::TYPECK_COMPTIME_RETURN_RUNTIME) .with_primary_label_span(span.clone(), Some("runtime return expression")), @@ -1098,7 +1098,7 @@ fn signature_from_scheme<'db>( }) .collect::>(); format!( - "{name}({}) -> {}", + "{name}({}) returns ({})", parameters.join(", "), display_ty_source(db, ret, type_var_names) ) @@ -1124,11 +1124,39 @@ fn source_signature_from_func_sig<'db>( } } let ret = sig.ret?; - Some(format!( - "{name}({}) -> {}", - params.join(", "), - display_type_ref_source(db, ret) - )) + let type_vars = if sig.type_vars.is_empty() { + String::new() + } else { + format!( + "<{}>", + sig.type_vars + .iter() + .map(|var| ident_text(db, var)) + .collect::>() + .join(", ") + ) + }; + let mut out = format!("{name}{type_vars}({})", params.join(", ")); + if sig.public.is_some() { + out.push_str(" public"); + } + if sig.payable.is_some() { + out.push_str(" payable"); + } + out.push_str(" returns ("); + out.push_str(&display_type_ref_source(db, ret)); + out.push(')'); + if !sig.preds.is_empty() { + out.push_str(" where "); + out.push_str( + &sig.preds + .iter() + .map(|pred| format_pred_ref(db, *pred)) + .collect::>() + .join(", "), + ); + } + Some(out) } fn def_hir_module<'db>(db: &'db dyn Db, def: DefId<'db>) -> Module<'db> { @@ -1657,44 +1685,6 @@ fn type_ref_constructor_name<'db>(db: &'db dyn HirDb, ty: TypeRef<'db>) -> Strin } } -pub(super) fn implicit_class_head_binder_diagnostic<'db>( - db: &'db dyn HirDb, - class: ClassDef<'db>, -) -> Option { - let vars = class.type_var_elems(db); - let [var] = vars.as_slice() else { - return None; - }; - let head = class.head(db).kind(db); - let TypeRefKind::Named { - qualifier: None, - name, - args, - } = head.ty.kind(db) - else { - return None; - }; - if !args.atom().is_empty() || builtin_type_name(ident_text(db, name).as_str()) { - return None; - } - if ident_text(db, var) != ident_text(db, name) || var.span(db) != name.span(db) { - return None; - } - Some(TypeckDiagnostic::UndefinedTypeVariables { - vars: vec![( - LabelSpan::from_span(db, name.span(db)), - ident_text(db, name), - )], - }) -} - -fn builtin_type_name(name: &str) -> bool { - matches!( - name, - "word" | "Word" | "bool" | "()" | "pair" | "sum" | "integer" - ) -} - #[derive(Clone)] struct DataCycleNode<'db> { adt: AdtDef<'db>, @@ -2232,35 +2222,19 @@ pub(super) fn is_complete_signature(sig: &FuncSig<'_>) -> bool { pub(super) fn format_func_sig<'db>(db: &'db dyn HirDb, sig: &FuncSig<'db>) -> String { let mut out = String::new(); + out.push_str("function "); + out.push_str(&ident_text(db, &sig.name)); if !sig.type_vars.is_empty() { - out.push_str("forall "); + out.push('<'); out.push_str( &sig.type_vars .iter() .map(|var| ident_text(db, var)) .collect::>() - .join(" "), - ); - out.push_str(". "); - } - if !sig.preds.is_empty() { - out.push_str( - &sig.preds - .iter() - .map(|pred| format_pred_ref(db, *pred)) - .collect::>() .join(", "), ); - out.push_str(" => "); - } - if sig.public.is_some() { - out.push_str("public "); - } - if sig.payable.is_some() { - out.push_str("payable "); + out.push('>'); } - out.push_str("function "); - out.push_str(&ident_text(db, &sig.name)); out.push('('); out.push_str( &sig.params @@ -2271,9 +2245,26 @@ pub(super) fn format_func_sig<'db>(db: &'db dyn HirDb, sig: &FuncSig<'db>) -> St .join(", "), ); out.push(')'); + if sig.public.is_some() { + out.push_str(" public"); + } + if sig.payable.is_some() { + out.push_str(" payable"); + } if let Some(ret) = sig.ret { - out.push_str(" -> "); + out.push_str(" returns ("); out.push_str(&format_type_ref(db, ret)); + out.push(')'); + } + if !sig.preds.is_empty() { + out.push_str(" where "); + out.push_str( + &sig.preds + .iter() + .map(|pred| format_pred_ref(db, *pred)) + .collect::>() + .join(", "), + ); } out } @@ -2286,7 +2277,7 @@ fn format_func_param<'db>(db: &'db dyn HirDb, param: &FuncParam<'db>) -> String out.push_str("comptime "); } out.push_str(&ident_text(db, name)); - out.push_str(" : "); + out.push_str(": "); out.push_str(&format_type_ref(db, *ty)); out } @@ -2305,12 +2296,12 @@ fn format_func_param<'db>(db: &'db dyn HirDb, param: &FuncParam<'db>) -> String fn format_pred_ref<'db>(db: &'db dyn HirDb, pred: hir::ast::ty::PredRef<'db>) -> String { let pred = pred.kind(db); let mut out = format!( - "{} : {}", + "{}: {}", format_type_ref(db, pred.ty), ident_text(db, &pred.class) ); if !pred.args.atom().is_empty() { - out.push('('); + out.push('<'); out.push_str( &pred .args @@ -2320,7 +2311,7 @@ fn format_pred_ref<'db>(db: &'db dyn HirDb, pred: hir::ast::ty::PredRef<'db>) -> .collect::>() .join(", "), ); - out.push(')'); + out.push('>'); } out } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 2b2cc295..1e98abff 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -62,7 +62,7 @@ impl<'db> InferCtx<'db> { args, expected.clone(), ), - ExprKind::Proxy { .. } => self.engine.fresh_var(), + ExprKind::Proxy { ty, .. } => self.infer_proxy_expr(*ty, expected.clone()), ExprKind::Lambda { params, ret, @@ -226,6 +226,49 @@ impl<'db> InferCtx<'db> { self.memory_dyn_array_ty(elem_ty).unwrap_or(InferTy::Error) } + /// Gives `@T` the same `Proxy` constructor selected by its call-site + /// context. A source tree can contain both the bundled std module and a + /// main-library mirror of it, so choosing an arbitrary canonical `Proxy` + /// definition would make otherwise identical types nominally distinct. + fn infer_proxy_expr( + &mut self, + ty: TypeRef<'db>, + expected: Option>, + ) -> InferTy<'db> { + let inner = self.lower_type_ref(ty); + if let Some(expected) = expected { + let resolved = self.engine.resolve(expected.clone()); + if let InferTy::Named { ctor, args } = &resolved + && args.len() == 1 + && matches!( + ctor, + TyCtor::User(user) + if user.def.name(self.db).as_deref() == Some("Proxy") + ) + { + self.unify_span(ty.span(self.db), args[0].clone(), inner); + return resolved; + } + } + + crate::support::canonical_std_adt_defs(self.db, "Proxy") + .into_iter() + .find(|def| { + self.entry_module.is_some_and(|entry| { + crate::support::module_for_def_via_graph(self.db, entry, *def).is_some() + }) + }) + .or_else(|| crate::support::canonical_std_adt_def(self.db, "Proxy")) + .map(|def| InferTy::Named { + ctor: TyCtor::User(UserTyCtor { + def, + kind: UserTyCtorKind::Adt, + }), + args: vec![inner], + }) + .unwrap_or_else(|| self.engine.fresh_var()) + } + fn report_numeric_if_branch_mismatch( &mut self, body: FuncBody<'db>, diff --git a/crates/hir-ty/src/infer/mod.rs b/crates/hir-ty/src/infer/mod.rs index 13b8641c..9fa4c6e7 100644 --- a/crates/hir-ty/src/infer/mod.rs +++ b/crates/hir-ty/src/infer/mod.rs @@ -35,7 +35,7 @@ use tracing::field; use crate::{ BinderEnv, BodyDesugarView, BodyPreTypeckDesugarPlan, BoolUnitSumView, BuiltinClassId, BuiltinTyCtor, ClassId, Db, LoweredFunction, Pred, PredKind, ProductShape, QualTy, - SourceOrigin, Ty, TyCtor, TyKind, TyScheme, TypeLowering, TypeLoweringDiagnostic, + SourceOrigin, Ty, TyCtor, TyKind, TyScheme, TypeLowering, TypeLoweringDiagnostic, UserTyCtor, UserTyCtorKind, alias::{AliasError, AliasNormalizer, AliasType, AliasTypeKind}, builtin_scheme, canonical_goal_with_allowed, class_method_type_vars, diff --git a/crates/hir-ty/src/infer/obligations.rs b/crates/hir-ty/src/infer/obligations.rs index 8e859a98..7ab8a982 100644 --- a/crates/hir-ty/src/infer/obligations.rs +++ b/crates/hir-ty/src/infer/obligations.rs @@ -529,7 +529,7 @@ impl<'db> InferCtx<'db> { index, TypeckDiagnostic::AmbiguousInferredType { span: self.body_label_span(self.root_body), - scheme: format!("forall _ . {pred_text} => {root_ty}"), + scheme: format!("<_> {root_ty} where {pred_text}"), }, )); } @@ -868,10 +868,10 @@ impl<'db> InferCtx<'db> { let preds = ambiguous .into_iter() - .map(|main| format!("{main} : Int")) + .map(|main| format!("{main}: Int")) .collect::>() .join(", "); - let scheme = format!("forall _ . {preds} => {}", self.display_infer_ty(root_ty)); + let scheme = format!("<_> {} where {preds}", self.display_infer_ty(root_ty)); self.diagnostics .push(TypeckDiagnostic::AmbiguousInferredType { span: self.body_label_span(self.root_body), diff --git a/crates/hir-ty/src/infer/tests.rs b/crates/hir-ty/src/infer/tests.rs index d4adfaee..bd51b108 100644 --- a/crates/hir-ty/src/infer/tests.rs +++ b/crates/hir-ty/src/infer/tests.rs @@ -98,7 +98,7 @@ impl nameres::Db for TestDb { impl crate::Db for TestDb {} fn source_file(db: &TestDb, name: &str, src: &str) -> SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid url"); + let url = format!("memory:///{name}.sol").parse().expect("valid url"); SourceFile::new(db, url, Some(src.to_owned())) } @@ -120,7 +120,7 @@ fn module_key(path: &[&str]) -> ModuleKey { fn insert_module_source(db: &mut TestDb, path: &[&str], src: &str) -> ModuleKey { let key = module_key(path); - let url = format!("memory:///{}.solc", path.join("/")) + let url = format!("memory:///{}.sol", path.join("/")) .parse() .expect("valid url"); let file = SourceFile::new(&*db, url, Some(src.to_owned())); @@ -136,114 +136,112 @@ fn db_with_main_typeck(src: &str) -> (TestDb, ModuleKey) { fn db_with_array_std(main_src: &str) -> (TestDb, ModuleKey) { let mut db = TestDb::default(); - let std_path = PathBuf::from("/std/std.solc"); - let main_path = PathBuf::from("/main/main.solc"); + let std_path = PathBuf::from("/std/std.sol"); + let main_path = PathBuf::from("/main/main.sol"); let std_file = source_file_at_path( &db, &std_path, r#" export { memory(*), storage(*), calldata(*), DynArray, array(*), uint256(*), address(*), string, Encoded(*), Decoded(*), concatLit, Add, Array, ArrayPush, Length, Typedef, CanStore, RValueIdxAccess }; -data memory(t) = memory(word); -data storage(t) = storage(word); -data calldata(t) = calldata(word); -data DynArray(t); -data array(t) = array(word); -data uint256 = uint256(word); -data address = address(word); -data string; -data Encoded = Encoded(word); -data Decoded = Decoded(word); +enum memory {memory(word)} +enum storage {storage(word)} +enum calldata {calldata(word)} +enum DynArray {} +enum array {array(word)} +enum uint256 {uint256(word)} +enum address {address(word)} +enum string {} +enum Encoded {Encoded(word)} +enum Decoded {Decoded(word)} -function concatLit(comptime lhs:string, comptime rhs:string) -> string { return lhs; } +function concatLit(comptime lhs:string, comptime rhs:string) returns (string) { return lhs; } -forall self . class self:Add { - function add(lhs:self, rhs:self) -> self; +trait Add { + function add(lhs:self, rhs:self) returns (self) ; } -instance uint256:Add { - function add(lhs:uint256, rhs:uint256) -> uint256 { return lhs; } +impl Add { + function add(lhs:uint256, rhs:uint256) returns (uint256) { return lhs; } } -forall abs rep . class abs:Typedef(rep) { - function abs(x:rep) -> abs; - function rep(x:abs) -> rep; +trait Typedef { + function abs(x:rep) returns (abs) ; + function rep(x:abs) returns (rep) ; } -forall t . default instance t:Typedef(t) { - function abs(x:t) -> t { return x; } - function rep(x:t) -> t { return x; } +default impl Typedef { + function abs(x:t) returns (t) { return x; } + function rep(x:t) returns (t) { return x; } } -instance uint256:Typedef(word) { - function abs(x:word) -> uint256 { return uint256(x); } - function rep(x:uint256) -> word { return 0; } +impl Typedef { + function abs(x:word) returns (uint256) { return uint256(x); } + function rep(x:uint256) returns (word) { return 0; } } -instance memory(string):Typedef(word) { - function abs(x:word) -> memory(string) { return memory(x); } - function rep(x:memory(string)) -> word { return 0; } +impl Typedef,word> { + function abs(x:word) returns (memory) { return memory(x); } + function rep(x:memory) returns (word) { return 0; } } -forall col_idx val . class col_idx:RValueIdxAccess(val) { - function lookup(xi:col_idx) -> val; +trait RValueIdxAccess { + function lookup(xi:col_idx) returns (val) ; } -forall i . i:Typedef(word) => -instance (calldata(array(Encoded)), i):RValueIdxAccess(Decoded) { - function lookup(xi:(calldata(array(Encoded)), i)) -> Decoded { +impl RValueIdxAccess<(calldata>, i),Decoded> where i: Typedef { + function lookup(xi:(calldata>, i)) returns (Decoded) { return Decoded(0); } } -forall dst value . class dst:CanStore(value) { - function store(dst:dst, value:value) -> (); - function load(dst:dst) -> value; +trait CanStore { + function store(dst:dst, value:value) returns () ; + function load(dst:dst) returns (value) ; } -instance storage(word):CanStore(word) { - function store(dst:storage(word), value:word) -> () { return (); } - function load(dst:storage(word)) -> word { return 0; } +impl CanStore,word> { + function store(dst:storage, value:word) returns () { return (); } + function load(dst:storage) returns (word) { return 0; } } -instance storage(uint256):CanStore(uint256) { - function store(dst:storage(uint256), value:uint256) -> () { return (); } - function load(dst:storage(uint256)) -> uint256 { return uint256(0); } +impl CanStore,uint256> { + function store(dst:storage, value:uint256) returns () { return (); } + function load(dst:storage) returns (uint256) { return uint256(0); } } -instance storage(string):CanStore(memory(string)) { - function store(dst:storage(string), value:memory(string)) -> () { return (); } - function load(dst:storage(string)) -> memory(string) { return memory(0); } +impl CanStore,memory> { + function store(dst:storage, value:memory) returns () { return (); } + function load(dst:storage) returns (memory) { return memory(0); } } -instance storage(array(word)):CanStore(storage(array(word))) { - function store(dst:storage(array(word)), value:storage(array(word))) -> () { return (); } - function load(dst:storage(array(word))) -> storage(array(word)) { return dst; } +impl CanStore>,storage>> { + function store(dst:storage>, value:storage>) returns () { return (); } + function load(dst:storage>) returns (storage>) { return dst; } } -forall self . class self:Length { - function length(value:self) -> uint256; +trait Length { + function length(value:self) returns (uint256) ; } -forall self . class self:Array { - function pop(value:self) -> (); +trait Array { + function pop(value:self) returns () ; } -forall self elem . class self:ArrayPush(elem) { - function push(value:self, elem:elem) -> (); +trait ArrayPush { + function push(value:self, elem:elem) returns () ; } -forall t . instance storage(array(t)):Length { - function length(value:storage(array(t))) -> uint256 { return uint256(0); } +impl Length>> { + function length(value:storage>) returns (uint256) { return uint256(0); } } -forall t . instance storage(array(t)):Array { - function pop(value:storage(array(t))) -> () { return (); } +impl Array>> { + function pop(value:storage>) returns () { return (); } } -forall t elem . storage(t):CanStore(elem) => -instance storage(array(t)):ArrayPush(elem) { - function push(value:storage(array(t)), elem:elem) -> () { return (); } +impl ArrayPush>,elem> where storage: CanStore { + function push(value:storage>, elem:elem) returns () { return (); } } "#, ); @@ -719,9 +717,9 @@ fn has_user_obligation<'db>( } #[test] -fn unannotated_function_scheme_uses_inferred_polymorphic_body_type() { +fn explicit_polymorphic_function_scheme_uses_declared_body_type() { let db = TestDb::default(); - let module = parse_module(&db, "function id(x) { return x; }"); + let module = parse_module(&db, "function id(x: a) returns (a) { return x; }"); let info = function_info_named(&db, module, "id"); let scheme = function_scheme_in_hir_module(&db, module, info.function.def_id_value(&db)) .expect("scheme"); @@ -742,14 +740,14 @@ fn unannotated_function_scheme_uses_inferred_polymorphic_body_type() { } #[test] -fn contract_entry_dispatch_uses_inferred_return_type() { +fn contract_entry_dispatch_uses_declared_return_type() { let mut db = TestDb::default(); let key = insert_module_source( &mut db, &["main"], r#" contract Answer { - public function main() { + function main() public returns (word) { return 42; } } @@ -778,19 +776,23 @@ fn inference_result_records_comptime_obligation_sites() { let module = parse_module( &db, r#" -function need(comptime x: word) -> comptime word { +function need(comptime x: word) returns (comptime) { return x; } -function g() -> comptime word { - let y : comptime word = need(2); +function g() returns (comptime) { + let y : comptime = need(2); return y; } -function f(x: word) -> comptime word { - match x { - | comptime 1 => return need(2); - | _ => return 0; +function f(x: word) returns (comptime) { + match (x) { + case comptime 1 { + return need(2); + } + default { + return 0; + } } } "#, @@ -842,7 +844,7 @@ fn inferred_integer_let_records_comptime_obligation() { let module = parse_module( &db, r#" -function f() -> word { +function f() returns (word) { let x = wordToInteger(20); return wordFromInteger(x); } @@ -866,56 +868,56 @@ function f() -> word { #[test] fn comptime_only_types_cover_params_returns_typed_lets_and_call_args() { let mut db = TestDb::default(); - let std_path = PathBuf::from("/std/std.solc"); - let main_path = PathBuf::from("/main/main.solc"); + let std_path = PathBuf::from("/std/std.sol"); + let main_path = PathBuf::from("/main/main.sol"); let std_file = source_file_at_path( &db, &std_path, r#" export { string }; -data string; +enum string {} "#, ); let main_file = source_file_at_path( &db, &main_path, r#" -import std.{string}; +import {string} from std; type Text = string; type Big = integer; -function explicitlyNeedsText(comptime value: Text) -> () { +function explicitlyNeedsText(comptime value: Text) returns () { return (); } -function explicitlyNeedsBig(comptime value: Big) -> () { +function explicitlyNeedsBig(comptime value: Big) returns () { return (); } -function textParamIsComptime(value: Text) -> () { +function textParamIsComptime(value: Text) returns () { return explicitlyNeedsText(value); } -function bigParamIsComptime(value: Big) -> () { +function bigParamIsComptime(value: Big) returns () { return explicitlyNeedsBig(value); } -function takesText(value: Text) -> () { +function takesText(value: Text) returns () { return (); } -function takesBig(value: Big) -> () { +function takesBig(value: Big) returns () { return (); } -function exerciseText(value: Text) -> Text { +function exerciseText(value: Text) returns (Text) { let copy: Text = value; takesText(copy); return copy; } -function exerciseBig(value: Big) -> Big { +function exerciseBig(value: Big) returns (Big) { let copy: Big = value; takesBig(copy); return copy; @@ -979,17 +981,17 @@ function exerciseBig(value: Big) -> Big { #[test] fn string_literals_and_concat_lit_use_str_conversion_only_at_literal_sites() { let mut db = TestDb::default(); - let std_path = PathBuf::from("/std/std.solc"); - let main_path = PathBuf::from("/main/main.solc"); + let std_path = PathBuf::from("/std/std.sol"); + let main_path = PathBuf::from("/main/main.sol"); let std_file = source_file_at_path( &db, &std_path, r#" export { memory(*), string, concatLit, strlenLit }; -data memory(a) = memory(word); -data string; -function concatLit(comptime lhs: string, comptime rhs: string) -> string { return lhs; } -function strlenLit(comptime value: string) -> word { return 0; } +enum memory {memory(word)} +enum string {} +function concatLit(comptime lhs: string, comptime rhs: string) returns (string) { return lhs; } +function strlenLit(comptime value: string) returns (word) { return 0; } "#, ); let main_file = source_file_at_path( @@ -997,45 +999,45 @@ function strlenLit(comptime value: string) -> word { return 0; } &main_path, r#" import std; -import std.{memory, string, strlenLit}; +import {memory, string, strlenLit} from std; -data Tag = Tag(word); -instance Tag : Str { - function fromString(comptime value: string) -> Tag { +enum Tag {Tag(word)} +impl Str { + function fromString(comptime value: string) returns (Tag) { return Tag(strlenLit(value)); } } -function literal() -> memory(string) { return "hello"; } -function concatLit(lhs: word, rhs: word) -> word { return lhs; } -function concatenated() -> memory(string) { return std.concatLit("he", "llo"); } -function explicit(value: string) -> memory(string) { return Str.fromString(value); } -function tagged() -> Tag { return "abcd"; } -function taggedFromLet() -> Tag { +function literal() returns (memory) { return "hello"; } +function concatLit(lhs: word, rhs: word) returns (word) { return lhs; } +function concatenated() returns (memory) { return std.concatLit("he", "llo"); } +function explicit(value: string) returns (memory) { return Str.fromString(value); } +function tagged() returns (Tag) { return "abcd"; } +function taggedFromLet() returns (Tag) { let value = "abcd"; return Str.fromString(value); } -function inferredLiteral() -> () { let value = "x"; return (); } -function inferredConcat() -> () { let value = std.concatLit("a", "b"); return (); } -function consumePair(value: (string, word)) -> word { return 0; } -function inferredTuple() -> word { +function inferredLiteral() returns () { let value = "x"; return (); } +function inferredConcat() returns () { let value = std.concatLit("a", "b"); return (); } +function consumePair(value: (string, word)) returns (word) { return 0; } +function inferredTuple() returns (word) { let value = ("x", 0); return consumePair(value); } -function inferredComptimeParam() -> () { - let sink = lam (comptime value) -> () { return (); }; +function inferredComptimeParam() returns () { + let sink = lam (comptime value: string) -> () { return (); }; sink("x"); return (); } -function invalidConcat() -> memory(string) { return concatLit(1, 2); } -function makeWord() -> word { return 0; } -function invalidSource() -> memory(string) { +function invalidConcat() returns (memory) { return concatLit(1, 2); } +function makeWord() returns (word) { return 0; } +function invalidSource() returns (memory) { let value; - let result: memory(string) = Str.fromString(value); + let result: memory = Str.fromString(value); value = makeWord(); return result; } -function runtime(value: string) -> memory(string) { return value; } +function runtime(value: string) returns (memory) { return value; } "#, ); let std_key = module_key_for_path(LibraryId::Std, &PathBuf::from("/std"), &std_path).unwrap(); @@ -1111,10 +1113,10 @@ function runtime(value: string) -> memory(string) { return value; } fn array_literals_infer_canonical_memory_dyn_array_and_empty_uses_context() { let (db, key) = db_with_array_std( r#" -import std.{memory, DynArray}; +import {memory, DynArray} from std; -function filled(x:word, y:word) -> memory(DynArray(word)) { return [x, y]; } -function empty() -> memory(DynArray(word)) { return []; } +function filled(x:word, y:word) returns (memory>) { return [x, y]; } +function empty() returns (memory>) { return []; } "#, ); let module = module_id_from_key(&db, &key); @@ -1135,9 +1137,9 @@ function empty() -> memory(DynArray(word)) { return []; } fn array_literal_rejects_mixed_element_types() { let (db, key) = db_with_array_std( r#" -import std.{memory, DynArray}; +import {memory, DynArray} from std; -function mixed(x:word, flag:bool) -> memory(DynArray(word)) { +function mixed(x:word, flag:bool) returns (memory>) { return [x, flag]; } "#, @@ -1160,33 +1162,33 @@ fn array_string_literals_use_memory_string_from_memory_and_storage_contexts() { let (db, key) = db_with_array_std( r#" import std; -import std.{memory, storage, DynArray, array, string, Typedef, CanStore}; +import {memory, storage, DynArray, array, string, Typedef, CanStore} from std; -function inMemory() -> memory(DynArray(memory(string))) { +function inMemory() returns (memory>>) { return ["hello"]; } -function explicitConversion() -> memory(DynArray(memory(string))) { +function explicitConversion() returns (memory>>) { return [Str.fromString("hello")]; } -function concatenated() -> memory(DynArray(memory(string))) { +function concatenated() returns (memory>>) { return [std.concatLit("hel", "lo")]; } -function conditional(flag:bool) -> memory(DynArray(memory(string))) { - return [if (flag) then "yes" else "no"]; +function conditional(flag:bool) returns (memory>>) { + return [((flag) ? "yes" : "no")]; } contract C { - names:array(string); + names:array; - function setNames() -> () { + function setNames() returns () { names = ["alice", "bob"]; return (); } - function clearNames() -> () { + function clearNames() returns () { names = []; return (); } @@ -1275,21 +1277,21 @@ contract C { fn storage_array_field_ufcs_prepends_receiver_once() { let (db, key) = db_with_array_std( r#" -import std.{array, storage, uint256, Array, ArrayPush, Length}; +import {array, storage, uint256, Array, ArrayPush, Length} from std; contract C { - members:array(uint256); + members:array; - function memberCount() -> uint256 { + function memberCount() returns (uint256) { return members.length(); } - function append(value:uint256) -> () { + function append(value:uint256) returns () { members.push(value); return (); } - function removeLast() -> () { + function removeLast() returns () { members.pop(); return (); } @@ -1344,19 +1346,19 @@ contract C { fn local_and_parameter_ufcs_infer_receiver_and_evidence_once() { let (db, key) = db_with_main_typeck( r#" -forall self . class self:Echo { - function echo(value:self) -> self; +trait Echo { + function echo(value:self) returns (self) ; } -instance word:Echo { - function echo(value:word) -> word { return value; } +impl Echo { + function echo(value:word) returns (word) { return value; } } -function parameterReceiver(value:word) -> word { +function parameterReceiver(value:word) returns (word) { return value.echo(); } -function localReceiver(value:word) -> word { +function localReceiver(value:word) returns (word) { let local:word = value; return local.echo(); } @@ -1400,24 +1402,24 @@ function localReceiver(value:word) -> word { fn field_ufcs_comptime_parameter_uses_explicit_argument_position() { let (db, key) = db_with_array_std( r#" -import std.{array, storage}; +import {array, storage} from std; -forall self . class self:Stamp { - function stamp(value:self, comptime tag:word) -> word; +trait Stamp { + function stamp(value:self, comptime tag:word) returns (word) ; } -instance storage(array(word)):Stamp { - function stamp(value:storage(array(word)), comptime tag:word) -> word { return tag; } +impl Stamp>> { + function stamp(value:storage>, comptime tag:word) returns (word) { return tag; } } contract C { - stored:array(word); + stored:array; - function literalTag() -> word { + function literalTag() returns (word) { return stored.stamp(7); } - function runtimeTag(tag:word) -> word { + function runtimeTag(tag:word) returns (word) { return stored.stamp(tag); } } @@ -1477,28 +1479,28 @@ contract C { fn local_and_parameter_ufcs_comptime_parameter_uses_explicit_argument_position() { let (db, key) = db_with_main_typeck( r#" -forall self . class self:Stamp { - function stamp(value:self, comptime tag:word) -> word; +trait Stamp { + function stamp(value:self, comptime tag:word) returns (word) ; } -instance word:Stamp { - function stamp(value:word, comptime tag:word) -> word { return tag; } +impl Stamp { + function stamp(value:word, comptime tag:word) returns (word) { return tag; } } -function parameterLiteral(value:word) -> word { +function parameterLiteral(value:word) returns (word) { return value.stamp(7); } -function localLiteral(value:word) -> word { +function localLiteral(value:word) returns (word) { let local:word = value; return local.stamp(7); } -function parameterRuntime(value:word, tag:word) -> word { +function parameterRuntime(value:word, tag:word) returns (word) { return value.stamp(tag); } -function localRuntime(value:word, tag:word) -> word { +function localRuntime(value:word, tag:word) returns (word) { let local:word = value; return local.stamp(tag); } @@ -1559,29 +1561,29 @@ function localRuntime(value:word, tag:word) -> word { fn memory_dyn_array_index_returns_element_and_requires_word_typedefs() { let (db, key) = db_with_array_std( r#" -import std.{memory, DynArray, uint256, Typedef}; +import {memory, DynArray, uint256, Typedef} from std; -function read(xs:memory(DynArray(word)), i:uint256) -> word { +function read(xs:memory>, i:uint256) returns (word) { return xs[i]; } -function write(xs:memory(DynArray(word)), i:uint256, value:word) -> () { +function write(xs:memory>, i:uint256, value:word) returns () { xs[i] = value; return (); } -function compound(xs:memory(DynArray(word)), i:uint256, value:word) -> () { +function compound(xs:memory>, i:uint256, value:word) returns () { xs[i] += value; return (); } -function annotatedWrite(xs:memory(DynArray(word)), i:uint256, value:word) -> () { - (xs[i] : word) : word = value; +function annotatedWrite(xs:memory>, i:uint256, value:word) returns () { + (xs[i] ) = value; return (); } -function annotatedCompound(xs:memory(DynArray(word)), i:uint256, value:word) -> () { - xs[i] : word += value; +function annotatedCompound(xs:memory>, i:uint256, value:word) returns () { + xs[i] += value; return (); } "#, @@ -1627,14 +1629,14 @@ function annotatedCompound(xs:memory(DynArray(word)), i:uint256, value:word) -> fn calldata_array_index_uses_rvalue_evidence_and_improves_decoded_type() { let (db, key) = db_with_array_std( r#" -import std.{*}; +import * from std; -function inferred(xs:calldata(array(Encoded)), i:uint256) -> () { +function inferred(xs:calldata>, i:uint256) returns () { let value = xs[i]; return (); } -function expected(xs:calldata(array(Encoded)), i:uint256) -> Decoded { +function expected(xs:calldata>, i:uint256) returns (Decoded) { return xs[i]; } "#, @@ -1692,41 +1694,25 @@ function expected(xs:calldata(array(Encoded)), i:uint256) -> Decoded { fn calldata_array_index_rejects_plain_and_compound_writes() { let (db, key) = db_with_array_std( r#" -import std.{*}; +import * from std; -function write( - xs:calldata(array(Encoded)), - i:uint256, - value:Decoded -) -> () { +function write(xs: calldata>, i: uint256, value: Decoded) { xs[i] = value; return (); } -function compound( - xs:calldata(array(Encoded)), - i:uint256, - value:Decoded -) -> () { +function compound(xs: calldata>, i: uint256, value: Decoded) { xs[i] += value; return (); } -function annotatedWrite( - xs:calldata(array(Encoded)), - i:uint256, - value:Decoded -) -> () { - (xs[i] : Decoded) : Decoded = value; +function annotatedWrite(xs: calldata>, i: uint256, value: Decoded) { + (xs[i] ) = value; return (); } -function annotatedCompound( - xs:calldata(array(Encoded)), - i:uint256, - value:Decoded -) -> () { - xs[i] : Decoded += value; +function annotatedCompound(xs: calldata>, i: uint256, value: Decoded) { + xs[i] += value; return (); } "#, @@ -1751,12 +1737,12 @@ function annotatedCompound( fn same_named_non_std_calldata_array_keeps_generic_index_typing() { let (db, key) = db_with_array_std( r#" -import std.{RValueIdxAccess}; +import {RValueIdxAccess} from std; -data calldata(t) = calldata(word); -data array(t) = array(word); +enum calldata {calldata(word)} +enum array {array(word)} -function read(xs:calldata(array(word)), i:word) -> word { +function read(xs:calldata>, i:word) returns (word) { return xs[i]; } "#, @@ -1789,12 +1775,9 @@ function read(xs:calldata(array(word)), i:word) -> word { fn direct_storage_array_handle_assignment_is_a_raw_rebind() { let (db, key) = db_with_array_std( r#" -import std.{storage, array, string, CanStore}; +import {storage, array, string, CanStore} from std; -function rebind( - lhs:storage(array(string)), - rhs:storage(array(string)) -) -> () { +function rebind(lhs: storage>, rhs: storage>) { lhs = rhs; return (); } @@ -1821,7 +1804,7 @@ fn importless_contract_field_assignment_keeps_the_declared_value_type() { contract C { value:word; - function write(flag:bool) -> () { + function write(flag:bool) returns () { value = flag; return (); } @@ -1844,24 +1827,24 @@ contract C { fn storage_load_and_assign_use_can_store_result_improvement() { let (db, key) = db_with_array_std( r#" -import std.{memory, storage, CanStore}; +import {memory, storage, CanStore} from std; -data Blob; +enum Blob {} -instance storage(Blob):CanStore(memory(Blob)) { - function store(dst:storage(Blob), value:memory(Blob)) -> () { return (); } - function load(dst:storage(Blob)) -> memory(Blob) { return memory(0); } +impl CanStore,memory> { + function store(dst:storage, value:memory) returns () { return (); } + function load(dst:storage) returns (memory) { return memory(0); } } contract C { value:Blob; - function write(src:memory(Blob)) -> () { + function write(src:memory) returns () { value = src; return (); } - function read() -> memory(Blob) { + function read() returns (memory) { return value; } } @@ -1880,61 +1863,56 @@ fn contract_field_assignment_uses_specific_assign_evidence() { r#" pragma no-patterson-condition Assign; -data storage(t) = storage(word); -data mapping(k, v) = mapping(word); -data Foo = Foo(word); +enum storage {storage(word)} +enum mapping {mapping(word)} +enum Foo {Foo(word)} -forall dst value . class dst:CanStore(value) { - function store(dst:dst, value:value) -> (); - function load(dst:dst) -> value; +trait CanStore { + function store(dst:dst, value:value) returns () ; + function load(dst:dst) returns (value) ; } -forall lhs rhs . class lhs:Assign(rhs) { - function assign(lhs:lhs, rhs:rhs) -> (); +trait Assign { + function assign(lhs:lhs, rhs:rhs) returns () ; } -instance storage(word):CanStore(word) { - function store(dst:storage(word), value:word) -> () { return (); } - function load(dst:storage(word)) -> word { return 0; } +impl CanStore,word> { + function store(dst:storage, value:word) returns () { return (); } + function load(dst:storage) returns (word) { return 0; } } -forall a b . a:CanStore(b) => instance a:Assign(b) { - function assign(lhs:a, rhs:b) -> () { CanStore.store(lhs, rhs); } +impl Assign where a: CanStore { + function assign(lhs:a, rhs:b) returns () { CanStore.store(lhs, rhs); } } -instance storage(word):Assign(bool) { - function assign(lhs:storage(word), rhs:bool) -> () { return (); } +impl Assign,bool> { + function assign(lhs:storage, rhs:bool) returns () { return (); } } -instance storage(mapping(word, word)):CanStore(storage(mapping(word, word))) { - function store( - dst:storage(mapping(word, word)), - value:storage(mapping(word, word)) - ) -> () { return (); } - function load( - dst:storage(mapping(word, word)) - ) -> storage(mapping(word, word)) { return storage(0); } +impl CanStore word)>,storage word)>> { + function store(dst: storage word)>, value: storage word)>) { return (); } + function load(dst: storage word)>) returns (storage word)>) { return storage(0); } } -instance storage(mapping(word, word)):Assign(Foo) { - function assign(lhs:storage(mapping(word, word)), rhs:Foo) -> () { return (); } +impl Assign word)>,Foo> { + function assign(lhs:storage word)>, rhs:Foo) returns () { return (); } } contract C { value:word; - values:mapping(word, word); + values:mapping(word => word); - function write(flag:bool) -> () { + function write(flag:bool) returns () { value = flag; return (); } - function writeAnnotated(flag:bool) -> () { - value : storage(word) = flag; + function writeAnnotated(flag:bool) returns () { + value = flag; return (); } - function writeMapping(value:Foo) -> () { + function writeMapping(value:Foo) returns () { values = value; return (); } @@ -1973,13 +1951,9 @@ contract C { fn compound_storage_array_index_recognizes_parameter_handles() { let (db, key) = db_with_array_std( r#" -import std.{*}; +import * from std; -function bump( - values:storage(array(uint256)), - index:uint256, - delta:uint256 -) -> () { +function bump(values: storage>, index: uint256, delta: uint256) { values[index] += delta; return (); } @@ -2002,8 +1976,8 @@ function bump( fn storage_index_numeric_guard_rejects_shadowed_uint_names() { let (db, key) = db_with_array_std( r#" -data uint; -data uint256; +enum uint {} +enum uint256 {} "#, ); let module_id = module_id_from_key(&db, &key); @@ -2042,26 +2016,29 @@ data uint256; } #[test] -fn storage_ref_annotations_are_checked_without_widening_array_literal_routing() { +fn typed_storage_bindings_are_checked_without_widening_array_literal_routing() { let (db, key) = db_with_array_std( r#" -import std.{*}; +import * from std; contract C { - xs:array(uint256); + xs:array; - function good(i:uint256, value:uint256) -> () { - (xs : storage(array(uint256)))[i] = value; + function good(i:uint256, value:uint256) returns () { + let typed: storage> = xs; + typed[i] = value; return (); } - function bad(i:uint256) -> () { - (xs : storage(array(address)))[i] = uint256(1); + function bad(i:uint256) returns () { + let typed: storage> = xs; + typed[i] = uint256(1); return (); } - function annotatedLiteral() -> () { - xs = ([uint256(1)] : memory(DynArray(uint256))); + function typedLiteral() returns () { + let values: memory> = [uint256(1)]; + xs = values; return (); } } @@ -2071,15 +2048,16 @@ contract C { let (body, good) = infer_module_function_with_solver(&db, module_id, "good"); assert_no_typeck(&good); - let annotation = body - .exprs(&db) + let binding = body + .top_level_stmts(&db) .iter() - .find_map(|(id, expr)| matches!(expr.kind, ExprKind::TypeAnnot { .. }).then_some(id)) - .expect("storage array annotation"); + .copied() + .find(|stmt| matches!(body.stmts(&db).get(*stmt).kind, StmtKind::Let { .. })) + .expect("typed storage binding"); let uint256 = canonical_std_adt_ty(&db, "uint256", Vec::new()); let array = canonical_std_adt_ty(&db, "array", vec![uint256]); let storage_array = canonical_std_adt_ty(&db, "storage", vec![array]); - assert_eq!(good.expr_ty(body, annotation), Some(storage_array)); + assert_eq!(good.let_ty(body, binding), Some(storage_array)); let (body, bad) = infer_module_function_with_solver(&db, module_id, "bad"); assert!( @@ -2089,42 +2067,39 @@ contract C { "{:?}", bad.diagnostics ); - let annotation = body - .exprs(&db) + let binding = body + .top_level_stmts(&db) .iter() - .find_map(|(id, expr)| matches!(expr.kind, ExprKind::TypeAnnot { .. }).then_some(id)) - .expect("mismatched storage array annotation"); - assert_eq!(bad.expr_ty(body, annotation), Some(Ty::error(&db))); + .copied() + .find(|stmt| matches!(body.stmts(&db).get(*stmt).kind, StmtKind::Let { .. })) + .expect("mismatched storage binding"); + assert_eq!(bad.let_ty(body, binding), Some(Ty::error(&db))); - let (_, annotated_literal) = - infer_module_function_with_solver(&db, module_id, "annotatedLiteral"); + let (_, typed_literal) = infer_module_function_with_solver(&db, module_id, "typedLiteral"); assert!( - annotated_literal + typed_literal .diagnostics .iter() .any(|diagnostic| matches!(diagnostic, TypeckDiagnostic::Mismatch { .. })), "{:?}", - annotated_literal.diagnostics + typed_literal.diagnostics ); let module = module_hir(&db, module_id).expect("module hir"); let plan = crate::frontend_desugar_plan(&db, module); - let annotated_literal = plan + let typed_literal = plan .bodies .iter() - .find(|body| body.function_name == "annotatedLiteral") - .expect("annotatedLiteral desugar plan"); + .find(|body| body.function_name == "typedLiteral") + .expect("typedLiteral desugar plan"); assert!( - annotated_literal - .transforms - .iter() - .any(|transform| matches!( + typed_literal.transforms.iter().any(|transform| matches!( transform, crate::FrontendTransform::FieldWrite { hook, .. } if hook.starts_with("Assign.assign(") - )), + )), "{:?}", - annotated_literal.transforms + typed_literal.transforms ); } @@ -2132,31 +2107,31 @@ contract C { fn storage_array_index_alias_and_literal_assignment_preserve_reference_types() { let (db, key) = db_with_array_std( r#" -import std.{storage, array, uint256, Typedef, CanStore}; +import {storage, array, uint256, Typedef, CanStore} from std; contract C { - xs:array(word); + xs:array; n:word; - function read(i:uint256) -> word { return xs[i]; } + function read(i:uint256) returns (word) { return xs[i]; } - function aliasRead(i:uint256) -> word { + function aliasRead(i:uint256) returns (word) { let ys = xs; return ys[i]; } - function aliasWrite(i:uint256, value:word) -> () { + function aliasWrite(i:uint256, value:word) returns () { let ys = xs; ys[i] = value; return (); } - function set(x:word) -> () { + function set(x:word) returns () { xs = [x, x]; return (); } - function bad(x:word) -> () { + function bad(x:word) returns () { n = [x]; return (); } @@ -2226,12 +2201,12 @@ contract C { fn array_literal_contract_field_write_plan_uses_store_array_lit() { let (db, key) = db_with_array_std( r#" -import std.{storage, array}; +import {storage, array} from std; contract C { - xs:array(word); + xs:array; - function set(x:word) -> () { + function set(x:word) returns () { xs = [x]; return (); } @@ -2261,18 +2236,18 @@ contract C { fn module_local_string_and_integer_adts_remain_runtime_types() { let diagnostics = lowered_module_typeck_diagnostics( r#" -data string = RuntimeString(word); -data integer = RuntimeInteger(word); +enum string {RuntimeString(word)} +enum integer {RuntimeInteger(word)} -function takesString(value: string) -> () { +function takesString(value: string) returns () { return (); } -function takesInteger(value: integer) -> () { +function takesInteger(value: integer) returns () { return (); } -function exercise(value: word) -> () { +function exercise(value: word) returns () { takesString(string.RuntimeString(value)); takesInteger(integer.RuntimeInteger(value)); return (); From 25b5ee1db116584c250b112aff838fc65eeca6b4 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 035/110] Switch the compiler and fixtures to canonical syntax: hir ty Co-authored-by: Codex --- crates/hir-ty/src/infer/tests.rs | 485 ++++++++++---------- crates/hir-ty/src/lower.rs | 2 +- crates/hir-ty/src/prepare.rs | 71 ++- crates/hir-ty/src/solver/derived_class.rs | 4 +- crates/hir-ty/src/solver/derived_storage.rs | 6 +- crates/hir-ty/src/solver/display.rs | 14 +- crates/hir-ty/src/solver/evidence.rs | 6 +- crates/hir-ty/src/solver/mod.rs | 2 +- crates/hir-ty/src/solver/soundness.rs | 4 +- crates/hir-ty/src/support.rs | 2 +- crates/hir-ty/tests/contract_semantics.rs | 300 ++++++------ 11 files changed, 439 insertions(+), 457 deletions(-) diff --git a/crates/hir-ty/src/infer/tests.rs b/crates/hir-ty/src/infer/tests.rs index bd51b108..675c0791 100644 --- a/crates/hir-ty/src/infer/tests.rs +++ b/crates/hir-ty/src/infer/tests.rs @@ -2262,12 +2262,16 @@ function exercise(value: word) returns () { fn module_local_string_adt_rejects_primitive_string_patterns() { let diagnostics = lowered_module_typeck_diagnostics( r#" -data string = RuntimeString(word); +enum string {RuntimeString(word)} -function inspect(value: string) -> word { - match value { - | "a" => return 1; - | _ => return 0; +function inspect(value: string) returns (word) { + match (value) { + case "a" { + return 1; + } + default { + return 0; + } } } "#, @@ -2286,18 +2290,18 @@ fn contract_local_string_and_integer_adts_remain_runtime_types() { let diagnostics = lowered_module_typeck_diagnostics( r#" contract RuntimeNames { - data string = RuntimeString(word); - data integer = RuntimeInteger(word); + enum string {RuntimeString(word)} + enum integer {RuntimeInteger(word)} - function takesString(value: string) -> () { + function takesString(value: string) returns () { return (); } - function takesInteger(value: integer) -> () { + function takesInteger(value: integer) returns () { return (); } - function exercise(value: word) -> () { + function exercise(value: word) returns () { takesString(string.RuntimeString(value)); takesInteger(integer.RuntimeInteger(value)); return (); @@ -2322,7 +2326,7 @@ fn inferred_string_let_records_comptime_obligation() { let module = parse_module( &db, r#" -function f() -> word { +function f() returns (word) { let message = "hello"; return 0; } @@ -2402,14 +2406,14 @@ fn scheme_instantiation_reuses_one_fresh_var_per_binder() { #[test] fn ambiguous_integer_literal_defaults_to_word() { let db = TestDb::default(); - let module = parse_module(&db, "function f() -> word { return 1; }"); + let module = parse_module(&db, "function f() returns (word) { return 1; }"); let (body, result) = infer_function(&db, module, "f"); assert!(result.diagnostics.is_empty()); let expr = return_expr(&db, body); assert_eq!(result.expr_ty(body, expr), Some(Ty::word(&db))); assert_eq!(result.obligations.len(), 1); - assert_eq!(result.obligations[0].pred.display(&db), "word:Int"); + assert_eq!(result.obligations[0].pred.display(&db), "word: Int"); } #[test] @@ -2418,17 +2422,17 @@ fn end_to_end_body_infers_word_arithmetic() { let module = parse_module( &db, r#" -class t:Add { - function add(l:t, r:t) -> t; +trait Add { + function add(l:t, r:t) returns (t) ; } -instance word:Add { - function add(l:word, r:word) -> word { +impl Add { + function add(l:word, r:word) returns (word) { return primAddWord(l, r); } } -function f(x: word) -> word { return x + 1; } +function f(x: word) returns (word) { return x + 1; } "#, ); let (body, result) = infer_function(&db, module, "f"); @@ -2447,7 +2451,7 @@ function f(x: word) -> word { return x + 1; } result .obligations .iter() - .any(|obligation| obligation.pred.display(&db) == "word:Int"), + .any(|obligation| obligation.pred.display(&db) == "word: Int"), "{:?}", result.obligations ); @@ -2459,13 +2463,13 @@ fn class_method_call_emits_obligation() { let module = parse_module( &db, r#" -forall a . class a: Enum { - function fromEnum(x : a) -> word; +trait Enum { + function fromEnum(x : a) returns (word) ; } -data Food = Curry | Beans | Other; +enum Food {Curry , Beans , Other} -function main() -> word { +function main() returns (word) { return Enum.fromEnum(Food.Beans); } "#, @@ -2476,7 +2480,7 @@ function main() -> word { result .obligations .iter() - .any(|obligation| obligation.pred.display(&db).contains(":Enum")), + .any(|obligation| obligation.pred.display(&db).contains(": Enum")), "expected Enum obligation, got {:?}", result.obligations ); @@ -2488,15 +2492,15 @@ fn pair_domains_preserve_source_call_arity_and_explicit_tuple_arguments() { let module = parse_module( &db, r#" -function call_zero(f : () -> word) -> word { +function call_zero(f : function() returns (word)) returns (word) { return f(); } -function call_pair(f : (word, bool) -> word, x : word, y : bool) -> word { +function call_pair(f : function(word, bool) returns (word), x : word, y : bool) returns (word) { return f(x, y); } -function call_tuple(f : ((word, bool)) -> word, x : (word, bool)) -> word { +function call_tuple(f : function((word, bool)) returns (word), x : (word, bool)) returns (word) { return f(x); } "#, @@ -2517,10 +2521,8 @@ fn class_method_local_forall_is_lowered_as_a_method_binder() { let module = parse_module( &db, r#" -forall b. -class b:IsA { - forall a. - function ais(p : (a,b)) -> a; +trait IsA { + function ais(p : (a, b)) returns (a) ; } "#, ); @@ -2564,15 +2566,12 @@ class b:IsA { fn method_local_forall_survives_instance_signature_soundness() { let diagnostics = lowered_module_typeck_diagnostics( r#" -forall b. -class b:IsA { - forall a. - function ais(x : a, witness : b) -> a; +trait IsA { + function ais(x : a, witness : b) returns (a) ; } -instance word:IsA { - forall a. - function ais(x : a, witness : word) -> a { +impl IsA { + function ais(x : a, witness : word) returns (a) { return x; } } @@ -2586,8 +2585,8 @@ instance word:IsA { fn builtin_str_instance_requires_from_string() { let (db, key) = db_with_main_typeck( r#" -data Wrapped = Wrapped(word); -instance Wrapped:Str {} +enum Wrapped {Wrapped(word)} +impl Str {} "#, ); let module = module_id_from_key(&db, &key); @@ -2607,9 +2606,9 @@ instance Wrapped:Str {} fn builtin_str_instance_rejects_unknown_methods() { let (db, key) = db_with_main_typeck( r#" -data Wrapped = Wrapped(word); -instance Wrapped:Str { - function unexpected(x:word) -> word { return x; } +enum Wrapped {Wrapped(word)} +impl Str { + function unexpected(x:word) returns (word) { return x; } } "#, ); @@ -2630,9 +2629,9 @@ instance Wrapped:Str { fn builtin_str_instance_rejects_wrong_from_string_signature() { let (db, key) = db_with_main_typeck( r#" -data Wrapped = Wrapped(word); -instance Wrapped:Str { - function fromString(s:word) -> Wrapped { return Wrapped(s); } +enum Wrapped {Wrapped(word)} +impl Str { + function fromString(s:word) returns (Wrapped) { return Wrapped(s); } } "#, ); @@ -2652,29 +2651,29 @@ instance Wrapped:Str { #[test] fn builtin_str_ground_instance_rejects_overlapping_source_instance() { let mut db = TestDb::default(); - let std_path = PathBuf::from("/std/std.solc"); - let main_path = PathBuf::from("/main/main.solc"); + let std_path = PathBuf::from("/std/std.sol"); + let main_path = PathBuf::from("/main/main.sol"); let std_file = source_file_at_path( &db, &std_path, r#" export { memory(*), string }; -data memory(a) = memory(word); -data string; +enum memory {memory(word)} +enum string {} "#, ); let main_file = source_file_at_path( &db, &main_path, r#" -import std.{*}; +import * from std; -instance string:Str { - function fromString(comptime value:string) -> string { return value; } +impl Str { + function fromString(comptime value:string) returns (string) { return value; } } -instance memory(string):Str { - function fromString(comptime value:string) -> memory(string) { +impl Str> { + function fromString(comptime value:string) returns (memory) { return Str.fromString(value); } } @@ -2710,17 +2709,25 @@ fn comptime_numeric_scrutinees_accept_integer_literal_patterns() { let module = parse_module( &db, r#" -function classify_word(comptime x : word) -> word { - match x { - | 0 => return 10; - | _ => return 20; +function classify_word(comptime x : word) returns (word) { + match (x) { + case 0 { + return 10; + } + default { + return 20; + } } } -function classify_integer(comptime x : integer) -> word { - match x { - | 0 => return 10; - | _ => return 20; +function classify_integer(comptime x : integer) returns (word) { + match (x) { + case 0 { + return 10; + } + default { + return 20; + } } } "#, @@ -2741,13 +2748,13 @@ fn unconstrained_phantom_constructor_result_is_ambiguous() { let module = parse_module( &db, r#" -data Foo(a) = Foo(word); +enum Foo {Foo(word)} -forall a . function read(x : Foo(a)) -> word { +function read(x : Foo) returns (word) { return 0; } -function main() -> word { +function main() returns (word) { return read(Foo(42)); } "#, @@ -2770,15 +2777,14 @@ fn payload_constrained_constructor_result_is_not_phantom() { let module = parse_module( &db, r#" -data Box(a) = Box(a); +enum Box {Box(a)} -forall a . function unwrap(x : Box(a)) -> a { - match x { - | Box(value) => return value; - } +function unwrap(x : Box) returns (a) { + match (x) { + case Box(value) { return value; }} } -function main() -> word { +function main() returns (word) { return unwrap(Box(42)); } "#, @@ -2794,9 +2800,9 @@ fn expected_type_constrains_phantom_constructor_result() { let module = parse_module( &db, r#" -data Foo(a) = Foo(word); +enum Foo {Foo(word)} -function main() -> Foo(word) { +function main() returns (Foo) { return Foo(42); } "#, @@ -2812,20 +2818,19 @@ fn storage_word_field_read_loads_as_word_without_context() { let module = parse_module( &db, r#" -data storage(t) = storage(word); +enum storage {storage(word)} -forall a b. -class a:CanStore(b) { - function store(r:a, v:b) -> (); - function load(r:a) -> b; +trait CanStore { + function store(r:a, v:b) returns () ; + function load(r:a) returns (b) ; } -instance storage(word):CanStore(word) { - function store(dst: storage(word), src: word) -> () { +impl CanStore,word> { + function store(dst: storage, src: word) returns () { return (); } - function load(src: storage(word)) -> word { + function load(src: storage) returns (word) { return 0; } } @@ -2835,7 +2840,7 @@ contract C { function get() { let x = value; -return x; +return (); } } "#, @@ -2860,22 +2865,21 @@ fn storage_string_field_read_loads_as_memory_string_without_context() { let module = parse_module( &db, r#" -data string; -data memory(t) = memory(word); -data storage(t) = storage(word); +enum string {} +enum memory {memory(word)} +enum storage {storage(word)} -forall a b. -class a:CanStore(b) { - function store(r:a, v:b) -> (); - function load(r:a) -> b; +trait CanStore { + function store(r:a, v:b) returns () ; + function load(r:a) returns (b) ; } -instance storage(string):CanStore(memory(string)) { - function store(dst: storage(string), src: memory(string)) -> () { +impl CanStore,memory> { + function store(dst: storage, src: memory) returns () { return (); } - function load(src: storage(string)) -> memory(string) { + function load(src: storage) returns (memory) { return memory(0); } } @@ -2885,7 +2889,7 @@ contract C { function get() { let x = value; -return x; +return (); } } "#, @@ -2912,29 +2916,28 @@ fn storage_mapping_assignment_records_concrete_base_ref_type() { let module = parse_module( &db, r#" -data mapping(index, member) = mapping(word); -data storage(t) = storage(word); +enum mapping {mapping(word)} +enum storage {storage(word)} -forall a b. -class a:CanStore(b) { - function store(r:a, v:b) -> (); - function load(r:a) -> b; +trait CanStore { + function store(r:a, v:b) returns () ; + function load(r:a) returns (b) ; } -instance storage(word):CanStore(word) { - function store(dst: storage(word), src: word) -> () { +impl CanStore,word> { + function store(dst: storage, src: word) returns () { return (); } - function load(src: storage(word)) -> word { + function load(src: storage) returns (word) { return 0; } } contract C { - m: mapping(word, word); + m: mapping(word => word); - function next() -> word { + function next() returns (word) { return 1; } @@ -2967,14 +2970,14 @@ fn constrained_function_call_records_call_site_evidence() { let module = parse_module( &db, r#" -data T = T; +enum T {T} -forall a . class a:C {} -instance T:C {} +trait C {} +impl C {} -forall a . a:C => function use(x: a) -> word { return 0; } +function use(x: a) returns (word) where a: C { return 0; } -function main(t: T) -> word { +function main(t: T) returns (word) { return use(t); } "#, @@ -3017,8 +3020,8 @@ fn trait_solver_rejects_unproductive_instance_cycle() { let module = parse_module( &db, r#" -forall a . class a:C {} -forall a . a:C => instance a:C {} +trait C {} +impl C where a: C {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3039,8 +3042,8 @@ fn tabled_solver_cycle_saturates_without_fuel_diagnostic() { let module = parse_module( &db, r#" -forall a . class a:C {} -forall a . a:C => instance a:C {} +trait C {} +impl C where a: C {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3060,15 +3063,15 @@ forall a . a:C => instance a:C {} r#" pragma no-patterson-condition C; -forall a . class a:C {} +trait C {} -forall a . a:C => instance a:C {} +impl C where a: C {} -forall a . a:C => function needsC(x:a) -> () { +function needsC(x:a) returns () where a: C { return (); } -function main(x: word) -> () { +function main(x: word) returns () { return needsC(x); } "#, @@ -3087,11 +3090,11 @@ fn tabled_solver_mutual_recursion_saturates_without_answers() { let module = parse_module( &db, r#" -forall a . class a:C {} -forall a . class a:D {} +trait C {} +trait D {} -forall a . a:D => instance a:C {} -forall a . a:C => instance a:D {} +impl C where a: D {} +impl D where a: C {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3116,16 +3119,16 @@ fn tabled_solver_shares_diamond_subgoals() { let module = parse_module( &db, r#" -forall a . class a:Leaf {} -forall a . class a:Left {} -forall a . class a:Right {} -forall a . class a:Top {} +trait Leaf {} +trait Left {} +trait Right {} +trait Top {} -instance word:Leaf {} +impl Leaf {} -forall a . a:Leaf => instance a:Left {} -forall a . a:Leaf => instance a:Right {} -forall a . a:Left, a:Right => instance a:Top {} +impl Left where a: Leaf {} +impl Right where a: Leaf {} +impl Top where a: Left, a: Right {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3154,18 +3157,18 @@ fn tabled_solver_shares_alpha_equivalent_flexible_subgoals() { let module = parse_module( &db, r#" -data Pair(a, b) = Pair(a, b); +enum Pair {Pair(a, b)} -forall a . class a:Leaf {} -forall a . class a:Left {} -forall a . class a:Right {} -forall a . class a:Top {} +trait Leaf {} +trait Left {} +trait Right {} +trait Top {} -forall a . instance a:Leaf {} +impl Leaf {} -forall a b c . Pair(b, c):Leaf => instance a:Left {} -forall a c b . Pair(b, c):Leaf => instance a:Right {} -forall a . a:Left, a:Right => instance a:Top {} +impl Left where Pair: Leaf {} +impl Right where Pair: Leaf {} +impl Top where a: Left, a: Right {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3195,12 +3198,12 @@ fn tabled_solver_dedups_replayed_identical_answer() { let module = parse_module( &db, r#" -forall a . class a:Seed {} -forall a . class a:Derived {} +trait Seed {} +trait Derived {} -instance word:Seed {} +impl Seed {} -forall a . a:Seed, a:Seed => instance a:Derived {} +impl Derived where a: Seed, a: Seed {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3228,14 +3231,14 @@ fn tabled_solver_replays_answers_to_late_consumers() { let module = parse_module( &db, r#" -forall a . class a:Seed {} -forall a . class a:Derived {} -forall a . class a:Needs {} +trait Seed {} +trait Derived {} +trait Needs {} -instance word:Seed {} +impl Seed {} -forall a . a:Seed => instance a:Derived {} -forall a . a:Seed, a:Derived => instance a:Needs {} +impl Derived where a: Seed {} +impl Needs where a: Seed, a: Derived {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3263,13 +3266,13 @@ fn trait_solver_resolves_recursive_pair_instance() { let module = parse_module( &db, r#" -data Pair(a, b) = Pair(a, b); +enum Pair {Pair(a, b)} -forall a . class a:StorageSize {} +trait StorageSize {} -instance word:StorageSize {} +impl StorageSize {} -forall a b . a:StorageSize, b:StorageSize => instance Pair(a, b):StorageSize {} +impl StorageSize> where a: StorageSize, b: StorageSize {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3303,22 +3306,22 @@ fn trait_solver_prefilters_only_heads_that_cannot_unify() { let module = parse_module( &db, r#" -forall a . class a:Target {} -forall a . class a:Noise {} -forall a . class a:DefaultTarget {} -forall a . class a:GenericTarget {} -forall a . class a:GivenTarget {} -forall a . class a:Parent {} -forall a . a:Parent => class a:Child {} -forall a . class a:AmbiguousTarget {} +trait Target {} +trait Noise {} +trait DefaultTarget {} +trait GenericTarget {} +trait GivenTarget {} +trait Parent {} +trait Child where a: Parent {} +trait AmbiguousTarget {} -instance word:Target {} -instance bool:Noise {} -forall a . default instance a:Noise {} -forall a . default instance a:DefaultTarget {} -forall a . instance a:GenericTarget {} -instance word:AmbiguousTarget {} -instance word:AmbiguousTarget {} +impl Target {} +impl Noise {} +default impl Noise {} +default impl DefaultTarget {} +impl GenericTarget {} +impl AmbiguousTarget {} +impl AmbiguousTarget {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3408,7 +3411,7 @@ fn trait_solver_preserves_comptime_transparent_fixed_local_given() { let module = parse_module( &db, r#" -forall abs rep . class abs:Typedef(rep) {} +trait Typedef {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3442,12 +3445,12 @@ fn trait_solver_preserves_rigid_origin_across_nested_goal_canonicalization() { let module = parse_module( &db, r#" -data Wrap(a) = Wrap(a); +enum Wrap {Wrap(a)} -forall self rep . class self:Foo(rep) {} -forall self rep . class self:Bar(rep) {} +trait Foo {} +trait Bar {} -forall a rep . a:Foo(rep) => instance Wrap(a):Bar(rep) {} +impl Bar,rep> where a: Foo {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3500,20 +3503,18 @@ fn inference_improves_multi_parameter_result_through_local_given() { let module = parse_module( &db, r#" -data Wrap(a) = Wrap(a); +enum Wrap {Wrap(a)} -forall self rep . class self:Foo(rep) {} -forall self rep . class self:Bar(rep) {} +trait Foo {} +trait Bar {} -forall a rep . a:Foo(rep) => instance Wrap(a):Bar(rep) {} +impl Bar,rep> where a: Foo {} -forall a rep . Wrap(a):Bar(rep) => -function need_bar(x:Wrap(a)) -> () { +function need_bar(x:Wrap) returns () where Wrap: Bar { return (); } -forall a . a:Foo(word) => -function use_bar(x:Wrap(a)) -> () { +function use_bar(x:Wrap) returns () where a: Foo { need_bar(x); return (); } @@ -3544,8 +3545,8 @@ fn trait_solver_prefilter_preserves_comptime_correlated_instance_head() { let module = parse_module( &db, r#" -forall a . class a:Correlated {} -forall x . instance (comptime x, x):Correlated {} +trait Correlated {} +impl Correlated<(comptime, x)> {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3578,9 +3579,9 @@ fn trait_solver_prefers_specific_instance_over_default() { let module = parse_module( &db, r#" -forall a . class a:Test {} -forall a . default instance a:Test {} -instance word:Test {} +trait Test {} +default impl Test {} +impl Test {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3617,13 +3618,13 @@ fn trait_solver_uses_default_instance_for_non_default_clause_condition() { let module = parse_module( &db, r#" -data Wrap(a) = Wrap(a); +enum Wrap {Wrap(a)} -forall a . class a:DefaultDependency {} -forall a . default instance a:DefaultDependency {} +trait DefaultDependency {} +default impl DefaultDependency {} -forall a . class a:Outer {} -forall a . a:DefaultDependency => instance Wrap(a):Outer {} +trait Outer {} +impl Outer> where a: DefaultDependency {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3669,9 +3670,9 @@ fn trait_solver_reports_overlapping_non_default_instances_as_ambiguous() { let module = parse_module( &db, r#" -forall a . class a:C {} -instance word:C {} -instance word:C {} +trait C {} +impl C {} +impl C {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3695,14 +3696,14 @@ fn trait_solver_keeps_distinct_substitutions_from_the_same_instance() { let module = parse_module( &db, r#" -data Pair(a, b) = Pair(a, b); +enum Pair {Pair(a, b)} -forall a r . class a:D(r) {} -forall a . default instance a:D(word) {} -forall a . default instance a:D(bool) {} +trait D {} +default impl D {} +default impl D {} -forall a . class a:C {} -forall a r . a:D(r) => instance Pair(a, r):C {} +trait C {} +impl C> where a: D {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3738,15 +3739,15 @@ fn trait_solver_unifies_weak_class_args_across_conditions() { let module = parse_module( &db, r#" -data Uint = Uint(word); +enum Uint {Uint(word)} -forall abs rep . class abs:Typedef(rep) {} -instance Uint:Typedef(word) {} +trait Typedef {} +impl Typedef {} -forall a . class a:StorageSize {} -instance word:StorageSize {} +trait StorageSize {} +impl StorageSize {} -forall a b . a:Typedef(b), b:StorageSize => instance a:StorageSize {} +impl StorageSize where a: Typedef, b: StorageSize {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3776,9 +3777,9 @@ fn default_instance_is_blocked_by_unifying_normal_head() { let module = parse_module( &db, r#" -forall a . class a:C {} -instance word:C {} -forall a . default instance a:C {} +trait C {} +impl C {} +default impl C {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3798,25 +3799,25 @@ forall a . default instance a:C {} #[test] fn imported_class_origin_contributes_superclass_clauses() { let mut db = TestDb::default(); - let lib_path = PathBuf::from("/main/lib.solc"); - let main_path = PathBuf::from("/main/main.solc"); + let lib_path = PathBuf::from("/main/lib.sol"); + let main_path = PathBuf::from("/main/main.sol"); let lib_file = source_file_at_path( &db, &lib_path, r#" export { Eq, Ord }; -forall a . class a:Eq {} -forall a . a:Eq => class a:Ord {} +trait Eq {} +trait Ord where a: Eq {} "#, ); let main_file = source_file_at_path( &db, &main_path, r#" -import lib.{Eq, Ord}; +import {Eq, Ord} from lib; -instance word:Ord {} +impl Ord {} "#, ); let lib_key = module_key_for_path(LibraryId::Main, &PathBuf::from("/main"), &lib_path).unwrap(); @@ -3850,23 +3851,23 @@ instance word:Ord {} #[test] fn trait_env_from_module_resolution_and_imports_deduplicates_superclass_modules() { let mut db = TestDb::default(); - let lib_path = PathBuf::from("/main/lib.solc"); - let main_path = PathBuf::from("/main/main.solc"); + let lib_path = PathBuf::from("/main/lib.sol"); + let main_path = PathBuf::from("/main/main.sol"); let lib_file = source_file_at_path( &db, &lib_path, r#" export { Parent, Child }; -forall a . class a:Parent {} -forall a . a:Parent => class a:Child {} +trait Parent {} +trait Child where a: Parent {} "#, ); let main_file = source_file_at_path( &db, &main_path, r#" -import lib.{Parent, Child}; +import {Parent, Child} from lib; "#, ); let lib_key = module_key_for_path(LibraryId::Main, &PathBuf::from("/main"), &lib_path).unwrap(); @@ -3905,9 +3906,9 @@ fn superclass_solution_records_projection_evidence() { let module = parse_module( &db, r#" -forall a . class a:Eq {} -forall a . a:Eq => class a:Ord {} -instance word:Ord {} +trait Eq {} +trait Ord where a: Eq {} +impl Ord {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3939,10 +3940,10 @@ fn direct_instance_precedes_superclass_projection() { let module = parse_module( &db, r#" -forall a . class a:Eq {} -forall a . a:Eq => class a:Ord {} -instance word:Eq {} -instance word:Ord {} +trait Eq {} +trait Ord where a: Eq {} +impl Eq {} +impl Ord {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -3971,9 +3972,9 @@ fn local_givens_and_superclasses_precede_global_instances() { let module = parse_module( &db, r#" -forall a . class a:Eq {} -forall a . a:Eq => class a:Ord {} -instance word:Eq {} +trait Eq {} +trait Ord where a: Eq {} +impl Eq {} "#, ); let module_resolution = hir_nameres::resolve_module(&db, module); @@ -4014,12 +4015,12 @@ fn pragma_corpus_files_have_no_instance_soundness_diagnostics() { let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let corpus = manifest.join("../parser/tests/fixtures/corpus"); let files = [ - "pragmas/coverage.solc", - "cases/array.solc", - "cases/bound-with-pragma.solc", - "cases/tabled-left-recursive-fail.solc", - "cases/tabled-cycle-fail.solc", - "cases/mptc-partial-instance.solc", + "pragmas/coverage.sol", + "cases/array.sol", + "cases/bound-with-pragma.sol", + "cases/tabled-left-recursive-fail.sol", + "cases/tabled-cycle-fail.sol", + "cases/mptc-partial-instance.sol", ]; for file in files { @@ -4048,9 +4049,9 @@ fn pragma_corpus_files_have_no_instance_soundness_diagnostics() { fn structured_default_instance_head_is_allowed_only_when_it_contains_a_type_variable() { let (db, key) = db_with_main_typeck( r#" -data Box(a) = Box(a); -forall a . class a:Marker {} -forall a . default instance Box(a):Marker {} +enum Box {Box(a)} +trait Marker {} +default impl Marker> {} "#, ); let module_id = module_id_from_key(&db, &key); @@ -4065,9 +4066,9 @@ forall a . default instance Box(a):Marker {} let (db, key) = db_with_main_typeck( r#" -data Box(a) = Box(a); -forall a . class a:Marker {} -default instance Box(word):Marker {} +enum Box {Box(a)} +trait Marker {} +default impl Marker> {} "#, ); let module_id = module_id_from_key(&db, &key); diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 65bfdff0..403a93bf 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -446,7 +446,7 @@ impl<'db> TypeLowering<'db> { hir_nameres::Resolution::Def { def, kind: hir_nameres::DefResolutionKind::Class, - } => Some(def.name(self.db).unwrap_or_else(|| "class".to_owned())), + } => Some(def.name(self.db).unwrap_or_else(|| "trait".to_owned())), _ => None, } } diff --git a/crates/hir-ty/src/prepare.rs b/crates/hir-ty/src/prepare.rs index 95473a2e..74a47c91 100644 --- a/crates/hir-ty/src/prepare.rs +++ b/crates/hir-ty/src/prepare.rs @@ -1664,9 +1664,9 @@ mod tests { std_root.clone(), BTreeMap::new(), )); - let main_path = main_root.join("main.solc"); - let std_path = std_root.join("std.solc"); - let dispatch_path = std_root.join("dispatch.solc"); + let main_path = main_root.join("main.sol"); + let std_path = std_root.join("std.sol"); + let dispatch_path = std_root.join("dispatch.sol"); db.module_fs_snapshot = Some(ModuleFsSnapshot::new( &db, BTreeSet::from([main_path.clone(), std_path.clone(), dispatch_path.clone()]), @@ -1739,8 +1739,8 @@ mod tests { #[test] fn preserves_source_and_builds_effective_dispatch_overlay() { let src = r#" -import std.dispatch.{*}; -contract C { public function answer(x:uint256) -> uint256 { return x; } } +import * from std.dispatch; +contract C { function answer(x: uint256) public returns (uint256) { return x; } } "#; let (db, file) = db_with_main(src); let source = source_module(&db, file); @@ -1772,8 +1772,8 @@ contract C { public function answer(x:uint256) -> uint256 { return x; } } #[test] fn preparation_preserves_contract_and_field_comments() { let src = r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // contract documentation contract C { // stored value documentation @@ -1781,7 +1781,7 @@ contract C { // constructor documentation constructor() {} // method documentation - public function answer(x:uint256) -> uint256 { return x; } + function answer(x:uint256) public returns (uint256) { return x; } } "#; let (db, file) = db_with_main(src); @@ -1872,7 +1872,7 @@ contract C { #[test] fn runtime_dispatch_is_implicit_and_existing_main_suppresses_it() { let (db, file) = db_with_main( - "contract C { public function answer() -> uint256 { return uint256(1); } }", + "contract C { function answer() public returns (uint256) { return uint256(1); } }", ); let source = source_module(&db, file); let prepared = prepare_module(&db, source); @@ -1891,8 +1891,8 @@ contract C { let (db, file) = db_with_main( r#" -import std.dispatch.{*}; -contract C { function main() -> () {} } +import * from std.dispatch; +contract C { function main() {} } "#, ); let source = source_module(&db, file); @@ -1913,8 +1913,7 @@ contract C { function main() -> () {} } #[test] fn nonempty_constructor_is_prepared_without_injecting_imports() { - let (db, file) = - db_with_main("contract C { constructor(x:word) {} function main() -> () {} }"); + let (db, file) = db_with_main("contract C { constructor(x:word) {} function main() {} }"); let source = source_module(&db, file); let prepared = prepare_module(&db, source); assert_ne!(prepared.module(&db), source); @@ -1933,11 +1932,11 @@ contract C { function main() -> () {} } fn constructor_overlay_preserves_source_and_generates_deployment_entry() { let (db, file) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - payable constructor(x:word, y:word) { let z = x; } - function main() -> () { return (); } + constructor(x:word, y:word) payable { let z = x; } + function main() returns () { return (); } } "#, ); @@ -1990,10 +1989,10 @@ contract C { fn explicit_constructor_overlay_is_idempotent() { let (db, file) = db_with_main( r#" -import std.{*}; +import * from std; contract C { - payable constructor(x:word) { let saved = x; } - function main() -> () { return (); } + constructor(x:word) payable { let saved = x; } + function main() returns () { return (); } } "#, ); @@ -2030,19 +2029,19 @@ contract C { #[test] fn constructor_body_edit_keeps_generated_wrapper_identity() { let before = r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor(x:word) { let z = 1; } - function main() -> () { return (); } + function main() returns () { return (); } } "#; let after = r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor(x:word) { let z = 2; } - function main() -> () { return (); } + function main() returns () { return (); } } "#; let (mut db, file) = db_with_main(before); @@ -2084,10 +2083,10 @@ contract C { fn deduplicates_overloaded_method_name_declarations() { let (db, file) = db_with_main( r#" -import std.dispatch.{*}; +import * from std.dispatch; contract C { - public function get(x:uint256) -> uint256 { return x; } - public function get(x:bool) -> bool { return x; } + function get(x:uint256) public returns (uint256) { return x; } + function get(x:bool) public returns (bool) { return x; } } "#, ); @@ -2108,12 +2107,12 @@ contract C { fn dispatch_name_types_are_injective_across_contract_method_boundaries() { let (db, file) = db_with_main( r#" -import std.dispatch.{*}; +import * from std.dispatch; contract A { - public function B_C(x:uint256) -> uint256 { return x; } + function B_C(x:uint256) public returns (uint256) { return x; } } contract A_B { - public function C(x:uint256) -> uint256 { return x; } + function C(x:uint256) public returns (uint256) { return x; } } "#, ); @@ -2150,12 +2149,12 @@ contract A_B { #[test] fn omitted_return_uses_unit_and_body_edit_keeps_generated_identity() { let before = r#" -import std.dispatch.{*}; -contract C { public function ping() { let x = 1; } } +import * from std.dispatch; +contract C { function ping() public { let x = 1; } } "#; let after = r#" -import std.dispatch.{*}; -contract C { public function ping() { let x = 2; } } +import * from std.dispatch; +contract C { function ping() public { let x = 2; } } "#; let (mut db, file) = db_with_main(before); let source = source_module(&db, file); diff --git a/crates/hir-ty/src/solver/derived_class.rs b/crates/hir-ty/src/solver/derived_class.rs index 10ed2eab..841d8fda 100644 --- a/crates/hir-ty/src/solver/derived_class.rs +++ b/crates/hir-ty/src/solver/derived_class.rs @@ -109,7 +109,7 @@ pub(crate) fn class_derivation_diagnostics<'db>( span, ty, class: class_name, - reason: "only single-parameter classes can be derived".to_owned(), + reason: "only single-parameter traits can be derived".to_owned(), }); continue; } @@ -118,7 +118,7 @@ pub(crate) fn class_derivation_diagnostics<'db>( span, ty, class: class_name, - reason: "a contract-local data type cannot capture generic contract parameters" + reason: "a contract-local enum cannot capture generic contract parameters" .to_owned(), }); } diff --git a/crates/hir-ty/src/solver/derived_storage.rs b/crates/hir-ty/src/solver/derived_storage.rs index f708f943..29ab02ea 100644 --- a/crates/hir-ty/src/solver/derived_storage.rs +++ b/crates/hir-ty/src/solver/derived_storage.rs @@ -11,7 +11,7 @@ pub(super) struct DerivedStorageClauseSource<'db> { pub storage_size: DefId<'db>, /// `CanStore` class. pub can_store: DefId<'db>, - /// `storage(ty)` data type. + /// `storage` data type. pub storage: DefId<'db>, } @@ -25,7 +25,7 @@ pub(super) fn visible_storage_clause_source<'db>( /// Builds the storage obligation carried by a contract field declaration. /// -/// A field is addressed uniformly through `storage(field_ty)`, but mappings +/// A field is addressed uniformly through `storage`, but mappings /// and storage arrays load back as slot handles while strings and bytes load /// into memory. Keeping this distinction here mirrors expression inference /// and, importantly, makes an otherwise-unused ADT field validate the body of @@ -338,7 +338,7 @@ fn adt_named<'db>(db: &'db dyn Db, def: DefId<'db>, name: &str) -> Option<()> { } /// Adds the concrete `T:StorageSize` and -/// `storage(T):CanStore(T)` clauses emitted by upstream DeriveGeneric. +/// `storage: CanStore` clauses emitted by upstream DeriveGeneric. pub(super) fn push_derived_storage_clauses<'db>( db: &'db dyn Db, clauses: &mut Vec>, diff --git a/crates/hir-ty/src/solver/display.rs b/crates/hir-ty/src/solver/display.rs index b6d687a4..79507750 100644 --- a/crates/hir-ty/src/solver/display.rs +++ b/crates/hir-ty/src/solver/display.rs @@ -23,18 +23,18 @@ pub(super) fn display_scheme_source<'db>( .map(|pred| display_pred_source(db, *pred, &names)) .collect::>(); let ty = display_ty_source(db, body.ty(db), &names); - let qualified = if preds.is_empty() { + let mut displayed = if scheme.binder_count(db) == 0 { ty - } else { - format!("{} => {ty}", preds.join(", ")) - }; - if scheme.binder_count(db) == 0 { - qualified } else { let vars = (0..scheme.binder_count(db)) .map(|index| display_var_name(index, &names)) .collect::>() .join(", "); - format!("forall {vars}. {qualified}") + format!("<{vars}> {ty}") + }; + if !preds.is_empty() { + displayed.push_str(" where "); + displayed.push_str(&preds.join(", ")); } + displayed } diff --git a/crates/hir-ty/src/solver/evidence.rs b/crates/hir-ty/src/solver/evidence.rs index b3b9ef98..e765434f 100644 --- a/crates/hir-ty/src/solver/evidence.rs +++ b/crates/hir-ty/src/solver/evidence.rs @@ -19,10 +19,10 @@ impl<'db> Evidence<'db> { .collect::>() .join(", "); if sub_evidence.is_empty() { - format!("instance {name}({args})") + format!("impl {name}<{args}>") } else { format!( - "instance {name}({args}) with {} subproof(s)", + "impl {name}<{args}> with {} subproof(s)", sub_evidence.len() ) } @@ -34,7 +34,7 @@ impl<'db> Evidence<'db> { .filter(|name| !name.is_empty()) .unwrap_or_else(|| format!("{:?}", class.kind(db))); format!( - "superclass {name} => {} via {}", + "supertrait {name}: {} via {}", pred.display(db), child.display(db) ) diff --git a/crates/hir-ty/src/solver/mod.rs b/crates/hir-ty/src/solver/mod.rs index 5a4c0d25..e3b1bafd 100644 --- a/crates/hir-ty/src/solver/mod.rs +++ b/crates/hir-ty/src/solver/mod.rs @@ -262,7 +262,7 @@ pub enum DerivedClauseKind<'db> { /// ADT whose storage-size instance was synthesized. adt: DefId<'db>, }, - /// Concrete `storage(T):CanStore(T)` instance. + /// Concrete `storage: CanStore` impl. CanStore { /// ADT whose storage instance was synthesized. adt: DefId<'db>, diff --git a/crates/hir-ty/src/solver/soundness.rs b/crates/hir-ty/src/solver/soundness.rs index b9bd0a88..5045a4e0 100644 --- a/crates/hir-ty/src/solver/soundness.rs +++ b/crates/hir-ty/src/solver/soundness.rs @@ -506,7 +506,7 @@ fn check_instance_methods<'db>( .class .def_id_value(db) .name(db) - .unwrap_or_else(|| "".to_owned()); + .unwrap_or_else(|| "".to_owned()); let methods = instance.methods(db); let method_names = methods .iter() @@ -691,7 +691,7 @@ fn check_builtin_str_method_signature<'db>( span: LabelSpan::from_span(db, method.sig(db).span(db)), method: METHOD_NAME.to_owned(), reason: format!( - "expected (string) -> {}, got {}", + "expected function(string) returns ({}), got {}", display_ty_source(db, *main, &inherited_names), display_ty_source(db, actual, &inherited_names) ), diff --git a/crates/hir-ty/src/support.rs b/crates/hir-ty/src/support.rs index 0bc11db6..13558620 100644 --- a/crates/hir-ty/src/support.rs +++ b/crates/hir-ty/src/support.rs @@ -22,7 +22,7 @@ pub(crate) fn canonical_std_adt_defs<'db>(db: &'db dyn Db, name: &str) -> Vec SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid url"); + let url = format!("memory:///{name}.sol").parse().expect("valid url"); SourceFile::new(db, url, Some(src.to_owned())) } @@ -126,8 +126,8 @@ fn db_with_main(src: &str) -> (TestDb, ModuleKey) { library: LibraryId::Main, logical_path: vec!["main".to_owned()], }; - let path = PathBuf::from("/main/main.solc"); - let file = source_file_at(&db, "/main/main.solc", src); + let path = PathBuf::from("/main/main.sol"); + let file = source_file_at(&db, "/main/main.sol", src); db.existing_files.insert(path); db.module_files.insert(key.clone(), file); db.sync_inputs(); @@ -143,45 +143,41 @@ fn insert_module_source(db: &mut TestDb, key: ModuleKey, path: &str, src: &str) fn insert_real_std_modules(db: &mut TestDb) { for (logical, path, source) in [ - ( - "std", - "/std/std.solc", - include_str!("../../../std/std.solc"), - ), + ("std", "/std/std.sol", include_str!("../../../std/std.sol")), ( "dispatch", - "/std/dispatch.solc", - include_str!("../../../std/dispatch.solc"), + "/std/dispatch.sol", + include_str!("../../../std/dispatch.sol"), ), ( "opcodes", - "/std/opcodes.solc", - include_str!("../../../std/opcodes.solc"), + "/std/opcodes.sol", + include_str!("../../../std/opcodes.sol"), ), ( "Generic", - "/std/Generic.solc", - include_str!("../../../std/Generic.solc"), + "/std/Generic.sol", + include_str!("../../../std/Generic.sol"), ), ( "ABIGeneric", - "/std/ABIGeneric.solc", - include_str!("../../../std/ABIGeneric.solc"), + "/std/ABIGeneric.sol", + include_str!("../../../std/ABIGeneric.sol"), ), ( "StorageGeneric", - "/std/StorageGeneric.solc", - include_str!("../../../std/StorageGeneric.solc"), + "/std/StorageGeneric.sol", + include_str!("../../../std/StorageGeneric.sol"), ), ( "eip712", - "/std/eip712.solc", - include_str!("../../../std/eip712.solc"), + "/std/eip712.sol", + include_str!("../../../std/eip712.sol"), ), ( "eip7951", - "/std/eip7951.solc", - include_str!("../../../std/eip7951.solc"), + "/std/eip7951.sol", + include_str!("../../../std/eip7951.sol"), ), ] { insert_module_source( @@ -285,7 +281,7 @@ fn yul_function_values_are_local_and_cannot_capture_sail_values() { "dynamic read", r#" contract C { - function main() -> word { + function main() returns (word) { let outer : word; assembly { outer := callvalue() @@ -301,7 +297,7 @@ contract C { "known write", r#" contract C { - function main() -> word { + function main() returns (word) { let outer : word = 7; assembly { function writeOuter() { outer := 9 } @@ -316,7 +312,7 @@ contract C { "outer Yul read", r#" contract C { - function main() -> word { + function main() returns (word) { let result : word; assembly { let outerYul := callvalue() @@ -342,7 +338,7 @@ contract C { let local = diagnostics( r#" contract C { - function main() -> word { + function main() returns (word) { let result : word; assembly { function localValue(input) -> output { @@ -364,7 +360,7 @@ fn yul_for_body_values_do_not_leak_into_the_post_block() { let diagnostics = diagnostics( r#" contract C { - function main() -> word { + function main() returns (word) { let result : word; assembly { let i := 0 @@ -395,7 +391,7 @@ fn generated_dispatch_is_synthesized_before_import_resolution() { &db, r#" contract Answer { - public function add(x: word) -> word { return x; } + function add(x: word) public returns (word) { return x; } } "#, ); @@ -414,7 +410,7 @@ contract Answer { &manual_db, r#" contract Answer { - function main() -> () { return (); } + function main() returns () { return (); } } "#, ); @@ -428,7 +424,7 @@ contract Answer { let parameterized_main = diagnostics( r#" contract Answer { - public function main(x: word) -> word { return x; } + function main(x: word) public returns (word) { return x; } } "#, ); @@ -444,11 +440,11 @@ contract Answer { fn prepared_dispatch_uses_its_synthetic_sigstring_instance_during_typeck() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Answer { - public function ping(x: word) -> word { return x; } + function ping(x: word) public returns (word) { return x; } } "#, ); @@ -458,11 +454,11 @@ contract Answer { library: LibraryId::Std, logical_path: vec!["std".to_owned()], }, - "/std/std.solc", + "/std/std.sol", r#" export { Proxy(*), string }; -data Proxy(t) = Proxy; -data string; +enum Proxy {Proxy} +enum string {} "#, ); insert_module_source( @@ -471,9 +467,9 @@ data string; library: LibraryId::Std, logical_path: vec!["dispatch".to_owned()], }, - "/std/dispatch.solc", + "/std/dispatch.sol", r#" -import std.{*}; +import * from std; export { Contract(*), @@ -486,31 +482,29 @@ export { fallback_default_implementation }; -data Contract(methods, fb) = Contract(methods, fb); -data Method(name, payability, args, rets, fn) = - Method(Proxy(name), Proxy(payability), Proxy(args), Proxy(rets), fn); -data Fallback(payability, args, rets, fn) = - Fallback(Proxy(payability), Proxy(args), Proxy(rets), fn); -data Payable; -data NonPayable; +enum Contract {Contract(methods, fb)} +enum Method {Method(Proxy, Proxy, Proxy, Proxy, fn)} +enum Fallback {Fallback(Proxy, Proxy, Proxy, fn)} +enum Payable {} +enum NonPayable {} -forall t . class t:SigString { - function sigStr(value: Proxy(t)) -> string; +trait SigString { + function sigStr(value: Proxy) returns (string) ; } -forall c . class c:RunContract { - function exec(value: c) -> (); +trait RunContract { + function exec(value: c) returns () ; } -forall name payability args rets fn fb - . name:SigString -=> instance Contract(Method(name, payability, args, rets, fn), fb):RunContract { - function exec(value: Contract(Method(name, payability, args, rets, fn), fb)) -> () { +impl + RunContract, fb>> + where name: SigString { + function exec(value: Contract, fb>) returns () { return (); } } -function fallback_default_implementation() -> () { return (); } +function fallback_default_implementation() returns () { return (); } "#, ); @@ -543,15 +537,15 @@ function fallback_default_implementation() -> () { return (); } fn dispatch_names_and_selectors_distinguish_contract_method_boundaries() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract A { - public function B_C(x:uint256) -> uint256 { return x; } + function B_C(x:uint256) public returns (uint256) { return x; } } contract A_B { - public function C(x:uint256) -> uint256 { return x; } + function C(x:uint256) public returns (uint256) { return x; } } "#, ); @@ -581,15 +575,15 @@ fn dispatch_surface_tracks_public_private_constructor_and_fallback() { &db, r#" contract Token { - payable constructor(amount: word) {} + constructor(amount: word) payable {} - function hidden(x: word) -> word { return x; } + function hidden(x: word) returns (word) { return x; } - public payable function pay(to: word) -> (word, bool) { + function pay(to: word) public payable returns ((word, bool)) { return (to, true); } - payable fallback() -> () {} + fallback() payable {} } "#, ); @@ -626,8 +620,8 @@ fn abi_json_matches_reference_public_function_shape() { &db, r#" contract Sample { - public function get() -> word { return 1; } - function secret() -> word { return 0; } + function get() public returns (word) { return 1; } + function secret() returns (word) { return 0; } } "#, ); @@ -663,7 +657,7 @@ fn abi_json_matches_reference_constructor_payable_and_tuple_outputs() { contract Token { constructor(amount: word) {} - public payable function pay(to: word) -> (word, bool) { + function pay(to: word) public payable returns ((word, bool)) { return (to, true); } } @@ -685,10 +679,10 @@ fn abi_json_preserves_source_declaration_order() { &db, r#" contract Order { - public function a() -> word { return 1; } + function a() public returns (word) { return 1; } constructor(seed: word) {} - payable fallback() -> () {} - public function b(x: word) -> word { return x; } + fallback() payable {} + function b(x: word) public returns (word) { return x; } } "#, ); @@ -718,7 +712,7 @@ type UnitAlias = (); contract AliasDispatch { constructor(seed: U) {} - fallback() -> UnitAlias {} + fallback() {} } "#, ); @@ -747,20 +741,12 @@ contract AliasDispatch { fn dispatch_signature_spelling_matches_reference_sigstring_shape() { let (mut db, key) = db_with_main( r#" -import std.{*}; +import * from std; type U = word; contract Signatures { - public function spell( - a: word, - b: (word, bool), - c: memory(string), - d: memory(bytes), - e: bytes32, - f: address, - g: U - ) -> word { + function spell(a: word, b: (word, bool), c: memory, d: memory, e: bytes32, f: address, g: U) public returns (word) { return a; } } @@ -772,14 +758,14 @@ contract Signatures { library: LibraryId::Std, logical_path: vec!["std".to_owned()], }, - "/std/std.solc", + "/std/std.sol", r#" export { string, address(*), bytes, bytes32(*), memory(*) }; -data string; -data address = address(word); -data bytes; -data bytes32 = bytes32(word); -data memory(t) = memory(word); +enum string {} +enum address {address(word)} +enum bytes {} +enum bytes32 {bytes32(word)} +enum memory {memory(word)} "#, ); let file = db.module_files[&key]; @@ -797,10 +783,10 @@ data memory(t) = memory(word); fn bytes4_is_supported_by_the_e136_public_abi_surface() { let (mut db, key) = db_with_main( r#" -import std.{*}; +import * from std; contract Bytes4Echo { - public function echo(value: bytes4) -> bytes4 { return value; } + function echo(value: bytes4) public returns (bytes4) { return value; } } "#, ); @@ -832,14 +818,14 @@ contract Bytes4Echo { fn calldata_array_abi_uses_generic_signature_and_source_adt_json_name() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Operation = Approve(uint256) | Reject(uint256); +enum Operation {Approve(uint256) , Reject(uint256)} contract Batch { - public function count(ops: calldata(array(Operation))) -> uint256 { + function count(ops: calldata>) public returns (uint256) { return uint256(0); } } @@ -874,10 +860,10 @@ contract Batch { fn calldata_tuple_array_json_preserves_components_and_runtime_sigstring_shape() { let (mut db, key) = db_with_main( r#" -import std.{*}; +import * from std; contract Tuples { - public function first(values: calldata(array((uint256, address)))) -> uint256 { + function first(values: calldata>) public returns (uint256) { return uint256(0); } } @@ -906,12 +892,10 @@ contract Tuples { fn nested_calldata_arrays_recurse_in_signatures_and_abi_json() { let (mut db, key) = db_with_main( r#" -import std.{*}; +import * from std; contract NestedArrays { - public function first( - values: calldata(array(calldata(array(uint256)))) - ) -> uint256 { + function first(values: calldata>>>) public returns (uint256) { return uint256(0); } } @@ -944,12 +928,10 @@ contract NestedArrays { fn calldata_arrays_are_rejected_from_nested_output_positions() { let (mut db, key) = db_with_main( r#" -import std.{*}; +import * from std; contract InputOnly { - public function keep( - values: calldata(array(uint256)) - ) -> (uint256, calldata(array(uint256))) { + function keep(values: calldata>) public returns (uint256, calldata>) { return (uint256(0), values); } } @@ -970,7 +952,7 @@ contract InputOnly { diagnostic.code.as_deref() == Some("SC0231") && diagnostic .message - .contains("calldata(array(t)) is input-only") + .contains("calldata> is input-only") && diagnostic.message.contains("no ABIEncode evidence") })); assert!(contract_abi_json(&db, module, contract).is_err()); @@ -980,15 +962,15 @@ contract InputOnly { fn calldata_array_signature_recurses_through_nested_derived_generic_reps() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Inner = Number(uint256) | Account(address); -data Outer = Outer(Inner, bytes32); +enum Inner {Number(uint256) , Account(address)} +enum Outer {Outer(Inner, bytes32)} contract Nested { - public function inspect(values: calldata(array(Outer))) -> uint256 { + function inspect(values: calldata>) public returns (uint256) { return uint256(0); } } @@ -1012,25 +994,25 @@ contract Nested { fn calldata_array_supports_parameterized_and_rejects_recursive_and_manual_generic_adts() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Box(a) = Box(a); -data Node = Node(uint256, Node); +enum Box {Box(a)} +enum Node {Node(uint256, Node)} pragma no-generic-instance-for Manual; -data Manual = Left(uint256) | Right(uint256); -instance Manual:Generic(sum(uint256, uint256)) {} +enum Manual {Left(uint256) , Right(uint256)} +impl Generic> {} contract Rejected { - public function boxed(values: calldata(array(Box(uint256)))) -> uint256 { + function boxed(values: calldata>>) public returns (uint256) { return uint256(0); } - public function recursive(values: calldata(array(Node))) -> uint256 { + function recursive(values: calldata>) public returns (uint256) { return uint256(0); } - public function manual(values: calldata(array(Manual))) -> uint256 { + function manual(values: calldata>) public returns (uint256) { return uint256(0); } } @@ -1046,7 +1028,7 @@ contract Rejected { assert_eq!(surface.methods[0].signature, "boxed(uint256[])"); assert_eq!( surface.methods[0].inputs[0].ty.to_string(), - "Box(uint256)[]" + "Box[]" ); assert!(surface.methods[1..].iter().all(|method| { method.signature.ends_with("()") @@ -1070,16 +1052,16 @@ contract Rejected { fn visible_orphan_generic_instance_rejects_calldata_adt_array_surface() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; -import model.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; +import * from model; -instance Payload:Generic(word) {} +impl Generic {} contract C { - public function inspect(values:calldata(array(Payload))) -> uint256 { + function inspect(values:calldata>) public returns (uint256) { return uint256(0); } } @@ -1092,13 +1074,13 @@ contract C { library: LibraryId::Main, logical_path: vec!["model".to_owned()], }, - "/main/model.solc", + "/main/model.sol", r#" -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; export { Payload(*) }; -data Payload = Left(uint256) | Right(uint256); +enum Payload {Left(uint256) , Right(uint256)} "#, ); @@ -1122,11 +1104,11 @@ fn same_named_user_calldata_and_array_types_do_not_gain_abi_meaning() { let module = parse_module( &db, r#" -data array(a) = array(word); -data calldata(a) = calldata(word); +enum array {array(word)} +enum calldata {calldata(word)} contract Fake { - public function inspect(values: calldata(array(word))) -> word { + function inspect(values: calldata>) public returns (word) { return 0; } } @@ -1144,14 +1126,14 @@ contract Fake { fn parameterized_single_constructor_adt_uses_its_generic_rep_in_the_public_abi() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Point(a) = Point(a, bool); +enum Point {Point(a, bool)} contract Shapes { - public function roundtrip(p: Point(uint256)) -> Point(uint256) { return p; } + function roundtrip(p: Point) public returns (Point) { return p; } } "#, ); @@ -1171,32 +1153,32 @@ contract Shapes { ); let method = &surface.methods[0]; assert_eq!(method.signature, "roundtrip(uint256,bool)"); - assert_eq!(method.inputs[0].ty.to_string(), "Point(uint256)"); - assert_eq!(method.outputs[0].ty.to_string(), "Point(uint256)"); + assert_eq!(method.inputs[0].ty.to_string(), "Point"); + assert_eq!(method.outputs[0].ty.to_string(), "Point"); let abi = contract_abi_json(&db, module, contract).expect("direct parameterized ADT ABI"); assert!( - abi.contains("\"internalType\": \"Point(uint256)\""), + abi.contains("\"internalType\": \"Point\""), "{abi}" ); - assert!(abi.contains("\"type\": \"Point(uint256)\""), "{abi}"); + assert!(abi.contains("\"type\": \"Point\""), "{abi}"); } #[test] fn nested_parameterized_adt_instantiations_are_finite_but_recursive_plans_are_rejected() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Box(a) = Box(a); -data Node = Node(Node); +enum Box {Box(a)} +enum Node {Node(Node)} contract Finite { - public function roundtrip(value:Box(Box(uint256))) -> Box(Box(uint256)) { return value; } + function roundtrip(value:Box>) public returns (Box>) { return value; } } contract Recursive { - public function recursive(value:Node) -> Node { return value; } + function recursive(value:Node) public returns (Node) { return value; } } "#, ); @@ -1209,14 +1191,14 @@ contract Recursive { assert_eq!(surface.methods[0].signature, "roundtrip(uint256)"); assert_eq!( surface.methods[0].inputs[0].ty.to_string(), - "Box(Box(uint256))" + "Box>" ); assert_eq!( surface.methods[0].outputs[0].ty.to_string(), - "Box(Box(uint256))" + "Box>" ); let abi = contract_abi_json(&db, module, finite).expect("finite nested ADT ABI"); - assert!(abi.contains("\"type\": \"Box(Box(uint256))\""), "{abi}"); + assert!(abi.contains("\"type\": \"Box>\""), "{abi}"); let recursive = contract_named(&db, module, "Recursive"); let surface = contract_dispatch_surface(&db, module, recursive); @@ -1235,17 +1217,17 @@ contract Recursive { fn phantom_adt_type_arguments_must_be_supported_by_the_derived_abi_context() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Phantom(a) = Phantom(uint256); +enum Phantom {Phantom(uint256)} contract PhantomAbi { - public function take(value:Phantom(mapping(uint256, uint256))) -> uint256 { + function take(value:Phantom uint256)>) public returns (uint256) { return uint256(0); } - public function make() -> Phantom(mapping(uint256, uint256)) { + function make() public returns (Phantom uint256)>) { return Phantom(uint256(0)); } } From d562c441c3cf7de4ed4da407f00a999f288775bf Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 036/110] Switch the compiler and fixtures to canonical syntax: hir ty Co-authored-by: Codex --- crates/hir-ty/tests/contract_semantics.rs | 197 +++++++++--------- crates/hir-ty/tests/derived_abi_solver.rs | 43 ++-- crates/hir-ty/tests/derived_class_solver.rs | 28 +-- crates/hir-ty/tests/derived_storage_solver.rs | 20 +- crates/hir-ty/tests/frontend_smoke.rs | 32 +-- crates/hir-ty/tests/incremental_cache.rs | 102 +++++---- crates/hir-ty/tests/ok_fixtures.rs | 2 +- crates/hir-ty/tests/properties.rs | 7 +- crates/hir-ty/tests/scheme_cycle.rs | 10 +- 9 files changed, 208 insertions(+), 233 deletions(-) diff --git a/crates/hir-ty/tests/contract_semantics.rs b/crates/hir-ty/tests/contract_semantics.rs index 1b59c34f..e62e4218 100644 --- a/crates/hir-ty/tests/contract_semantics.rs +++ b/crates/hir-ty/tests/contract_semantics.rs @@ -1268,16 +1268,16 @@ contract PhantomAbi { fn calldata_arrays_nested_in_derived_adt_outputs_remain_input_only() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Bag = Bag(calldata(array(uint256))); -data Outer = Outer(Bag); +enum Bag {Bag(calldata>)} +enum Outer {Outer(Bag)} contract InvalidOutputs { - public function bag(values:calldata(array(uint256))) -> Bag { return Bag(values); } - public function outer(values:calldata(array(uint256))) -> Outer { + function bag(values:calldata>) public returns (Bag) { return Bag(values); } + function outer(values:calldata>) public returns (Outer) { return Outer(Bag(values)); } } @@ -1301,7 +1301,7 @@ contract InvalidOutputs { diagnostic.code.as_deref() == Some("SC0231") && diagnostic .message - .contains("calldata(array(t)) is input-only") + .contains("calldata> is input-only") }) .count() >= 2, @@ -1315,14 +1315,14 @@ contract InvalidOutputs { fn tuple_typed_constructor_field_uses_the_structural_generic_signature() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Wrap = Wrap((uint256, bool)); +enum Wrap {Wrap((uint256, bool))} contract Shapes { - public function roundtrip(value: Wrap) -> Wrap { return value; } + function roundtrip(value: Wrap) public returns (Wrap) { return value; } } "#, ); @@ -1352,11 +1352,11 @@ fn user_defined_location_name_does_not_make_an_adt_abi_safe() { let module = parse_module( &db, r#" -data memory(a) = memory(word); -data Wrap = Wrap(memory((word, bool))); +enum memory {memory(word)} +enum Wrap {Wrap(memory<(word, bool)>)} contract Shapes { - public function roundtrip(value: Wrap) -> Wrap { return value; } + function roundtrip(value: Wrap) public returns (Wrap) { return value; } } "#, ); @@ -1381,14 +1381,14 @@ contract Shapes { fn direct_dynamic_sum_adt_supports_input_output_and_roundtrip() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data D2 = L(uint256) | R(memory(bytes)); +enum D2 {L(uint256) , R(memory)} contract SumRoundtrip { - public function rtD2(x: D2) -> D2 { return x; } + function rtD2(x: D2) public returns (D2) { return x; } } "#, ); @@ -1419,12 +1419,12 @@ contract SumRoundtrip { fn imported_direct_adt_uses_definition_side_abi_derivation() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; -import model.{*}; +import * from std; +import * from std.dispatch; +import * from model; contract Imported { - public function roundtrip(payload:Payload) -> Payload { return payload; } + function roundtrip(payload:Payload) public returns (Payload) { return payload; } } "#, ); @@ -1435,14 +1435,14 @@ contract Imported { library: LibraryId::Main, logical_path: vec!["model".to_owned()], }, - "/main/model.solc", + "/main/model.sol", r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; export { Payload(*) }; -data Payload = Left(uint256) | Right(uint256); +enum Payload {Left(uint256) , Right(uint256)} "#, ); @@ -1471,12 +1471,12 @@ data Payload = Left(uint256) | Right(uint256); fn imported_output_only_adt_requires_definition_side_abi_derivation() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; -import model.{*}; +import * from std; +import * from std.dispatch; +import * from model; contract Imported { - public function make() -> Payload { return Payload.Left(uint256(1)); } + function make() public returns (Payload) { return Payload.Left(uint256(1)); } } "#, ); @@ -1487,13 +1487,13 @@ contract Imported { library: LibraryId::Main, logical_path: vec!["model".to_owned()], }, - "/main/model.solc", + "/main/model.sol", r#" -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; export { Payload(*) }; -data Payload = Left(uint256) | Right(uint256); +enum Payload {Left(uint256) , Right(uint256)} "#, ); @@ -1519,12 +1519,12 @@ data Payload = Left(uint256) | Right(uint256); fn db_with_reexported_abi_adt(api_source: &str) -> (TestDb, ModuleKey) { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; -import api.{Payload}; +import * from std; +import * from std.dispatch; +import {Payload} from api; contract Reexported { - public function roundtrip(payload:Payload) -> Payload { return payload; } + function roundtrip(payload:Payload) public returns (Payload) { return payload; } } "#, ); @@ -1535,14 +1535,14 @@ contract Reexported { library: LibraryId::Main, logical_path: vec!["base".to_owned()], }, - "/main/base.solc", + "/main/base.sol", r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; export { Payload(*) }; -data Payload = Left(uint256) | Right(uint256); +enum Payload {Left(uint256) , Right(uint256)} "#, ); insert_module_source( @@ -1551,7 +1551,7 @@ data Payload = Left(uint256) | Right(uint256); library: LibraryId::Main, logical_path: vec!["api".to_owned()], }, - "/main/api.solc", + "/main/api.sol", api_source, ); (db, key) @@ -1608,18 +1608,18 @@ fn instance_import_in_reexport_module_exposes_definition_side_abi_evidence() { fn visible_orphan_generic_instance_is_rejected_from_constructor_abi() { let (mut db, key) = db_with_main( r#" -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import model.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from model; pragma no-generic-instance-for Payload; -instance Payload:Generic(word) {} +impl Generic {} contract C { constructor(payload:Payload) {} - public function roundtrip(payload:Payload) -> Payload { return payload; } + function roundtrip(payload:Payload) public returns (Payload) { return payload; } } "#, ); @@ -1629,7 +1629,7 @@ contract C { library: LibraryId::Std, logical_path: vec!["std".to_owned()], }, - "/std/std.solc", + "/std/std.sol", "", ); insert_module_source( @@ -1638,14 +1638,14 @@ contract C { library: LibraryId::Std, logical_path: vec!["Generic".to_owned()], }, - "/std/Generic.solc", + "/std/Generic.sol", r#" pragma no-patterson-condition; pragma no-bounded-variable-condition; export { Generic }; -forall a rep. class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } "#, ); @@ -1655,7 +1655,7 @@ forall a rep. class a:Generic(rep) { library: LibraryId::Std, logical_path: vec!["dispatch".to_owned()], }, - "/std/dispatch.solc", + "/std/dispatch.sol", "", ); insert_module_source( @@ -1664,11 +1664,11 @@ forall a rep. class a:Generic(rep) { library: LibraryId::Main, logical_path: vec!["model".to_owned()], }, - "/main/model.solc", + "/main/model.sol", r#" -import std.{*}; +import * from std; export { Payload(*) }; - data Payload = Payload(word, bool); + enum Payload {Payload(word, bool)} "#, ); @@ -1694,10 +1694,10 @@ export { Payload(*) }; fn unsupported_std_leaf_is_not_reinterpreted_as_a_structural_user_adt() { let (mut db, key) = db_with_main( r#" -import std.{*}; +import * from std; contract C { - public function echo(value:byte) -> word { return 0; } + function echo(value:byte) public returns (word) { return 0; } } "#, ); @@ -1723,10 +1723,10 @@ fn abi_like_user_type_names_are_not_treated_as_canonical_types() { let module = parse_module( &db, r#" -data bytes16 = bytes16(word); +enum bytes16 {bytes16(word)} contract C { - public function echo(value:bytes16) -> bytes16 { return value; } + function echo(value:bytes16) public returns (bytes16) { return value; } } "#, ); @@ -1752,10 +1752,10 @@ fn parameterized_abi_type_fails_loudly_and_duplicate_signatures_are_diagnosed() let module = parse_module( &db, r#" -data Mapping(a, b) = Mapping; +enum Mapping {Mapping} contract Store { - public function put(m: Mapping(word, word)) -> word { return 0; } + function put(m: Mapping) public returns (word) { return 0; } } "#, ); @@ -1777,10 +1777,10 @@ contract Store { assert!( diagnostics( r#" -data Mapping(a, b) = Mapping; +enum Mapping {Mapping} contract Store { - public function put(m: Mapping(word, word)) -> word { return 0; } + function put(m: Mapping) public returns (word) { return 0; } } "# ) @@ -1792,8 +1792,8 @@ contract Store { &db, r#" contract Dup { - public function f(x: word) -> word { return x; } - public function f(x: word) -> word { return x; } + function f(x: word) public returns (word) { return x; } + function f(x: word) public returns (word) { return x; } } "#, ); @@ -1818,9 +1818,9 @@ contract Dup { fn different_signatures_with_the_same_selector_are_diagnosed() { let src = r#" contract Collision { - public function collision_8764(x: word) -> () { return (); } - public function collision_99992(x: word) -> () { return (); } - function main() -> () { return (); } + function collision_8764(x: word) public returns () { return (); } + function collision_99992(x: word) public returns () { return (); } + function main() returns () { return (); } } "#; let db = TestDb::default(); @@ -1868,8 +1868,8 @@ fn frontend_desugar_plan_records_if_bool_and_storage_field_hooks() { contract C { flag: word; - public function f() -> word { - if true { + function f() public returns (word) { + if (true) { flag = 1; } else { return flag; @@ -1918,24 +1918,22 @@ fn pre_typeck_desugar_plan_records_tuple_product_shapes_and_origins() { &db, r#" contract C { - seed: (word, bool) = if (true) then (1, true) else (2, false); + seed: (word, bool) = ((true) ? (1, true) : (2, false)); - public function f(x : word, y : bool, z : word) -> (word, bool, word) { + function f(x : word, y : bool, z : word) public returns ((word, bool, word)) { let t : (word, bool, word) = (x, y, z); let b : bool = true; - match b { - | true => return (x, y, z); - | false => return (z, y, x); - } - let w : word = if (y) then x else z; + match (b) { + case true { return (x, y, z); } +case false { return (z, y, x); }} + let w : word = ((y) ? x : z); if (y) { return (w, y, z); } else { return (z, y, w); } - match t { - | (a, b, c) => return (a, b, c); - } + match (t) { + case (a, b, c) { return (a, b, c); }} } } "#, @@ -2099,7 +2097,7 @@ contract C { fn typeck_lowers_tuple_return_type_to_right_nested_product() { let (db, key) = db_with_main( r#" -function triple(x : word, y : bool, z : word) -> (word, bool, word) { +function triple(x : word, y : bool, z : word) returns ((word, bool, word)) { return (x, y, z); } "#, @@ -2144,8 +2142,7 @@ fn frontend_desugar_plan_records_indirect_call_shape_and_evidence() { let module = parse_module( &db, r#" -forall c . c : invokable(pair(word, word), word) => -function apply2(f : c, a : word, b : word) -> word { +function apply2(f : c, a : word, b : word) returns (word) where c : invokable, word> { return f(a, b); } "#, @@ -2185,7 +2182,7 @@ function apply2(f : c, a : word, b : word) -> word { #[test] fn frontend_desugar_plan_records_compose3_indirect_call() { let src = - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.solc"); + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol"); assert!(diagnostics(src).is_empty()); let db = TestDb::default(); @@ -2214,7 +2211,7 @@ fn frontend_desugar_plan_records_compose3_indirect_call() { #[test] fn frontend_desugar_plan_records_simple_lambda_pair_arg_call() { let src = - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.solc"); + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol"); assert!(diagnostics(src).is_empty()); let db = TestDb::default(); @@ -2246,7 +2243,7 @@ fn frontend_desugar_plan_records_captured_zero_arg_closure_call() { let module = parse_module( &db, r#" -function inc(x : word) -> word { +function inc(x : word) returns (word) { let f = lam () { return x; }; return f(); } @@ -2279,7 +2276,7 @@ fn derived_generic_plan_uses_right_nested_product_rep_for_tree() { let module = parse_module( &db, r#" -data Tree(a) = Leaf | Node(Tree(a), a, Tree(a)); +enum Tree {Leaf , Node(Tree, a, Tree)} "#, ); let tree = adt_named(&db, module, "Tree"); @@ -2314,13 +2311,13 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-generic-instance-for Excluded; -forall a rep . class a:Generic(rep) {} +trait Generic {} -data Eligible = Eligible(word); -data Excluded = Excluded(word); -data Manual = Manual(word); +enum Eligible {Eligible(word)} +enum Excluded {Excluded(word)} +enum Manual {Manual(word)} -instance Manual:Generic(word) {} +impl Generic {} "#, ); let generic = module diff --git a/crates/hir-ty/tests/derived_abi_solver.rs b/crates/hir-ty/tests/derived_abi_solver.rs index dba819f4..9882a1ee 100644 --- a/crates/hir-ty/tests/derived_abi_solver.rs +++ b/crates/hir-ty/tests/derived_abi_solver.rs @@ -23,18 +23,18 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -forall a rep . class a:Generic(rep) {} -forall self . class self:ABIDeriving {} -forall self . class self:ABIAttribs {} -forall decoder decoded . class decoder:ABIDecode(decoded) {} -forall reader . class reader:WordReader {} +trait Generic {} +trait ABIDeriving {} +trait ABIAttribs {} +trait ABIDecode {} +trait WordReader {} -data ABIDecoder(ty, reader) = ABIDecoder(reader); -data Reader = Reader; +enum ABIDecoder {ABIDecoder(reader)} +enum Reader {Reader} -instance Reader:WordReader {} -instance word:ABIAttribs {} -instance ABIDecoder(word, Reader):ABIDecode(word) {} +impl WordReader {} +impl ABIAttribs {} +impl ABIDecode,word> {} "#; fn class_def<'db>(db: &'db TestDb, module: Module<'db>, name: &str) -> DefId<'db> { @@ -86,13 +86,7 @@ fn decoder_ty<'db>( #[test] fn derives_parameterized_abi_evidence_once() { let mut db = TestDb::default(); - let key = load_main_source( - &mut db, - &format!( - "{ABI_SOURCE}\n\ - data Box(a) = Box(a);\n" - ), - ); + let key = load_main_source(&mut db, &format!("{ABI_SOURCE}\nenum Box {{Box(a)}}\n")); let module_id = module_id_from_key(&db, &key); let file = db.module_file(module_id).expect("main source file"); let module = parse_file_to_hir(&db, file).module(&db); @@ -171,13 +165,7 @@ fn excludes_recursive_no_generic_and_manual_generic_adts() { let key = load_main_source( &mut db, &format!( - "{ABI_SOURCE}\n\ - pragma no-generic-instance-for Excluded;\n\ - data Eligible = Eligible(word);\n\ - data Excluded = Excluded(word);\n\ - data Manual = Manual(word);\n\ - data Recursive = Recursive(Recursive);\n\ - instance Manual:Generic(word) {{}}\n" + "{ABI_SOURCE}\npragma no-generic-instance-for Excluded;\nenum Eligible {{Eligible(word)}}\nenum Excluded {{Excluded(word)}}\nenum Manual {{Manual(word)}}\nenum Recursive {{Recursive(Recursive)}}\nimpl Generic {{}}\n" ), ); let module_id = module_id_from_key(&db, &key); @@ -314,12 +302,7 @@ fn excludes_contract_local_adts_with_inherited_type_binders() { let mut db = TestDb::default(); let key = load_main_source( &mut db, - &format!( - "{ABI_SOURCE}\n\ - contract C(t) {{\n\ - data Local(a) = Local(a);\n\ - }}\n" - ), + &format!("{ABI_SOURCE}\ncontract C {{\nenum Local {{Local(a)}}\n}}\n"), ); let module_id = module_id_from_key(&db, &key); let file = db.module_file(module_id).expect("main source file"); diff --git a/crates/hir-ty/tests/derived_class_solver.rs b/crates/hir-ty/tests/derived_class_solver.rs index 9cfaf3eb..a885634b 100644 --- a/crates/hir-ty/tests/derived_class_solver.rs +++ b/crates/hir-ty/tests/derived_class_solver.rs @@ -59,9 +59,9 @@ fn derived_clause_constrains_every_declared_type_parameter() { let key = load_main_source( &mut db, r#" -forall a . class a:Marker {} -instance word:Marker {} -#[derive(Marker)] data Phantom(a) = Phantom(word); +trait Marker {} +impl Marker {} +#[derive(Marker)] enum Phantom { Phantom(word) } "#, ); let module_id = module_id_from_key(&db, &key); @@ -112,8 +112,8 @@ fn duplicate_derive_targets_remain_distinct_solver_candidates() { let key = load_main_source( &mut db, r#" -forall a . class a:Marker {} -#[derive(Marker, Marker)] data Target; +trait Marker {} +#[derive(Marker, Marker)] enum Target {} "#, ); let module_id = module_id_from_key(&db, &key); @@ -147,9 +147,9 @@ fn manual_and_derived_instances_report_the_usual_overlap() { let key = load_main_source( &mut db, r#" -forall a . class a:Marker {} -#[derive(Marker)] data Target; -instance Target:Marker {} +trait Marker {} +#[derive(Marker)] enum Target {} +impl Marker {} "#, ); let module = module_id_from_key(&db, &key); @@ -169,9 +169,9 @@ fn generic_contract_capture_does_not_create_an_unconditional_clause() { let key = load_main_source( &mut db, r#" -forall a . class a:Marker {} -contract C(t) { - #[derive(Marker)] data Local = Local(t); +trait Marker {} +contract C { + #[derive(Marker)] enum Local { Local(t) } } "#, ); @@ -194,8 +194,8 @@ fn multi_parameter_class_derive_is_rejected_at_the_declaration() { let key = load_main_source( &mut db, r#" -forall a r . class a:Convert(r) {} -#[derive(Convert)] data Target; +trait Convert {} +#[derive(Convert)] enum Target {} "#, ); let module = module_id_from_key(&db, &key); @@ -207,7 +207,7 @@ forall a r . class a:Convert(r) {} diagnostic, AnyDiagnostic::Typeck(diagnostic) if diagnostic.code.as_deref() == Some(DiagnosticCode::TYPECK_INVALID_DERIVE) - && diagnostic.message.contains("only single-parameter classes") + && diagnostic.message.contains("only single-parameter traits") )) ); } diff --git a/crates/hir-ty/tests/derived_storage_solver.rs b/crates/hir-ty/tests/derived_storage_solver.rs index 018d285a..796143b0 100644 --- a/crates/hir-ty/tests/derived_storage_solver.rs +++ b/crates/hir-ty/tests/derived_storage_solver.rs @@ -22,15 +22,15 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -forall a rep . class a:Generic(rep) {} -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize {} -forall slot value . class slot:CanStore(value) {} +trait Generic {} +trait StorageDeriving {} +trait StorageSize {} +trait CanStore {} -data storage(ty) = storage(word); +enum storage {storage(word)} -instance word:StorageSize {} -instance storage(word):CanStore(word) {} +impl StorageSize {} +impl CanStore,word> {} "#; fn class_def<'db>(db: &'db TestDb, module: Module<'db>, name: &str) -> DefId<'db> { @@ -79,7 +79,7 @@ fn derives_parameterized_storage_evidence_once() { let mut db = TestDb::default(); let key = load_main_source( &mut db, - &format!("{STORAGE_SOURCE}\ndata Box(a) = Box(a);\n"), + &format!("{STORAGE_SOURCE}\nenum Box {{Box(a)}}\n"), ); let module_id = module_id_from_key(&db, &key); let file = db.module_file(module_id).expect("main source file"); @@ -157,9 +157,7 @@ fn recursive_storage_derivation_is_a_per_type_skip() { let key = load_main_source( &mut db, &format!( - "{STORAGE_SOURCE}\n\ - data Point = Point(word, word);\n\ - data Recursive = Recursive(Recursive);\n" + "{STORAGE_SOURCE}\nenum Point {{Point(word, word)}}\nenum Recursive {{Recursive(Recursive)}}\n" ), ); let module_id = module_id_from_key(&db, &key); diff --git a/crates/hir-ty/tests/frontend_smoke.rs b/crates/hir-ty/tests/frontend_smoke.rs index 73ce2240..42af22d7 100644 --- a/crates/hir-ty/tests/frontend_smoke.rs +++ b/crates/hir-ty/tests/frontend_smoke.rs @@ -187,11 +187,11 @@ fn std_solc_frontend_typecheck_triage() { let repo = repo_root(); let corpus_root = repo.join("crates/parser/tests/fixtures/corpus/ok"); let std_root = corpus_root.join("std"); - let outcome = run_frontend(&std_root.join("std.solc"), &std_root); + let outcome = run_frontend(&std_root.join("std.sol"), &std_root); let std_triage = std_solc_triage(&outcome); let mut report = String::new(); - writeln!(&mut report, "std.solc frontend triage").unwrap(); + writeln!(&mut report, "std.sol frontend triage").unwrap(); writeln!( &mut report, " unresolved-imports: {}", @@ -217,7 +217,7 @@ fn std_solc_frontend_typecheck_triage() { assert!( outcome.unresolved_imports.is_empty(), - "std.solc has unresolved imports:\n{report}" + "std.sol has unresolved imports:\n{report}" ); assert!( std_triage.unrecorded.is_empty() && std_triage.stale.is_empty(), @@ -231,9 +231,9 @@ fn curated_solver_files_execute_solver_and_soundness_queries() { let corpus_root = repo.join("crates/parser/tests/fixtures/corpus"); let std_root = corpus_root.join("ok/std"); let fixtures = [ - "examples/cases/tabled-default-instance.solc", - "examples/cases/tabled-given-order.solc", - "examples/cases/tabled-residual-given.solc", + "examples/cases/tabled-default-instance.sol", + "examples/cases/tabled-given-order.sol", + "examples/cases/tabled-residual-given.sol", ]; for fixture in fixtures { @@ -290,7 +290,7 @@ fn curated_solver_files_execute_solver_and_soundness_queries() { fn generated_dispatch_reuses_std_instance_facts_per_module() { let repo = repo_root(); let entry = repo.join( - "crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.solc", + "crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol", ); let std_root = repo.join("std"); let outcome = run_frontend(&entry, &std_root); @@ -321,9 +321,9 @@ fn match_coverage_conservative_cases_emit_no_false_diagnostics() { let std_root = corpus_root.join("ok/std"); for fixture in [ - "examples/cases/false-redundant-warning.solc", - "examples/comptime/match_labels.solc", - "examples/cases/polymatch-error.solc", + "examples/cases/false-redundant-warning.sol", + "examples/comptime/match_labels.sol", + "examples/cases/polymatch-error.sol", ] { let entry = corpus_entry(&corpus_root, fixture); let outcome = run_frontend_with_roots( @@ -735,7 +735,7 @@ fn relative_solc_paths(root: &Path) -> BTreeSet { let path = entry.path(); if path.is_dir() { walk(root, &path, paths); - } else if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + } else if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { let relative = path .strip_prefix(root) .expect("walked path is below corpus root") @@ -980,7 +980,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -1094,7 +1094,7 @@ fn append_diagnostic_sample(report: &mut String, label: &str, diagnostics: &[Str fn append_std_solc_triage(report: &mut String, triage: &StdSolcTriage) { if !triage.known_by_reason.is_empty() { - writeln!(report, "\nstd.solc known diagnostic families").unwrap(); + writeln!(report, "\nstd.sol known diagnostic families").unwrap(); for (reason, diagnostics) in &triage.known_by_reason { writeln!(report, " {reason}: {}", diagnostics.len()).unwrap(); for diagnostic in diagnostics.iter().take(6) { @@ -1107,14 +1107,14 @@ fn append_std_solc_triage(report: &mut String, triage: &StdSolcTriage) { } if !triage.unrecorded.is_empty() { - writeln!(report, "\nstd.solc unrecorded diagnostic families").unwrap(); + writeln!(report, "\nstd.sol unrecorded diagnostic families").unwrap(); for diagnostic in triage.unrecorded.iter().take(20) { writeln!(report, " {}: {}", diagnostic.phase, diagnostic.diagnostic).unwrap(); } if triage.unrecorded.len() > 20 { writeln!( report, - " ... {} more unrecorded std.solc diagnostics", + " ... {} more unrecorded std.sol diagnostics", triage.unrecorded.len() - 20 ) .unwrap(); @@ -1122,7 +1122,7 @@ fn append_std_solc_triage(report: &mut String, triage: &StdSolcTriage) { } if !triage.stale.is_empty() { - writeln!(report, "\nstd.solc stale diagnostic families").unwrap(); + writeln!(report, "\nstd.sol stale diagnostic families").unwrap(); for known in &triage.stale { writeln!( report, diff --git a/crates/hir-ty/tests/incremental_cache.rs b/crates/hir-ty/tests/incremental_cache.rs index 6c448cf3..3323c49d 100644 --- a/crates/hir-ty/tests/incremental_cache.rs +++ b/crates/hir-ty/tests/incremental_cache.rs @@ -124,14 +124,14 @@ impl solcore_hir_ty::Db for TestDb {} #[test] fn unrelated_signature_edit_does_not_rerun_every_body_inference() { let before = r#" -function id(x: word) -> word { return x; } -function unrelated(x: word) -> word { return 0; } -function main() -> word { return id(1); } +function id(x: word) returns (word) { return x; } +function unrelated(x: word) returns (word) { return 0; } +function main() returns (word) { return id(1); } "#; let after = r#" -function id(x: word) -> word { return x; } -function unrelated(x: bool) -> word { return 0; } -function main() -> word { return id(1); } +function id(x: word) returns (word) { return x; } +function unrelated(x: bool) returns (word) { return 0; } +function main() returns (word) { return id(1); } "#; let (mut db, file, key) = db_with_main(before); @@ -165,21 +165,21 @@ function main() -> word { return id(1); } #[test] fn same_obligation_body_edit_does_not_resolve_solver_query() { let before = r#" -forall a . class a:C {} -instance word:C {} -forall a . a:C => function use(x: a) -> word { return 0; } +trait C {} +impl C {} +function use(x: a) returns (word) where a: C { return 0; } -function main() -> word { +function main() returns (word) { let y: word = 1; return use(1); } "#; let after = r#" -forall a . class a:C {} -instance word:C {} -forall a . a:C => function use(x: a) -> word { return 0; } +trait C {} +impl C {} +function use(x: a) returns (word) where a: C { return 0; } -function main() -> word { +function main() returns (word) { let y: word = 2; return use(1); } @@ -220,14 +220,14 @@ function main() -> word { #[test] fn instance_soundness_edit_is_backdated_into_module_diagnostics() { let before = r#" -data Box(a) = Box(word); -forall a b . class a:C(b) {} -forall a b . instance Box(a):C(b) {} +enum Box {Box(word)} +trait C {} +impl C,b> {} "#; let after = r#" -data Box(a) = Box(word); -forall a b . class a:C(b) {} -forall a . instance Box(a):C(word) {} +enum Box {Box(word)} +trait C {} +impl C,word> {} "#; let (mut db, file, key) = db_with_main(before); @@ -267,10 +267,10 @@ fn instance_soundness_reuses_scope_resolution_for_many_instances() { let mut source = String::new(); for index in 0..INSTANCE_COUNT { - writeln!(source, "forall a . class a:AuditClass{index} {{}}").unwrap(); - writeln!(source, "instance word:AuditClass{index} {{}}").unwrap(); + writeln!(source, "trait AuditClass{index} {{}}").unwrap(); + writeln!(source, "impl AuditClass{index} {{}}").unwrap(); } - source.push_str("function main() -> word { return 0; }\n"); + source.push_str("function main() returns (word) { return 0; }\n"); let (db, _file, key) = db_with_file_backed_main(&source); let module = module_id_from_key(&db, &key); @@ -289,8 +289,8 @@ fn instance_soundness_reuses_scope_resolution_for_many_instances() { #[test] fn generic_lookup_does_not_reresolve_all_item_types() { let source = r#" -forall a rep . class a:Generic(rep) {} -data Box(a) = Box(a); +trait Generic {} +enum Box {Box(a)} "#; let (db, file, _key) = db_with_main(source); @@ -312,12 +312,12 @@ data Box(a) = Box(a); fn contract_body_edit_does_not_rerun_dispatch_surface_query() { let before = r#" contract C { - public function get() -> word { return 1; } + function get() public returns (word) { return 1; } } "#; let after = r#" contract C { - public function get() -> word { return 2; } + function get() public returns (word) { return 2; } } "#; let (mut db, file, _key) = db_with_main(before); @@ -356,14 +356,14 @@ contract C { fn import_diagnostic_span_edit_does_not_rerun_unrelated_body_inference() { let before = concat!( "\n", - "import util.{f}; \x20\n", - "function f() -> word { return 1; }\n", - "function main() -> word { return f(); }\n", + "import {f} from util; \n", + "function f() returns (word) { return 1; }\n", + "function main() returns (word) { return f(); }\n", ); let after = r#" -import util.{f} ; -function f() -> word { return 1; } -function main() -> word { return f(); } +import {f} from util; +function f() returns (word) { return 1; } +function main() returns (word) { return f(); } "#; let (mut db, file, key) = db_with_selected_import_conflict(before); @@ -399,28 +399,26 @@ function main() -> word { return f(); } #[test] fn desugar_body_edit_does_not_rerun_unrelated_body_inference() { let before = r#" -function choose(b: bool, x: word, y: word) -> word { +function choose(b: bool, x: word, y: word) returns (word) { let p: (word, bool) = (x, true); - let selected: word = if b then x else y; - match p { - | (head, flag) => return selected; - } + let selected: word = (b ? x : y); + match (p) { + case (head, flag) { return selected; }} } -function stable(x: word) -> word { return x; } -function main() -> word { return stable(choose(false, 1, 2)); } +function stable(x: word) returns (word) { return x; } +function main() returns (word) { return stable(choose(false, 1, 2)); } "#; let after = r#" -function choose(b: bool, x: word, y: word) -> word { +function choose(b: bool, x: word, y: word) returns (word) { let p: (word, bool) = (x, false); - let selected: word = if b then x else y; - match p { - | (head, flag) => return selected; - } + let selected: word = (b ? x : y); + match (p) { + case (head, flag) { return selected; }} } -function stable(x: word) -> word { return x; } -function main() -> word { return stable(choose(false, 1, 2)); } +function stable(x: word) returns (word) { return x; } +function main() returns (word) { return stable(choose(false, 1, 2)); } "#; let (mut db, file, key) = db_with_main(before); @@ -461,11 +459,11 @@ function main() -> word { return stable(choose(false, 1, 2)); } } fn db_with_main(content: &str) -> (TestDb, SourceFile, ModuleKey) { - db_with_main_url(content, "memory:///main.solc") + db_with_main_url(content, "memory:///main.sol") } fn db_with_file_backed_main(content: &str) -> (TestDb, SourceFile, ModuleKey) { - db_with_main_url(content, "file:///memory/main.solc") + db_with_main_url(content, "file:///memory/main.sol") } fn db_with_main_url(content: &str, url: &str) -> (TestDb, SourceFile, ModuleKey) { @@ -506,14 +504,14 @@ fn db_with_selected_import_conflict(content: &str) -> (TestDb, SourceFile, Modul }; let util_file = SourceFile::new( &db, - "memory:///util.solc".parse().expect("valid URL"), - Some("function f() -> word { return 0; }\nexport { f };\n".to_owned()), + "memory:///util.sol".parse().expect("valid URL"), + Some("function f() returns (word) { return 0; }\nexport { f };\n".to_owned()), ); db.insert_module_file(util_key, util_file); let file = SourceFile::new( &db, - "memory:///main.solc".parse().expect("valid URL"), + "memory:///main.sol".parse().expect("valid URL"), Some(content.to_owned()), ); let key = ModuleKey { diff --git a/crates/hir-ty/tests/ok_fixtures.rs b/crates/hir-ty/tests/ok_fixtures.rs index 3a38f829..e6252e22 100644 --- a/crates/hir-ty/tests/ok_fixtures.rs +++ b/crates/hir-ty/tests/ok_fixtures.rs @@ -12,7 +12,7 @@ define_frontend_test_db!(TestDb, solcore_hir_ty); #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/ok", - glob: "**/main.solc" + glob: "**/main.sol" )] fn hir_ty_ok_fixture_has_no_diagnostics(fixture: Fixture<&str>) { let case_dir = PathBuf::from(fixture.path()) diff --git a/crates/hir-ty/tests/properties.rs b/crates/hir-ty/tests/properties.rs index 9b9b7c5f..34ab6a55 100644 --- a/crates/hir-ty/tests/properties.rs +++ b/crates/hir-ty/tests/properties.rs @@ -13,8 +13,9 @@ fn run_frontend(source: &str) { } fn generated_program(literal: u64, depth: usize, result_kind: u8) -> String { - let mut source = - format!("function main(value : word) -> word {{\n let value0 : word = {literal};\n"); + let mut source = format!( + "function main(value : word) returns (word) {{\n let value0 : word = {literal};\n" + ); for index in 1..=depth { source.push_str(&format!( " let value{index} : word = value{};\n", @@ -25,7 +26,7 @@ fn generated_program(literal: u64, depth: usize, result_kind: u8) -> String { 0 => format!("value{depth}"), 1 => "true".to_owned(), 2 => "missing".to_owned(), - _ => format!("if true then value else value{depth}"), + _ => format!("true ? value : value{depth}"), }; source.push_str(&format!(" return {result};\n}}\n")); source diff --git a/crates/hir-ty/tests/scheme_cycle.rs b/crates/hir-ty/tests/scheme_cycle.rs index 1eb53746..65162141 100644 --- a/crates/hir-ty/tests/scheme_cycle.rs +++ b/crates/hir-ty/tests/scheme_cycle.rs @@ -5,13 +5,11 @@ use solcore_test_utils::{define_frontend_test_db, load_main_source, run_in_large define_frontend_test_db!(TestDb, hir_ty); -/// `return f` makes `f`'s inferred signature grow every fixpoint round; the -/// scheme query must converge through its cycle fallback instead of Salsa -/// panicking with "too many cycle iterations". The program is currently still -/// accepted under legacy signature inference (the reference meanwhile rejects -/// it with SC0220 "incomplete signature"), so only panic-freedom is asserted. +/// The missing `returns` clause intentionally gives `f` the canonical unit +/// result while its body returns `f` itself. Recovery from that recursive type +/// mismatch must not make the scheme query cycle or panic. #[test] -fn divergent_recursive_signature_does_not_panic() { +fn recursive_unit_return_mismatch_does_not_panic() { run_in_large_stack(|| { let mut db = TestDb::default(); let entry = load_main_source(&mut db, "function f(x: word) {\n return f;\n}\n"); From 98df56f9829e94d47d445478142681551dbabe71 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 037/110] Switch the compiler and fixtures to canonical syntax: hir ty fixtures Co-authored-by: Codex --- .../storage-adt-mapping-field-fail/main.sol | 10 ++--- .../storage-adt-recursive-fail/main.sol | 10 ++--- .../storage-adt-recursive-ok/main.sol | 30 +++++++------ .../storage-body-only-active-ok/main.sol | 11 ++--- .../storage-body-only-active-ok/types.sol | 8 ++-- .../storage-body-only-inactive-fail/main.sol | 11 ++--- .../storage-body-only-inactive-fail/types.sol | 6 +-- .../storage-body-only-qualified-ok/main.sol | 11 +++-- .../storage-body-only-qualified-ok/types.sol | 8 ++-- .../storage-builtins-unused-ok/main.sol | 12 ++--- .../main.sol | 8 ++-- .../types.sol | 8 ++-- .../main.sol | 8 ++-- .../types.sol | 6 +-- .../main.sol | 6 +-- .../types.sol | 8 ++-- .../base.sol | 8 ++-- .../main.sol | 6 +-- .../outer.sol | 10 ++--- .../main.sol | 18 ++++---- .../frontend_call_classification/main.sol | 6 +-- .../main.sol | 6 +-- .../ok/comptime/return_params/main.sol | 2 +- .../local-class/p4-default-instance/main.sol | 12 ++--- .../local-class/p4-local-instance/main.sol | 20 +++++---- .../local-class/tabled-answer-reuse/main.sol | 12 ++--- .../local-class/tabled-given-order/main.sol | 16 +++---- .../tabled-residual-given/main.sol | 12 ++--- .../fixtures/ok/corpus/spec/00answer/main.sol | 2 +- .../fixtures/ok/corpus/spec/021not/main.sol | 32 +++++++++----- .../fixtures/ok/corpus/spec/022add/main.sol | 4 +- .../fixtures/ok/corpus/spec/024arith/main.sol | 16 +++---- .../fixtures/ok/corpus/spec/031maybe/main.sol | 20 +++++---- .../ok/corpus/spec/036wildcard/main.sol | 18 +++++--- .../fixtures/ok/corpus/spec/041pair/main.sol | 12 ++--- .../ok/corpus/spec/042triple/main.sol | 12 ++--- .../fixtures/ok/corpus/spec/047rgb/main.sol | 20 ++++++--- .../fixtures/ok/corpus/spec/048rgb2/main.sol | 22 ++++++---- .../fixtures/ok/corpus/spec/049rgb3/main.sol | 22 ++++++---- .../main.sol | 8 ++-- .../class_scoped_patterson_pragma/main.sol | 6 +-- .../ok/solver/global_coverage_pragma/main.sol | 6 +-- .../obligation_order_improvement/main.sol | 25 +++++------ .../abstract_data_wildcard_match/main.sol | 12 ++--- .../bytes_storage_roundtrip_full/main.sol | 8 ++-- .../main.sol | 6 +-- .../main.sol | 10 ++--- .../main.sol | 12 ++--- .../constructor_dynamic_string_full/main.sol | 8 ++-- .../ok/typeck/contract_field_access/main.sol | 4 +- .../contract_field_initializer/main.sol | 2 +- .../dispatch_field_method_collision/main.sol | 10 ++--- .../dot_constructors_nested_patterns/main.sol | 18 +++++--- .../main.sol | 6 +-- .../import_same_name_ctor_unqualified/lib.sol | 4 +- .../main.sol | 24 +++++----- .../ok/typeck/imported_derived_class/lib.sol | 13 +++--- .../ok/typeck/imported_derived_class/main.sol | 7 ++- .../typeck/integer_literal_pattern/main.sol | 14 +++--- .../lambda_expected_function_type/main.sol | 6 +-- .../ok/typeck/literal_poly_noclass/main.sol | 2 +- .../nested_generic_adt_constructor/main.sol | 8 ++-- .../main.sol | 32 +++++++++----- .../same_name_nullary_ctor_pattern/main.sol | 30 ++++++++----- .../ok/typeck/self_recursive_data/main.sol | 4 +- .../ok/typeck/std_universe_eq_ord/main.sol | 16 +++---- .../ok/typeck/std_word_minmax/main.sol | 6 +-- .../main.sol | 30 ++++++------- .../main.sol | 30 ++++++------- .../storage_word_assignment_full/main.sol | 19 ++++---- .../main.sol | 44 +++++++++---------- 71 files changed, 483 insertions(+), 416 deletions(-) diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.sol index 15f842a6..15856de8 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-mapping-field-fail/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // A mapping cannot be a field of a data type. std only provides // `storage(mapping(k,v)) : CanStore(storage(mapping(k,v)))` — the slot handle @@ -12,7 +12,7 @@ import std.StorageGeneric.{*}; // (Even if it did, that instance's store/load are `unimplemented()`: copying a // mapping is not a meaningful storage operation.) -data Wrapper = Wrapper(mapping(uint256, uint256)); +enum Wrapper { Wrapper(mapping(uint256 => uint256)) } contract C { w : Wrapper; diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.sol index d7739a57..0895dd9a 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-fail/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // A recursive data type has no bounded slot footprint, so DeriveGeneric // (isRecursiveData) deliberately skips deriving StorageSize and @@ -11,7 +11,7 @@ import std.StorageGeneric.{*}; // The failure surfaces at the use site (the field assignment), not at // derivation time, which is the design stated in DeriveGeneric. -data IntList = Nil | Cons(uint256, IntList); +enum IntList { Nil, Cons(uint256, IntList) } contract C { xs : IntList; diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.sol index e28974fc..cacf5e80 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-adt-recursive-ok/main.sol @@ -1,30 +1,34 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; -// The counterpart of storage-adt-recursive-fail.solc: skipping storage +// The counterpart of storage-adt-recursive-fail.sol: skipping storage // derivation for a recursive type is a SKIP, not a hard error. The type still // gets its Generic instance and remains usable everywhere except storage. -data IntList = Nil | Cons(uint256, IntList); +enum IntList { Nil, Cons(uint256, IntList) } -function len(xs : IntList) -> uint256 { - match xs { - | IntList.Nil => return uint256(0); - | IntList.Cons(_, r) => return uint256(1) + len(r); - } +function len(xs: IntList) returns (uint256) { + match (xs) { +case IntList.Nil { +return uint256(0); +} +case IntList.Cons(_, r) { +return uint256(1) + len(r); +} +} } // A non-recursive neighbour in the same module still gets its storage // instances, so the skip is per-type rather than per-module. -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } contract C { p : Point; constructor() { p = Point(uint256(1), uint256(2)); - assert(StorageSize.size(Proxy : Proxy(Point)) == 2); + assert(StorageSize.size(@Point) == 2); } } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.sol index 48e697d7..9dc2258c 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/main.sol @@ -1,7 +1,8 @@ -import std.{*}; -import types.{Box}; +import * from std; +import {Box} from types; -function touchBox() -> () { - let size : word = StorageSize.size(Proxy : Proxy(Box(uint256))); - let value : Box(uint256) = CanStore.load(storage(0) : storage(Box(uint256))); +function touchBox() { + let size : word = StorageSize.size(@Box); + let slot : storage> = storage(0); + let value : Box = CanStore.load(slot); } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.sol index f20e7e56..cf198a3a 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-active-ok/types.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.sol index 48e697d7..9dc2258c 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/main.sol @@ -1,7 +1,8 @@ -import std.{*}; -import types.{Box}; +import * from std; +import {Box} from types; -function touchBox() -> () { - let size : word = StorageSize.size(Proxy : Proxy(Box(uint256))); - let value : Box(uint256) = CanStore.load(storage(0) : storage(Box(uint256))); +function touchBox() { + let size : word = StorageSize.size(@Box); + let slot : storage> = storage(0); + let value : Box = CanStore.load(slot); } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.sol index bbaa269e..57b5be64 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-inactive-fail/types.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; export { Box(*) }; // StorageGeneric is deliberately not visible in this defining module. -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.sol index e1bc16bf..5bf2469c 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/main.sol @@ -1,9 +1,8 @@ -import std.{*}; +import * from std; import types; -function touchBox() -> () { - let size : word = StorageSize.size(Proxy : Proxy(types.Box(uint256))); - let value : types.Box(uint256) = CanStore.load( - storage(0) : storage(types.Box(uint256)) - ); +function touchBox() { + let size : word = StorageSize.size(@types.Box); + let slot : storage> = storage(0); + let value : types.Box = CanStore.load(slot); } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.sol index f20e7e56..cf198a3a 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-body-only-qualified-ok/types.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.sol index df44106f..e1a5f9e6 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-builtins-unused-ok/main.sol @@ -1,15 +1,15 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // Declaration-side validation must use the value each storage handle actually // loads. Mappings and arrays load handles, strings and bytes load memory values, // and scalar fields load their declared value. contract C { n : uint256; - m : mapping(uint256, uint256); - a : array(uint256); + m : mapping(uint256 => uint256); + a : array; s : string; b : bytes; diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.sol index 5ecce205..e0ed6ce7 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/main.sol @@ -1,12 +1,12 @@ -import std.{*}; -import std.dispatch.{*}; -import types.{Box}; +import * from std; +import * from std.dispatch; +import {Box} from types; // The concrete storage instance belongs to Box's definition module. A // consumer only needs the ordinary storage classes; it need not import // Generic, StorageDeriving, or the structural implementation instances. contract C { - value : Box(uint256); + value : Box; constructor() {} } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.sol index f20e7e56..cf198a3a 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-active-no-marker-ok/types.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.sol index eea4b1e5..5a25057b 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/main.sol @@ -1,11 +1,11 @@ -import std.{*}; -import std.dispatch.{*}; -import types.{Box}; +import * from std; +import * from std.dispatch; +import {Box} from types; // Importing an ordinary Generic ADT does not retroactively create storage // instances when its definition module never enabled StorageGeneric. contract C { - value : Box(uint256); + value : Box; constructor() {} } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.sol index 88af9f6f..b1f85bfc 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-inactive-no-marker-fail/types.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.sol index 23cf325c..ae40fdb5 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/main.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; -import types.{Wrapper}; +import * from std; +import * from std.dispatch; +import {Wrapper} from types; // Selecting Wrapper's derived instance must validate its structural body in // the definition module even though this consumer does not import the marker. diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.sol index 43c3b895..d782e003 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-imported-invalid-no-marker-fail/types.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; export { Wrapper(*) }; -data Wrapper = Wrapper(mapping(uint256, uint256)); +enum Wrapper { Wrapper(mapping(uint256 => uint256)) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.sol index 3bb1914a..e7c795f5 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/base.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; export { Inner(*) }; -data Inner = Inner(uint256); +enum Inner { Inner(uint256) } diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.sol index d924c4be..748b8b73 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/main.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; -import outer.{Outer}; +import * from std; +import * from std.dispatch; +import {Outer} from outer; contract C { value : Outer; diff --git a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.sol b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.sol index b9352adf..44c713ac 100644 --- a/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.sol +++ b/crates/hir-ty/tests/fixtures/derived_storage_frontend/storage-nested-reexport-invalid-fail/outer.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; -import api.{Inner}; +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; +import {Inner} from api; export { Outer(*) }; -data Outer = Outer(Inner); +enum Outer { Outer(Inner) } diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.sol b/crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.sol index f2040319..6749c56f 100644 --- a/crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/comptime/class_method_runtime_body_deferred/main.sol @@ -1,17 +1,17 @@ -data Box = Box(word); +enum Box { Box(word) } -forall a. class a : Scale { - function scale(comptime factor : word, comptime x : a) -> comptime a; +trait Scale { + function scale(comptime factor: word, comptime x: a) returns (comptime) ; } -instance word : Scale { - function scale(comptime factor : word, comptime x : word) -> comptime word { +impl Scale { + function scale(comptime factor: word, comptime x: word) returns (comptime) { return x; } } -instance Box : Scale { - function scale(comptime factor : word, comptime x : Box) -> comptime Box { +impl Scale { + function scale(comptime factor: word, comptime x: Box) returns (comptime) { let y : word; assembly { y := sload(0) @@ -21,8 +21,8 @@ instance Box : Scale { } contract C { - function main() -> word { - let a : comptime word = Scale.scale(1, 2); + function main() returns (word) { + let a : comptime = Scale.scale(1, 2); return a; } } diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.sol b/crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.sol index 68c48b63..724842e6 100644 --- a/crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/comptime/frontend_call_classification/main.sol @@ -1,8 +1,8 @@ -function id(x: word) -> word { +function id(x: word) returns (word) { return x; } -function id_ct(x: word) -> comptime word { - let y : comptime word = id(x); +function id_ct(x: word) returns (comptime) { + let y : comptime = id(x); return id(x); } diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.sol b/crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.sol index 248d013f..bbc03c38 100644 --- a/crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/comptime/polymorphic_param_defers_runtime_arg/main.sol @@ -1,7 +1,7 @@ -forall t. class t : Wrap { - function unwrap(comptime x : t) -> comptime word; +trait Wrap { + function unwrap(comptime x: t) returns (comptime) ; } -forall t. t:Wrap => function process(z : t) -> word { +function process(z: t) returns (word) where t: Wrap { return Wrap.unwrap(z); } diff --git a/crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.sol b/crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.sol index 2af25936..074f6a04 100644 --- a/crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/comptime/return_params/main.sol @@ -1,3 +1,3 @@ -function id_ct(x: word) -> comptime word { +function id_ct(x: word) returns (comptime) { return x; } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.sol index cd383e3a..e24cf383 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-default-instance/main.sol @@ -1,15 +1,15 @@ -data Name = Name(word); +enum Name { Name(word) } -forall a . class a:Token { - function token(x:a) -> word; +trait Token { + function token(x: a) returns (word) ; } -forall a . default instance a:Token { - function token(x:a) -> word { +default impl Token { + function token(x: a) returns (word) { return 0; } } -function main() -> word { +function main() returns (word) { return Token.token(Name.Name(2)); } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.sol index ed3a3253..0a168834 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/p4-local-instance/main.sol @@ -1,17 +1,19 @@ -data Wrap = Wrap(word); +enum Wrap { Wrap(word) } -forall a . class a:Boxed { - function unbox(x:a) -> word; +trait Boxed { + function unbox(x: a) returns (word) ; } -instance Wrap:Boxed { - function unbox(x:Wrap) -> word { - match x { - | Wrap.Wrap(w) => return w; - } +impl Boxed { + function unbox(x: Wrap) returns (word) { + match (x) { +case Wrap.Wrap(w) { +return w; +} +} } } -function main() -> word { +function main() returns (word) { return Boxed.unbox(Wrap.Wrap(1)); } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.sol index d815c67e..13f3124a 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-answer-reuse/main.sol @@ -1,16 +1,16 @@ pragma no-patterson-condition Derived; -forall a . class a:Seed {} -forall a . class a:Derived {} +trait Seed {} +trait Derived {} -instance word:Seed {} +impl Seed {} -forall a . a:Seed => instance a:Derived {} +impl Derived where a: Seed {} -forall a . a:Derived, a:Derived => function needsDerivedTwice(x:a) -> () { +function needsDerivedTwice(x: a) where a: Derived, a: Derived { return (); } -function main() -> () { +function main() { return needsDerivedTwice(0); } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.sol index 689dee14..4d688c8f 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-given-order/main.sol @@ -1,23 +1,23 @@ pragma no-patterson-condition C; -forall a . class a:A {} -forall a . class a:B {} -forall a . class a:C {} +trait A {} +trait B {} +trait C {} -forall a . a:A, a:B => instance a:C {} +impl C where a: A, a: B {} -forall a . a:C => function needsC(x:a) -> () { +function needsC(x: a) where a: C { return (); } -forall a . a:A, a:B => function fromAB(x:a) -> () { +function fromAB(x: a) where a: A, a: B { return needsC(x); } -forall a . a:B, a:A => function fromBA(x:a) -> () { +function fromBA(x: a) where a: B, a: A { return needsC(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.sol index 29daa886..02beed75 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/local-class/tabled-residual-given/main.sol @@ -1,18 +1,18 @@ pragma no-patterson-condition Wanted; -forall a . class a:Known {} -forall a . class a:Wanted {} +trait Known {} +trait Wanted {} -forall a . a:Known => instance a:Wanted {} +impl Wanted where a: Known {} -forall a . a:Wanted => function needsWanted(x:a) -> () { +function needsWanted(x: a) where a: Wanted { return (); } -forall a . a:Known => function passKnown(x:a) -> () { +function passKnown(x: a) where a: Known { return needsWanted(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.sol index ba55aa25..48c89978 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/00answer/main.sol @@ -1,5 +1,5 @@ contract Answer { - public function main() -> word { + function main() public returns (word) { return 42; } } \ No newline at end of file diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.sol index df5b9377..aeeb720c 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/021not/main.sol @@ -1,21 +1,29 @@ contract Not { - data Bool = False | True; + enum Bool { False, True } - public function main() -> word { + function main() public returns (word) { return fromBool(bnot(Bool.False)); } - public function fromBool(b : Bool) -> word { - match(b) { - | Bool.False => return 0; - | Bool.True => return 1; - } + function fromBool(b: Bool) public returns (word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } - public function bnot(b : Bool) -> Bool { - match b { - | Bool.False => return Bool.True; - | Bool.True => return Bool.False; - } + function bnot(b: Bool) public returns (Bool) { + match (b) { +case Bool.False { +return Bool.True; +} +case Bool.True { +return Bool.False; +} +} } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.sol index 3ef65f35..85258483 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/022add/main.sol @@ -1,4 +1,4 @@ -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -7,7 +7,7 @@ function add(x : word, y : word) -> word { } contract Add1 { - public function main() -> word { + function main() public returns (word) { return add(40, 2); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.sol index a79ab49c..4043007d 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/024arith/main.sol @@ -1,6 +1,6 @@ -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -8,7 +8,7 @@ function add(x : word, y : word) -> word { return res; } -function sub(x : word, y : word) -> word { +function sub(x: word, y: word) returns (word) { let res: word; assembly { res := sub(x, y) @@ -16,7 +16,7 @@ function sub(x : word, y : word) -> word { return res; } -function div(x : word, y: word) -> word { +function div(x: word, y: word) returns (word) { let res: word; assembly { res := div(x, y) @@ -24,7 +24,7 @@ function div(x : word, y: word) -> word { return res; } -function sdiv(x : word, y: word) -> word { +function sdiv(x: word, y: word) returns (word) { let res: word; assembly { res := sdiv(x, y) @@ -32,7 +32,7 @@ function sdiv(x : word, y: word) -> word { return res; } -function mod(x : word, y: word) -> word { +function mod(x: word, y: word) returns (word) { let res: word; assembly { res := mod(x, y) @@ -40,7 +40,7 @@ function mod(x : word, y: word) -> word { return res; } -function smod(x : word, y: word) -> word { +function smod(x: word, y: word) returns (word) { let res: word; assembly { res := smod(x, y) @@ -48,7 +48,7 @@ function smod(x : word, y: word) -> word { return res; } -function exp(x : word, y: word) -> word { +function exp(x: word, y: word) returns (word) { let res: word; assembly { res := exp(x, y) @@ -58,7 +58,7 @@ function exp(x : word, y: word) -> word { contract Arith { - public function main() -> word { + function main() public returns (word) { return add(mod(sub(div(exp(2,18),4), 1), 16), 27); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.sol index d1de1135..379bb9a1 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/031maybe/main.sol @@ -1,16 +1,20 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(0, Option.Some(42)); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.sol index 1e83f44f..635bfe52 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/036wildcard/main.sol @@ -1,14 +1,18 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.Some(x) => return x; - | _ => return n; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.Some(x) { +return x; +} +default { +return n; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(7, Option.None); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.sol index b8180a0a..f0f1e963 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/041pair/main.sol @@ -1,12 +1,14 @@ contract Pair { - public function fst(p : (word, word)) -> word { - match p { - | (a,b) => return a; - } + function fst(p: (word, word)) public returns (word) { + match (p) { +case (a,b) { +return a; +} +} } - public function main() -> word { + function main() public returns (word) { return fst((1,0)); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.sol index 10c3724c..d2013eca 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/042triple/main.sol @@ -1,12 +1,14 @@ contract Triple { - public function asel(t : (word, word, word)) -> word { - match t { - | (a,b,c) => return c; - } + function asel(t: (word, word, word)) public returns (word) { + match (t) { +case (a,b,c) { +return c; +} +} } - public function main() -> word { + function main() public returns (word) { return asel((1,21,42)); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.sol index 576182e5..87529c81 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/047rgb/main.sol @@ -1,10 +1,16 @@ contract RGB { - data Color = R | G | B; - public function main() -> word { - match Color.B { - | Color.R => return 4; - | Color.G => return 2; - | Color.B => return 42; - } + enum Color { R, G, B } + function main() public returns (word) { + match (Color.B) { +case Color.R { +return 4; +} +case Color.G { +return 2; +} +case Color.B { +return 42; +} +} } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.sol index 5e33af5d..063a823e 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/048rgb2/main.sol @@ -1,13 +1,19 @@ contract RGB { - data Color = R | G | B; + enum Color { R, G, B } - public function fromEnum(c : Color) -> word { - match c { - | Color.R => return 4; - | Color.G => return 2; - | Color.B => return 42; - } + function fromEnum(c: Color) public returns (word) { + match (c) { +case Color.R { +return 4; +} +case Color.G { +return 2; +} +case Color.B { +return 42; +} +} } - public function main() -> word { return fromEnum(Color.B); } + function main() public returns (word) { return fromEnum(Color.B); } } diff --git a/crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.sol b/crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.sol index 8cfbaeca..2a7293b2 100644 --- a/crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/corpus/spec/049rgb3/main.sol @@ -1,17 +1,23 @@ -data RGB = Red(word) | Green(word) | Blue(word); +enum RGB { Red(word), Green(word), Blue(word) } contract RGB3 { - public function choose(c:RGB) -> word { + function choose(c: RGB) public returns (word) { let res : word; - match c { - | .Red(x) => assembly { res := add(x,1) } - | .Green(x) => assembly { res := add(x,2) } - | .Blue(x) => assembly { res := add(x,3) } - } + match (c) { +case .Red(x) { +assembly { res := add(x,1) } +} +case .Green(x) { +assembly { res := add(x,2) } +} +case .Blue(x) { +assembly { res := add(x,3) } +} +} return res; } - public function main() -> word { + function main() public returns (word) { choose(RGB.Green(42)) } } \ No newline at end of file diff --git a/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.sol b/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.sol index be43f937..abe459eb 100644 --- a/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_bounded_variable_pragma/main.sol @@ -1,7 +1,7 @@ pragma no-bounded-variable-condition Container; -data Box(a) = Box(word); -forall a . class a:Eq {} -forall a b . class a:Container(b) {} +enum Box { Box(word) } +trait Eq {} +trait Container {} -forall a c . c:Eq => instance Box(a):Container(a) {} +impl Container, a> where c: Eq {} diff --git a/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.sol b/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.sol index fe6247f8..99a6203c 100644 --- a/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/solver/class_scoped_patterson_pragma/main.sol @@ -1,6 +1,6 @@ pragma no-patterson-condition C1; -forall a . class a:C1 {} -forall a . class a:C2 {} +trait C1 {} +trait C2 {} -forall U . U:C1, U:C2 => instance U:C1 {} +impl C1 where U: C1, U: C2 {} diff --git a/crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.sol b/crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.sol index d8991856..3a5f4124 100644 --- a/crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/solver/global_coverage_pragma/main.sol @@ -1,6 +1,6 @@ pragma no-coverage-condition; -data Box(a) = Box(word); -forall a b . class a:MyClass(b) {} +enum Box { Box(word) } +trait MyClass {} -forall a b . instance Box(a):MyClass(b) {} +impl MyClass, b> {} diff --git a/crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.sol b/crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.sol index 46094edc..50ab5691 100644 --- a/crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/solver/obligation_order_improvement/main.sol @@ -9,35 +9,32 @@ // `R(word):Assign2(word)` in the next round. The reference compiler accepts // this program. -forall lhs rhs . -class lhs:Assign2(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign2 { + function assign(l: lhs, r: rhs) ; } -forall s o . -class s:Mk(o) { - function mk(x:s) -> o; +trait Mk { + function mk(x: s) returns (o) ; } -data R(a) = R(a); +enum R { R(a) } -forall a . -instance R(a):Assign2(a) { - function assign(l:R(a), r:a) -> () { +impl Assign2, a> { + function assign(l: R, r: a) { return (); } } -data S = S; +enum S { S } -instance S:Mk(R(word)) { - function mk(x:S) -> R(word) { +impl Mk> { + function mk(x: S) returns (R) { return R(0); } } contract Main { - public function main() -> word { + function main() public returns (word) { Assign2.assign(Mk.mk(S), 7); return 1; } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.sol index 62427041..4af52312 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/abstract_data_wildcard_match/main.sol @@ -1,7 +1,9 @@ -data Opaque; +enum Opaque {} -function keep(value: Opaque) -> Opaque { - match value { - | _ => return value; - } +function keep(value: Opaque) returns (Opaque) { + match (value) { +default { +return value; +} +} } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.sol index 7d3e4a50..41faf427 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/bytes_storage_roundtrip_full/main.sol @@ -1,17 +1,17 @@ -import std.{*}; +import * from std; contract C { value : bytes; - constructor(x : memory(bytes)) { + constructor(x : memory) { value = x; } - public function get() -> memory(bytes) { + function get() public returns (memory) { return value; } - function main() -> () { + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.sol index 69e5ac62..d5972494 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_constructor_entry_name/main.sol @@ -1,8 +1,8 @@ -import std.{*}; +import * from std; -function init_(x: word) -> word { return x; } +function init_(x: word) returns (word) { return x; } contract C { constructor(x: uint256) { let saved: word = init_(Typedef.rep(x)); } - function main() -> () { return (); } + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.sol index b5872c69..296427ee 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/compiler_private_dispatch_entry_name/main.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -function main(x: uint256) -> uint256 { return x; } +function main(x: uint256) returns (uint256) { return x; } contract C { - function call_top() -> uint256 { return main(uint256(1)); } - public function ping(x: uint256) -> uint256 { return x; } + function call_top() returns (uint256) { return main(uint256(1)); } + function ping(x: uint256) public returns (uint256) { return x; } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.sol index 88b0fb61..11e14a4f 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/compound_assignment_uses_class_method/main.sol @@ -1,16 +1,16 @@ -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -data Choice = Choice(word); +enum Choice { Choice(word) } -instance Choice:Add { - function add(l: Choice, r: Choice) -> Choice { +impl Add { + function add(l: Choice, r: Choice) returns (Choice) { return r; } } -function choose_right(x: Choice, y: Choice) -> Choice { +function choose_right(x: Choice, y: Choice) returns (Choice) { let result: Choice = x; result += y; return result; diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.sol index 713313bd..8183cadb 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/constructor_dynamic_string_full/main.sol @@ -1,17 +1,17 @@ -import std.{*}; +import * from std; contract C { value : string; - constructor(x : memory(string)) { + constructor(x : memory) { value = x; } - public function get() -> memory(string) { + function get() public returns (memory) { return value; } - function main() -> () { + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.sol index 3b15f848..71bd32fe 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_access/main.sol @@ -1,11 +1,11 @@ contract Simple { val : word; - public function getVal() -> word { + function getVal() public returns (word) { return val; } - function main() -> () { + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.sol index 94b19bc6..217f5df1 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/contract_field_initializer/main.sol @@ -1,4 +1,4 @@ contract C { x: word = 1; - function main() -> () { return (); } + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.sol index 5f98b4b6..ca388371 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/dispatch_field_method_collision/main.sol @@ -1,16 +1,16 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - data C = Foo; + enum C { Foo } allowance: uint256; - public function allowance() -> uint256 { + function allowance() public returns (uint256) { return allowance; } - public function Foo() -> uint256 { + function Foo() public returns (uint256) { return 1; } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.sol index dac1fb48..2fa6950a 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/dot_constructors_nested_patterns/main.sol @@ -1,12 +1,16 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function mkSome(x: word) -> Option { +function mkSome(x: word) returns (Option) { return .Some(x); } -function fromOption(x: Option) -> word { - match x { - | .Some(v) => return v; - | .None => return 0; - } +function fromOption(x: Option) returns (word) { + match (x) { +case .Some(v) { +return v; +} +case .None { +return 0; +} +} } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.sol index 8ff53dab..80775386 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/generated_dispatch_explicit_imports/main.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - public function echo(value: uint256) -> uint256 { return value; } + function echo(value: uint256) public returns (uint256) { return value; } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.sol b/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.sol index 3cde2b1a..fe63d647 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/lib.sol @@ -1,4 +1,4 @@ export { wrapper(wrapper), boxed(boxed) }; -data wrapper = wrapper(word); -data boxed = boxed(word); +enum wrapper { wrapper(word) } +enum boxed { boxed(word) } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.sol index 3c5cf062..55566562 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/import_same_name_ctor_unqualified/main.sol @@ -1,19 +1,23 @@ -import lib.{wrapper, boxed}; +import {wrapper, boxed} from lib; // Same-name constructors from a selective import stay legal unqualified in // both pattern and expression position. -function unwrap(u: wrapper) -> word { - match u { - | wrapper(w) => return w; - } +function unwrap(u: wrapper) returns (word) { + match (u) { +case wrapper(w) { +return w; +} +} } -function rebox(b: boxed) -> boxed { - match b { - | boxed(w) => return boxed(w); - } +function rebox(b: boxed) returns (boxed) { + match (b) { +case boxed(w) { +return boxed(w); +} +} } -function main() -> word { +function main() returns (word) { return unwrap(wrapper(3)); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.sol b/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.sol index aac838be..0bcfaff1 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/lib.sol @@ -1,18 +1,17 @@ export { Marker, Box, Phantom }; -forall a . -class a:Marker { - function mark(x: a) -> word; +trait Marker { + function mark(x: a) returns (word) ; } -instance word:Marker { - function mark(x: word) -> word { +impl Marker { + function mark(x: word) returns (word) { return x; } } #[derive(Marker)] -data Box(a) = Box(a); +enum Box { Box(a) } #[derive(Marker)] -data Phantom(a) = Phantom(word); +enum Phantom { Phantom(word) } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.sol index 7498b9a5..5bef8513 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/imported_derived_class/main.sol @@ -1,12 +1,11 @@ -import lib.{Marker, Box, Phantom}; +import {Marker, Box, Phantom} from lib; // The derived instance is declared in an imported module and recursively // discharges the class constraint for every declared type parameter. -function markBox(x: Box(word)) -> word { +function markBox(x: Box) returns (word) { return Marker.mark(x); } -forall a . a:Marker => -function markPhantom(x: Phantom(a)) -> word { +function markPhantom(x: Phantom) returns (word) where a: Marker { return Marker.mark(x); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.sol index c72f6735..420e8ada 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/integer_literal_pattern/main.sol @@ -1,6 +1,10 @@ -function classify(n : integer) -> integer { - match n { - | 0 => return 1; - | _ => return n; - } +function classify(n: integer) returns (integer) { + match (n) { +case 0 { +return 1; +} +default { +return n; +} +} } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.sol index f583276c..4892ce61 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/lambda_expected_function_type/main.sol @@ -1,9 +1,9 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function apply(f: (word) -> Option) -> Option { +function apply(f: function(word) returns (Option)) returns (Option) { return f(1); } -function main() -> Option { +function main() returns (Option) { return apply(lam(x) { return .Some(x); }); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.sol index 822b95b9..f4408331 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/literal_poly_noclass/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let y : word = 7; return y; } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.sol index f23c1d5d..9bb5db00 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/nested_generic_adt_constructor/main.sol @@ -1,11 +1,11 @@ -contract Box(t) { - data Option(u) = None | Some(u); +contract Box { + enum Option { None, Some(u) } - function mk(x: word) -> Option(word) { + function mk(x: word) returns (Option) { return .Some(x); } - function main() -> () { + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.sol index 95235b0f..d476214b 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/qualified_and_builtin_bool_patterns/main.sol @@ -1,19 +1,27 @@ -data flag = off | on; +enum flag { off, on } -function pick(f: flag) -> word { - match f { - | flag.off => return 0; - | flag.on => return 1; - } +function pick(f: flag) returns (word) { + match (f) { +case flag.off { +return 0; +} +case flag.on { +return 1; +} +} } -function flip(b: bool) -> word { - match b { - | true => return 1; - | false => return 0; - } +function flip(b: bool) returns (word) { + match (b) { +case true { +return 1; +} +case false { +return 0; +} +} } -function main() -> word { +function main() returns (word) { return primAddWord(pick(flag.on), flip(true)); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.sol index ce69e7dd..cda664f3 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/same_name_nullary_ctor_pattern/main.sol @@ -1,19 +1,25 @@ -data thing = thing; -data m = m | k; +enum thing { thing } +enum m { m, k } -function pickThing(t: thing) -> word { - match t { - | thing => return 7; - } +function pickThing(t: thing) returns (word) { + match (t) { +case thing { +return 7; +} +} } -function pickM(x: m) -> word { - match x { - | m => return 1; - | m.k => return 2; - } +function pickM(x: m) returns (word) { + match (x) { +case m { +return 1; +} +case m.k { +return 2; +} +} } -function main() -> word { +function main() returns (word) { return primAddWord(pickThing(thing), pickM(m.k)); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.sol index a6b0dc64..cac1c5a0 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/self_recursive_data/main.sol @@ -1,5 +1,5 @@ -data A = A(A) | Z; +enum A { A(A), Z } -function f(x: A) -> word { +function f(x: A) returns (word) { return 0; } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.sol index d7f620fb..abab0a4c 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/std_universe_eq_ord/main.sol @@ -1,29 +1,29 @@ -import std.{Eq, Ord, absurd}; +import {Eq, Ord, absurd} from std; -function eqUnit(x : (), y : ()) -> bool { +function eqUnit(x: (), y: ()) returns (bool) { return Eq.eq(x, y); } -function eqSum(x : sum(word, word), y : sum(word, word)) -> bool { +function eqSum(x: sum, y: sum) returns (bool) { return Eq.eq(x, y); } -function eqProduct(x : (word, word), y : (word, word)) -> bool { +function eqProduct(x: (word, word), y: (word, word)) returns (bool) { return Eq.eq(x, y); } -function ordUnit(x : (), y : ()) -> bool { +function ordUnit(x: (), y: ()) returns (bool) { return Ord.gt(x, y); } -function ordSum(x : sum(word, word), y : sum(word, word)) -> bool { +function ordSum(x: sum, y: sum) returns (bool) { return Ord.gt(x, y); } -function ordProduct(x : (word, word), y : (word, word)) -> bool { +function ordProduct(x: (word, word), y: (word, word)) returns (bool) { return Ord.gt(x, y); } -function bottomWord() -> word { +function bottomWord() returns (word) { return absurd(); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.sol index 1279816c..2a66e66a 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/std_word_minmax/main.sol @@ -1,9 +1,9 @@ -import std.{Typedef, maxWord, minWord, uint256}; +import {Typedef, maxWord, minWord, uint256} from std; -function minUint(a: uint256, b: uint256) -> uint256 { +function minUint(a: uint256, b: uint256) returns (uint256) { return uint256(minWord(Typedef.rep(a), Typedef.rep(b))); } -function maxUint(a: uint256, b: uint256) -> uint256 { +function maxUint(a: uint256, b: uint256) returns (uint256) { return uint256(maxWord(Typedef.rep(a), Typedef.rep(b))); } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.sol index 6ab1d8c1..437b70cf 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_uint256/main.sol @@ -1,24 +1,24 @@ -data mapping(key, value) = mapping(word); -data uint256 = uint256(word); +enum mapping { mapping(word) } +enum uint256 { uint256(word) } -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Sub { - function sub(l: t, r: t) -> t; +trait Sub { + function sub(l: t, r: t) returns (t) ; } -instance word:Add { - function add(l: word, r: word) -> word { return l; } +impl Add { + function add(l: word, r: word) returns (word) { return l; } } -instance word:Sub { - function sub(l: word, r: word) -> word { return l; } +impl Sub { + function sub(l: word, r: word) returns (word) { return l; } } -instance uint256:Add { - function add(l: uint256, r: uint256) -> uint256 { return l; } +impl Add { + function add(l: uint256, r: uint256) returns (uint256) { return l; } } contract C { - m: mapping(word, uint256); - function f(k: word, v: uint256) -> () { m[k] += v; } - function main() -> () { return (); } + m: mapping(word => uint256); + function f(k: word, v: uint256) { m[k] += v; } + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.sol index 7d22153f..0b3a1aa0 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/storage_mapping_compound_add_word/main.sol @@ -1,24 +1,24 @@ -data mapping(key, value) = mapping(word); -data uint256 = uint256(word); +enum mapping { mapping(word) } +enum uint256 { uint256(word) } -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Sub { - function sub(l: t, r: t) -> t; +trait Sub { + function sub(l: t, r: t) returns (t) ; } -instance word:Add { - function add(l: word, r: word) -> word { return l; } +impl Add { + function add(l: word, r: word) returns (word) { return l; } } -instance word:Sub { - function sub(l: word, r: word) -> word { return l; } +impl Sub { + function sub(l: word, r: word) returns (word) { return l; } } -instance uint256:Add { - function add(l: uint256, r: uint256) -> uint256 { return l; } +impl Add { + function add(l: uint256, r: uint256) returns (uint256) { return l; } } contract C { - m: mapping(word, word); - function f(k: word) -> () { m[k] += 1; } - function main() -> () { return (); } + m: mapping(word => word); + function f(k: word) { m[k] += 1; } + function main() { return (); } } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.sol index c904787b..a9fa2e0e 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/storage_word_assignment_full/main.sol @@ -1,17 +1,16 @@ -data storage(t) = storage(word); +enum storage { storage(word) } -forall a b. -class a:CanStore(b) { - function store(r:a, v:b) -> (); - function load(r:a) -> b; +trait CanStore { + function store(r: a, v: b) ; + function load(r: a) returns (b) ; } -instance storage(word):CanStore(word) { - function store(dst: storage(word), src: word) -> () { +impl CanStore, word> { + function store(dst: storage, src: word) { return (); } - function load(src: storage(word)) -> word { + function load(src: storage) returns (word) { return 0; } } @@ -19,11 +18,11 @@ instance storage(word):CanStore(word) { contract StorageWordAssign { x: word; - function setx() -> () { + function setx() { x = 8; } - public function main() -> word { + function main() public returns (word) { setx(); return x; } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol index a0f12c0d..f07632cc 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol @@ -1,51 +1,51 @@ -forall t . class t:Add { - function add(l:t, r:t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Mod { - function mod(l:t, r:t) -> t; +trait Mod { + function mod(l: t, r: t) returns (t) ; } -forall t . class t:BitAnd { - function band(l:t, r:t) -> t; +trait BitAnd { + function band(l: t, r: t) returns (t) ; } -forall t . class t:BitOr { - function bor(l:t, r:t) -> t; +trait BitOr { + function bor(l: t, r: t) returns (t) ; } -forall t . class t:BitXor { - function bxor(l:t, r:t) -> t; +trait BitXor { + function bxor(l: t, r: t) returns (t) ; } -forall t . class t:Ord { - function gt(l:t, r:t) -> bool; +trait Ord { + function gt(l: t, r: t) returns (bool) ; } -forall t . class t:Eq { - function eq(l:t, r:t) -> bool; +trait Eq { + function eq(l: t, r: t) returns (bool) ; } -instance word:Add { - function add(l:word, r:word) -> word { +impl Add { + function add(l: word, r: word) returns (word) { return primAddWord(l, r); } } -instance word:Mod { - function mod(l:word, r:word) -> word { +impl Mod { + function mod(l: word, r: word) returns (word) { return l; } } -instance word:BitAnd { - function band(l:word, r:word) -> word { +impl BitAnd { + function band(l: word, r: word) returns (word) { return l; } } -instance word:BitOr { - function bor(l:word, r:word) -> word { +impl BitOr { + function bor(l: word, r: word) returns (word) { return l; } } From 5773e6056f34abe6e0f0a9fac950210907f35cb7 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 038/110] Switch the compiler and fixtures to canonical syntax: hir ty fixtures Co-authored-by: Codex --- .../main.sol | 24 ++++++++++--------- .../fixtures/ok/typeck/yul_keccak256/main.sol | 2 +- .../ok/yul_polymorphic_terminators/main.sol | 12 +++++----- .../solver/derived_abi_imported/abi.sol | 20 ++++++++-------- .../solver/derived_abi_imported/main.sol | 6 ++--- .../solver/derived_abi_imported/types.sol | 4 ++-- .../derived_abi_imported_inactive/abi.sol | 20 ++++++++-------- .../derived_abi_imported_inactive/generic.sol | 2 +- .../derived_abi_imported_inactive/main.sol | 8 +++---- .../derived_abi_imported_inactive/types.sol | 4 ++-- .../derived_reexport_visibility/base.sol | 4 ++-- .../derived_reexport_visibility/classes.sol | 2 +- .../derived_reexport_visibility/main.sol | 6 ++--- .../solver/derived_storage_imported/main.sol | 2 +- .../storage_support.sol | 14 +++++------ .../solver/derived_storage_imported/types.sol | 4 ++-- .../generic.sol | 2 +- .../main.sol | 6 ++--- .../storage_support.sol | 14 +++++------ .../types.sol | 4 ++-- .../main.sol | 4 ++-- .../storage_support.sol | 14 +++++------ .../types.sol | 4 ++-- 23 files changed, 92 insertions(+), 90 deletions(-) diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol index f07632cc..dc46aecc 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/tuples_if_lambdas_for_loops_and_compound_assigns/main.sol @@ -50,29 +50,29 @@ impl BitOr { } } -instance word:BitXor { - function bxor(l:word, r:word) -> word { +impl BitXor { + function bxor(l: word, r: word) returns (word) { return l; } } -instance word:Ord { - function gt(l:word, r:word) -> bool { +impl Ord { + function gt(l: word, r: word) returns (bool) { return true; } } -instance word:Eq { - function eq(l:word, r:word) -> bool { +impl Eq { + function eq(l: word, r: word) returns (bool) { return true; } } -function lt(l:word, r:word) -> bool { +function lt(l: word, r: word) returns (bool) { return Ord.gt(r, l); } -function main() -> word { +function main() returns (word) { let f = lam(x: word) { return x; }; let acc : word = 0; for (let i : word = 0; i < 3; i = i + 1) { @@ -83,7 +83,9 @@ function main() -> word { acc %= 5; } let t : (word, word) = (acc, 1); - match t { - | (x, _) => return if x == 0 then 1 else x; - } + match (t) { +case (x, _) { +return x == 0 ? 1 : x; +} +} } diff --git a/crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.sol b/crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.sol index a4ff7b09..cd818abe 100644 --- a/crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/typeck/yul_keccak256/main.sol @@ -1,4 +1,4 @@ -function hash_word(value: word) -> word { +function hash_word(value: word) returns (word) { let result: word; assembly { mstore(0, value) diff --git a/crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol b/crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol index f5d04b75..5bc872f6 100644 --- a/crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol +++ b/crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol @@ -1,31 +1,31 @@ -forall a . function viaStop() -> a { +function viaStop() returns (a) { assembly { stop() } } -forall a . function viaInvalid() -> a { +function viaInvalid() returns (a) { assembly { invalid() } } -forall a . function viaSelfdestruct(beneficiary : word) -> a { +function viaSelfdestruct(beneficiary: word) returns (a) { assembly { selfdestruct(beneficiary) } } -forall a . function viaRevert() -> a { +function viaRevert() returns (a) { assembly { revert(0, 0) } } -function useWord(value : word) -> () {} +function useWord(value: word) {} contract Terminators { - public function main() -> () { + function main() public { useWord(viaStop()); useWord(viaInvalid()); useWord(viaSelfdestruct(0)); diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.sol index 847dac79..af823e53 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/abi.sol @@ -12,15 +12,15 @@ export { Reader }; -forall a rep . class a:Generic(rep) {} -forall self . class self:ABIDeriving {} -forall self . class self:ABIAttribs {} -forall decoder decoded . class decoder:ABIDecode(decoded) {} -forall reader . class reader:WordReader {} +trait Generic {} +trait ABIDeriving {} +trait ABIAttribs {} +trait ABIDecode {} +trait WordReader {} -data ABIDecoder(ty, reader) = ABIDecoder(reader); -data Reader = Reader; +enum ABIDecoder { ABIDecoder(reader) } +enum Reader { Reader } -instance Reader:WordReader {} -instance word:ABIAttribs {} -instance ABIDecoder(word, Reader):ABIDecode(word) {} +impl WordReader {} +impl ABIAttribs {} +impl ABIDecode, word> {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.sol index 3853b860..c8325e64 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/main.sol @@ -1,6 +1,6 @@ -import abi.{*}; -import types.{Box}; +import * from abi; +import {Box} from types; -function keepBoxVisible(x: Box(word)) -> Box(word) { +function keepBoxVisible(x: Box) returns (Box) { return x; } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.sol index 472be27d..f7e4bc85 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported/types.sol @@ -1,5 +1,5 @@ -import abi.{*}; +import * from abi; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.sol index 5ec8c0a4..44fa17bc 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/abi.sol @@ -2,7 +2,7 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -import generic.{Generic}; +import {Generic} from generic; export { ABIDeriving, @@ -13,14 +13,14 @@ export { Reader }; -forall self . class self:ABIDeriving {} -forall self . class self:ABIAttribs {} -forall decoder decoded . class decoder:ABIDecode(decoded) {} -forall reader . class reader:WordReader {} +trait ABIDeriving {} +trait ABIAttribs {} +trait ABIDecode {} +trait WordReader {} -data ABIDecoder(ty, reader) = ABIDecoder(reader); -data Reader = Reader; +enum ABIDecoder { ABIDecoder(reader) } +enum Reader { Reader } -instance Reader:WordReader {} -instance word:ABIAttribs {} -instance ABIDecoder(word, Reader):ABIDecode(word) {} +impl WordReader {} +impl ABIAttribs {} +impl ABIDecode, word> {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.sol index ba757d4f..8e6668fe 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/generic.sol @@ -1,3 +1,3 @@ export { Generic }; -forall a rep . class a:Generic(rep) {} +trait Generic {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.sol index c5130dbc..7fd19909 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/main.sol @@ -1,7 +1,7 @@ -import generic.{Generic}; -import abi.{*}; -import types.{Box}; +import {Generic} from generic; +import * from abi; +import {Box} from types; -function keepBoxVisible(x: Box(word)) -> Box(word) { +function keepBoxVisible(x: Box) returns (Box) { return x; } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.sol b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.sol index 949dd6da..2d1d3bd8 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_abi_imported_inactive/types.sol @@ -1,6 +1,6 @@ -import generic.{Generic}; +import {Generic} from generic; export { Box(*) }; // Generic is visible here, but the ABIDeriving marker deliberately is not. -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.sol b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.sol index 36c4cd8f..2175dde5 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/base.sol @@ -1,5 +1,5 @@ -import classes.{Visible}; +import {Visible} from classes; export { Reexported }; -#[derive(Visible)] data Reexported; +#[derive(Visible)] enum Reexported {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.sol b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.sol index 524a9f17..f9b00433 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/classes.sol @@ -1,3 +1,3 @@ export { Visible }; -forall a . class a:Visible {} +trait Visible {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.sol b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.sol index 68112c7f..f6069135 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_reexport_visibility/main.sol @@ -1,6 +1,6 @@ -import api.{Reexported}; -import classes.{Visible}; +import {Reexported} from api; +import {Visible} from classes; -function keepTypeVisible(x: Reexported) -> Reexported { +function keepTypeVisible(x: Reexported) returns (Reexported) { return x; } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.sol index cc38035b..ce1c8090 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/main.sol @@ -1,2 +1,2 @@ -import storage_support.{StorageSize, CanStore, storage}; +import {StorageSize, CanStore, storage} from storage_support; import types; diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.sol index 6af7d9db..f77343a6 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/storage_support.sol @@ -4,12 +4,12 @@ pragma no-coverage-condition; export { Generic, StorageDeriving, StorageSize, CanStore, storage(*) }; -forall a rep . class a:Generic(rep) {} -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize {} -forall slot value . class slot:CanStore(value) {} +trait Generic {} +trait StorageDeriving {} +trait StorageSize {} +trait CanStore {} -data storage(ty) = storage(word); +enum storage { storage(word) } -instance word:StorageSize {} -instance storage(word):CanStore(word) {} +impl StorageSize {} +impl CanStore, word> {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.sol index c8260a6c..b000e6cb 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported/types.sol @@ -1,5 +1,5 @@ -import storage_support.{*}; +import * from storage_support; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.sol index ba757d4f..8e6668fe 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/generic.sol @@ -1,3 +1,3 @@ export { Generic }; -forall a rep . class a:Generic(rep) {} +trait Generic {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.sol index 8005e46d..2ea17a06 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/main.sol @@ -1,3 +1,3 @@ -import generic.{Generic}; -import storage_support.{*}; -import types.{Box}; +import {Generic} from generic; +import * from storage_support; +import {Box} from types; diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.sol index 3dec0d35..548104bd 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/storage_support.sol @@ -2,15 +2,15 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -import generic.{Generic}; +import {Generic} from generic; export { StorageDeriving, StorageSize, CanStore, storage(*) }; -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize {} -forall slot value . class slot:CanStore(value) {} +trait StorageDeriving {} +trait StorageSize {} +trait CanStore {} -data storage(ty) = storage(word); +enum storage { storage(word) } -instance word:StorageSize {} -instance storage(word):CanStore(word) {} +impl StorageSize {} +impl CanStore, word> {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.sol index 89fcb452..64f54c0b 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_imported_inactive/types.sol @@ -1,6 +1,6 @@ -import generic.{Generic}; +import {Generic} from generic; export { Box(*) }; // Generic is visible here, but StorageDeriving deliberately is not. -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.sol index 382c459a..f40b6bf6 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/main.sol @@ -1,2 +1,2 @@ -import api.{Box}; -import storage_support.{StorageSize, CanStore, storage}; +import {Box} from api; +import {StorageSize, CanStore, storage} from storage_support; diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.sol index 6af7d9db..f77343a6 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/storage_support.sol @@ -4,12 +4,12 @@ pragma no-coverage-condition; export { Generic, StorageDeriving, StorageSize, CanStore, storage(*) }; -forall a rep . class a:Generic(rep) {} -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize {} -forall slot value . class slot:CanStore(value) {} +trait Generic {} +trait StorageDeriving {} +trait StorageSize {} +trait CanStore {} -data storage(ty) = storage(word); +enum storage { storage(word) } -instance word:StorageSize {} -instance storage(word):CanStore(word) {} +impl StorageSize {} +impl CanStore, word> {} diff --git a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.sol b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.sol index c8260a6c..b000e6cb 100644 --- a/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.sol +++ b/crates/hir-ty/tests/fixtures/solver/derived_storage_reexport_visibility/types.sol @@ -1,5 +1,5 @@ -import storage_support.{*}; +import * from storage_support; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } From 709c865630e76d23c518e90e563f94e8131e4398 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 039/110] Switch the compiler and fixtures to canonical syntax: hull Co-authored-by: Codex --- crates/hull/src/emit/mod.rs | 2 +- crates/hull/src/emit/storage.rs | 2 +- crates/hull/tests/smoke.rs | 580 +++++++++++++++++--------------- crates/hull/tests/snapshots.rs | 4 +- 4 files changed, 308 insertions(+), 280 deletions(-) diff --git a/crates/hull/src/emit/mod.rs b/crates/hull/src/emit/mod.rs index a18da6c4..d2c7b517 100644 --- a/crates/hull/src/emit/mod.rs +++ b/crates/hull/src/emit/mod.rs @@ -64,7 +64,7 @@ const STORAGE_ARRAY_SLOT_HELPER: &str = "__solcore_storage_array_slot"; const STORAGE_MAPPING_VALUE_HELPER: &str = "__solcore_storage_mapping_value"; const MEMORY_ARRAY_INDEX_HELPER: &str = "__solcore_memory_array_index"; /// Error selector of the reference std's `Unimplemented` error -/// (`Error(0x6e128399)` raised by `unimplemented()` in std.solc). +/// (`Error(0x6e128399)` raised by `unimplemented()` in std.sol). const UNIMPLEMENTED_SELECTOR: &str = "0x6e128399"; const OUT_OF_BOUNDS_SELECTOR: &str = "0xb4120f14"; diff --git a/crates/hull/src/emit/storage.rs b/crates/hull/src/emit/storage.rs index ed34854b..9c990406 100644 --- a/crates/hull/src/emit/storage.rs +++ b/crates/hull/src/emit/storage.rs @@ -256,7 +256,7 @@ impl<'db> Emitter<'db> { } } - /// Mirrors the reference std's `storage(mapping(k, v)) : CanStore` + /// Mirrors the reference std's `storage v)>: CanStore` /// instance, whose `load`/`store` bodies are `unimplemented()`: touching a /// whole mapping field as a value compiles, but reverts at runtime with /// the std `Unimplemented` error, nominally yielding the field's base diff --git a/crates/hull/tests/smoke.rs b/crates/hull/tests/smoke.rs index c41d5abd..65f2337f 100644 --- a/crates/hull/tests/smoke.rs +++ b/crates/hull/tests/smoke.rs @@ -100,27 +100,27 @@ fn specialization_corpus_subset_emits_and_checks() { let cases = [ ( "spec/01id", - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/01id.solc"), + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol"), ), ( "spec/00answer", - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.solc"), + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol"), ), ( "spec/022add", - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/022add.solc"), + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol"), ), ( "spec/024arith", - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.solc"), + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol"), ), ( "spec/031maybe", - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.solc"), + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol"), ), ( "spec/047rgb", - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.solc"), + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol"), ), ]; let mut failures = Vec::new(); @@ -181,11 +181,11 @@ fn objectless_string_materializers_are_content_deduplicated() { let (db, output) = specialize_src_with_std( "objectless_string_materializer", r#" -import std.{memory, string}; +import {memory, string} from std; -function alpha() -> memory(string) { return "alpha"; } -function beta() -> memory(string) { return "beta"; } -function main() -> memory(string) { +function alpha() returns (memory) { return "alpha"; } +function beta() returns (memory) { return "beta"; } +function main() returns (memory) { alpha(); beta(); return "alpha"; @@ -215,10 +215,10 @@ fn contract_objects_receive_their_reachable_string_materializer() { let (db, output) = specialize_src_with_std( "contract_string_materializers", r#" -import std.{memory, string}; +import {memory, string} from std; -contract A { function main() -> memory(string) { return "shared"; } } -contract B { function main() -> memory(string) { return "shared"; } } +contract A { function main() returns (memory) { return "shared"; } } +contract B { function main() returns (memory) { return "shared"; } } "#, ); assert_eq!(output.diagnostics, Vec::new()); @@ -243,13 +243,13 @@ fn canonical_revert_literal_lowers_to_message_revert() { let hull = pretty_src_hull_with_std( "revert_literal", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract WithFallback { - public function answer() -> uint256 { return uint256(42); } + function answer() public returns (uint256) { return uint256(42); } - fallback() -> () { + fallback() { revertLit("fallback-was-called"); } } @@ -268,11 +268,11 @@ fn let_initializer_revert_literal_lowers_to_message_revert() { let hull = pretty_src_hull_with_std( "let_revert_literal", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - fallback() -> () { + fallback() { let unreachable : () = revertLit("let-initializer"); return unreachable; } @@ -289,14 +289,14 @@ fn nested_revert_literal_lowers_before_its_containing_expression() { let hull = pretty_src_hull_with_std( "nested_revert_literal", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - fallback() -> () { + fallback() { let raw : word; assembly { raw := callvalue() } - let result : () = if (raw == 0) then revertLit("nested") else (); + let result : () = ((raw == 0) ? revertLit("nested") : ()); return result; } } @@ -317,7 +317,7 @@ fn contract_without_runtime_main_defers_dispatch_to_specialization() { "dispatch_word", r#" contract C { - function main() -> () {} + function main() returns () {} } "#, ); @@ -348,7 +348,7 @@ contract C { fn dispatch_basic_fixture_uses_std_dispatch_main() { solcore_test_utils::run_in_large_stack(|| { let fixture = repo_root() - .join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.solc"); + .join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol"); let (db, output) = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); let emitted = emit_module(db, &output.module, EmitOptions::default()); @@ -373,7 +373,7 @@ fn dispatch_basic_fixture_uses_std_dispatch_main() { fn deployment_objects_copy_runtime_and_guard_constructor_value() { let repo = repo_root(); let fixture = repo.join( - "crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.solc", + "crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol", ); let (db, output) = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); @@ -389,7 +389,7 @@ fn deployment_objects_copy_runtime_and_guard_constructor_value() { ); let fixture = repo - .join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.solc"); + .join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol"); let (db, output) = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); let emitted = emit_module(db, &output.module, EmitOptions::default()); @@ -420,8 +420,8 @@ fn deployment_objects_copy_runtime_and_guard_constructor_value() { .expect("runtime object"); assert!(!runtime.contains("_start"), "{hull}"); - let fixture = repo - .join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.solc"); + let fixture = + repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol"); let (db, output) = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); let emitted = emit_module(db, &output.module, EmitOptions::default()); @@ -442,7 +442,7 @@ fn importless_nullary_constructor_uses_overlay_deployment_entry() { contract C { constructor() {} - function main() -> () { + function main() returns () { return (); } } @@ -468,15 +468,15 @@ fn std_constructor_overlay_decodes_appended_arguments_in_deployment_closure() { let (db, output) = specialize_src_with_std( "std_ctor_overlay_args", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor(config : uint256) { let saved_config = config; } - public function echo(config : uint256) -> uint256 { return config; } + function echo(config : uint256) public returns (uint256) { return config; } } "#, ); @@ -519,11 +519,11 @@ fn std_dispatch_address_decode_rejects_dirty_high_bits() { let (db, output) = specialize_src_with_std( "std_address_dispatch", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - public function id_address(a : address) -> address { return a; } + function id_address(a : address) public returns (address) { return a; } } "#, ); @@ -547,12 +547,12 @@ fn std_dispatch_explicit_fallback_stops_after_execution() { let (db, output) = specialize_src_with_std( "std_fallback_dispatch", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - public function answer() -> uint256 { return uint256(42); } - fallback() -> () {} + function answer() public returns (uint256) { return uint256(42); } + fallback() {} } "#, ); @@ -568,7 +568,7 @@ contract C { fn for_loop_emits_hull_for_and_loop_control() { let repo = repo_root(); let fixture = - repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.solc"); + repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol"); let (db, output) = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); let emitted = emit_module(db, &output.module, EmitOptions::default()); @@ -599,7 +599,7 @@ fn for_loop_emits_hull_for_and_loop_control() { fn word_storage_fixture_reaches_word_slot_ops() { let repo = repo_root(); let fixture = - repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.solc"); + repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol"); let (db, output) = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); let emitted = emit_module(db, &output.module, EmitOptions::default()); @@ -620,22 +620,22 @@ fn word_storage_fixture_reaches_word_slot_ops() { #[test] fn single_constructor_matches_project_payloads_from_scrutinee() { - assert_fixture_emits_and_checks("cases/encoder1.solc"); - assert_fixture_has_no_unbound_alt("cases/mptc-multi-instance.solc"); + assert_fixture_emits_and_checks("cases/encoder1.sol"); + assert_fixture_has_no_unbound_alt("cases/mptc-multi-instance.sol"); } #[test] fn decision_tree_match_lowering_preserves_priority_nested_and_multi_scrutinee_cases() { for fixture in [ - "spec/033join.solc", - "spec/038food0.solc", - "cases/Option.solc", - "cases/option2.solc", - "cases/dot-pattern-nested-constructor.solc", - "cases/Logic.solc", - "cases/Ackermann.solc", - "cases/false-redundant-warning.solc", - "cases/super-class.solc", + "spec/033join.sol", + "spec/038food0.sol", + "cases/Option.sol", + "cases/option2.sol", + "cases/dot-pattern-nested-constructor.sol", + "cases/Logic.sol", + "cases/Ackermann.sol", + "cases/false-redundant-warning.sol", + "cases/super-class.sol", ] { assert_fixture_emits_without_match_lowering_regressions(fixture); } @@ -647,21 +647,25 @@ fn decision_tree_shape_preserves_specific_constructors_before_wildcard_defaults( "dwarves_runtime_shape", r#" contract Dwarves { - data Dwarf = Doc | Grumpy | Sleepy | Bashful | Happy | Sneezy | Dopey; + enum Dwarf {Doc , Grumpy , Sleepy , Bashful , Happy , Sneezy , Dopey} - public function fromEnum(c : Dwarf) -> word { + function fromEnum(c : Dwarf) public returns (word) { assembly { mstore(0, 0) } - match c { - | Dwarf.Doc => return 1; - | Dwarf.Grumpy => return 2; - | Dwarf.Sleepy => return 3; - | Dwarf.Bashful => return 4; - | Dwarf.Happy => return 5; - | _ => return 0; + match (c) { + case Dwarf.Doc { + return 1; + } + case Dwarf.Grumpy { return 2; } + case Dwarf.Sleepy { return 3; } + case Dwarf.Bashful { return 4; } + case Dwarf.Happy { return 5; } + default { + return 0; + } } } - function main() -> word { return fromEnum(Dwarf.Happy); } + function main() returns (word) { return fromEnum(Dwarf.Happy); } } "#, ); @@ -683,7 +687,7 @@ contract Dwarves { ], ); - let food0_actual = pretty_fixture_hull("spec/038food0.solc"); + let food0_actual = pretty_fixture_hull("spec/038food0.sol"); assert!( food0_actual.contains("function 038food0_FoodContract_main"), "{food0_actual}" @@ -693,20 +697,24 @@ contract Dwarves { let food0_shape = pretty_src_hull( "food0_runtime_shape", r#" -data Food = Curry | Beans | Other; -data CFood = Red(Food) | Green(Food) | Nocolor; +enum Food {Curry , Beans , Other} +enum CFood {Red(Food) , Green(Food) , Nocolor} -function fromEnum(x : CFood) -> word { +function fromEnum(x : CFood) returns (word) { assembly { mstore(0, 0) } - match x { - | CFood.Red(Food.Curry) => return 1; - | CFood.Green(Food.Beans) => return 42; - | _ => return 3; + match (x) { + case CFood.Red(Food.Curry) { + return 1; + } + case CFood.Green(Food.Beans) { return 42; } + default { + return 3; + } } } contract FoodContract { - function main() -> word { return fromEnum(CFood.Green(Food.Beans)); } + function main() returns (word) { return fromEnum(CFood.Green(Food.Beans)); } } "#, ); @@ -723,7 +731,7 @@ contract FoodContract { ], ); - let food = pretty_fixture_hull("spec/039food.solc"); + let food = pretty_fixture_hull("spec/039food.sol"); assert!( food.contains("function 039food_FoodContract_main") && food.contains("return 42"), "{food}" @@ -732,18 +740,22 @@ contract FoodContract { let wildcard_after_ctor = pretty_src_hull( "wildcard_after_ctor", r#" -data Tiny = A | B | C; +enum Tiny {A , B , C} contract C { - public function pick(t : Tiny) -> word { + function pick(t : Tiny) public returns (word) { assembly { mstore(0, 0) } - match t { - | Tiny.B => return 2; - | _ => return 9; + match (t) { + case Tiny.B { + return 2; + } + default { + return 9; + } } } - function main() -> word { return pick(Tiny.B); } + function main() returns (word) { return pick(Tiny.B); } } "#, ); @@ -757,9 +769,9 @@ contract C { #[test] fn cited_terminal_yul_fixtures_do_not_fail_missing_terminator() { for fixture in [ - "cases/yul-return.solc", - "cases/undefined.solc", - "cases/copytomem.solc", + "cases/yul-return.sol", + "cases/undefined.sol", + "cases/copytomem.sol", ] { let kinds = check_fixture_kinds(fixture); assert!( @@ -773,7 +785,7 @@ fn cited_terminal_yul_fixtures_do_not_fail_missing_terminator() { #[test] fn recursive_adt_layouts_are_cycle_safe() { - for fixture in ["cases/PeanoMatch.solc", "cases/listid.solc"] { + for fixture in ["cases/PeanoMatch.sol", "cases/listid.sol"] { assert_fixture_emits_and_checks(fixture); } } @@ -783,10 +795,14 @@ fn runtime_string_match_is_rejected_before_emission() { let (_db, output) = specialize_src( "string_literal_match", r#" -function main(s : string) -> word { - match s { - | "a" => return 1; - | _ => return 2; +function main(s : string) returns (word) { + match (s) { + case "a" { + return 1; + } + default { + return 2; + } } } "#, @@ -813,27 +829,33 @@ fn out_of_range_word_literals_wrap_in_hull_exprs_and_patterns() { "word_literal_wrap", &format!( r#" -import std.{{*}}; -import std.dispatch.{{*}}; +import * from std; +import * from std.dispatch; contract C {{ - function exact() -> word {{ + function exact() returns (word) {{ return {TWO_256}; }} - function plus() -> word {{ + function plus() returns (word) {{ return {TWO_256_PLUS_ONE}; }} - function pick(x : word) -> word {{ - match x {{ - | {TWO_256} => return 10; - | {TWO_256_PLUS_ONE} => return 11; - | _ => return 12; + function pick(x : word) returns (word) {{ + match (x) {{ + case {TWO_256} {{ + return 10; + }} + case {TWO_256_PLUS_ONE} {{ + return 11; + }} + default {{ + return 12; + }} }} }} - public function main() -> word {{ + function main() public returns (word) {{ let x : word = 0; assembly {{ x := calldataload(0) }} return exact() + plus() + pick(x); @@ -872,15 +894,19 @@ fn value_equal_word_patterns_share_one_canonical_switch_branch() { "equal_literal_spellings", r#" contract C { - function pick(x : word) -> word { - match x { - | 0x2a => return 111; - | 0042 => return 222; - | _ => return 333; + function pick(x : word) returns (word) { + match (x) { + case 0x2a { + return 111; + } + case 0042 { return 222; } + default { + return 333; + } } } - function main() -> word { + function main() returns (word) { let x : word = 0; assembly { x := calldataload(0) } return pick(x); @@ -907,23 +933,27 @@ fn evaluator_does_not_fold_past_unknown_return() { let hull = pretty_src_hull_with_std( "eval_return_unknown_abort", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract RetUnknown { - function pick(flag: bool, y: word) -> word { - match flag { - | true => return y; - | false => return 5; + function pick(flag: bool, y: word) returns (word) { + match (flag) { + case true { + return y; + } + case false { + return 5; + } } return 0; } - function get(x: word) -> word { + function get(x: word) returns (word) { return pick(true, x); } - public function main() -> word { + function main() public returns (word) { let x : word = 0; assembly { x := calldataload(0) } return get(x); @@ -942,17 +972,17 @@ fn evaluator_does_not_inline_storage_writing_helpers() { let mapping_hull = pretty_src_hull_with_std( "eval_storage_writer_mapping", r#" -import std.{*}; +import * from std; contract MappingWriter { - m: mapping(word, word); + m: mapping(word => word); - function set(k: word, v: word) -> word { + function set(k: word, v: word) returns (word) { m[k] = v; return v; } - public function main() -> word { + function main() public returns (word) { let a : word = set(1, 42); return m[1]; } @@ -974,17 +1004,17 @@ contract MappingWriter { let direct_hull = pretty_src_hull_with_std( "eval_storage_writer_direct", r#" -import std.{*}; +import * from std; contract DirectWriter { x: word; - function setv(v: word) -> word { + function setv(v: word) returns (word) { x = v; return v; } - public function main() -> word { + function main() public returns (word) { let a : word = setv(9); return x; } @@ -1012,13 +1042,13 @@ fn storage_index_assignment_materializes_slot_before_rhs() { let hull = pretty_src_hull_with_std( "storage_index_order", r#" -import std.{*}; +import * from std; contract StorageIndexOrder { counter: word; - m: mapping(word, word); + m: mapping(word => word); - function next() -> word { + function next() returns (word) { let cur: word = counter; let res: word; assembly { @@ -1028,7 +1058,7 @@ contract StorageIndexOrder { return res; } - public function main() -> word { + function main() public returns (word) { counter = 0; m[next()] = next(); return m[1]; @@ -1057,13 +1087,13 @@ contract StorageIndexOrder { let compound_hull = pretty_src_hull_with_std( "storage_index_compound", r#" -import std.{*}; +import * from std; contract StorageIndexCompound { counter: word; - m: mapping(word, word); + m: mapping(word => word); - function next() -> word { + function next() returns (word) { let cur: word = counter; let res: word; assembly { @@ -1073,7 +1103,7 @@ contract StorageIndexCompound { return res; } - public function main() -> word { + function main() public returns (word) { counter = 0; m[1] = 10; m[next()] += next(); @@ -1110,13 +1140,13 @@ fn new_compound_assignments_evaluate_storage_lhs_once() { let hull = pretty_src_hull_with_std( "storage_index_bit_not_compound", r#" -import std.{*}; +import * from std; contract StorageIndexBitNotCompound { counter: word; - m: mapping(word, word); + m: mapping(word => word); - function next() -> word { + function next() returns (word) { let cur: word = counter; let res: word; assembly { @@ -1126,7 +1156,7 @@ contract StorageIndexBitNotCompound { return res; } - public function main() -> word { + function main() public returns (word) { counter = 0; m[1] = 10; m[next()] ~=; @@ -1146,13 +1176,13 @@ contract StorageIndexBitNotCompound { for (name, operator) in [("mul", "*="), ("div", "/=")] { let source = format!( r#" -import std.{{*}}; +import * from std; contract StorageIndexBinaryCompound {{ counter: word; - m: mapping(word, word); + m: mapping(word => word); - function next() -> word {{ + function next() returns (word) {{ let cur: word = counter; let res: word; assembly {{ res := add(cur, 1) }} @@ -1160,7 +1190,7 @@ contract StorageIndexBinaryCompound {{ return res; }} - public function main() -> word {{ + function main() public returns (word) {{ counter = 0; m[1] = 12; m[next()] {operator} next(); @@ -1188,11 +1218,11 @@ fn evaluator_invalidates_storage_bindings_after_residual_calls() { contract StaleCall { x: word; - function setx() -> () { + function setx() returns () { x = 8; } - public function main() -> word { + function main() public returns (word) { x = 7; setx(); return x; @@ -1214,23 +1244,23 @@ fn audit_p0_match_scrutinees_are_materialized_exactly_once_even_for_default_bind for (name, arms) in [ ( "match_call_default_binding", - "| 0 => return 0; | n => return n;", + "case 0 { return 0; } case n { return n; }", ), - ("match_call_wildcard", "| _ => return 7;"), + ("match_call_wildcard", "default { return 7; }"), ] { let hull = pretty_src_hull( name, &format!( r#" -function read(x: word) -> word {{ +function read(x: word) returns (word) {{ let value: word; assembly {{ value := sload(x) }} return value; }} contract C {{ - public function main() -> word {{ - match read(0) {{ {arms} }} + function main() public returns (word) {{ + match (read(0)) {{ {arms} }} }} }} "# @@ -1250,7 +1280,7 @@ fn audit_p0_shadowing_let_materializes_its_initializer_before_declaration() { contract C { balance: word; - public function main() -> word { + function main() public returns (word) { let balance: word = balance; return balance; } @@ -1279,7 +1309,7 @@ fn audit_p0_for_initializer_let_remains_visible_after_the_loop() { contract C { i: word; - public function main() -> word { + function main() public returns (word) { for (let i: word; false; ) {} return i; } @@ -1296,19 +1326,19 @@ fn audit_p0_if_branch_let_is_hoisted_and_remains_a_local() { let hull = pretty_src_hull_with_std( "if_branch_let_scope", r#" -import std.{*}; +import * from std; contract C { x: word; - function f(flag: bool) -> word { + function f(flag: bool) returns (word) { if (flag && true) { let x: word = 7; } return x; } - public function main() -> word { return f(tobool(x)); } + function main() public returns (word) { return f(tobool(x)); } } "#, ); @@ -1345,11 +1375,11 @@ fn evaluator_invalidates_residual_assembly_branch_assignments() { let if_hull = pretty_src_hull_with_std( "eval_if_asm_assignment", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract IfAsm { - function f(b: bool) -> word { + function f(b: bool) returns (word) { let x : word = 1; if (b) { assembly { x := 5 } @@ -1357,7 +1387,7 @@ contract IfAsm { return x; } - public function main() -> word { + function main() public returns (word) { let raw : word = 0; assembly { raw := calldataload(0) } let b : bool = tobool(raw); @@ -1375,20 +1405,22 @@ contract IfAsm { let match_hull = pretty_src_hull_with_std( "eval_match_asm_assignment", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract MatchAsm { - function g(b: bool) -> word { + function g(b: bool) returns (word) { let x : word = 1; - match b { - | true => assembly { x := 5 } - | false => {} + match (b) { + case true { + assembly { x := 5 } + } + case false {} } return x; } - public function main() -> word { + function main() public returns (word) { let raw : word = 0; assembly { raw := calldataload(0) } let b : bool = tobool(raw); @@ -1407,9 +1439,9 @@ contract MatchAsm { #[test] fn cited_nested_layout_fixtures_check_cleanly() { for fixture in [ - "spec/032simplejoin.solc", - "spec/034cojoin.solc", - "spec/043fstsnd.solc", + "spec/032simplejoin.sol", + "spec/034cojoin.sol", + "spec/043fstsnd.sol", ] { let kinds = check_fixture_kinds(fixture); assert!(kinds.is_empty(), "{fixture}: {kinds:?}"); @@ -1454,24 +1486,24 @@ fn mapping_field_in_value_position_lowers_to_unimplemented_trap() { // `unimplemented()` runtime traps. This must not escape as an internal // hull-check error (previously: UndefinedVariable { name: "bal" }). let read_src = r#" -data mapping(key, value) = mapping(word); +enum mapping {mapping(word)} contract C { - bal : mapping(word, word); + bal : mapping(word => word); - public function main() -> word { + function main() public returns (word) { let b = bal; return 7; } } "#; let store_src = r#" -data mapping(key, value) = mapping(word); +enum mapping {mapping(word)} contract C { - bal : mapping(word, word); + bal : mapping(word => word); - public function main() -> word { + function main() public returns (word) { bal = bal; return 7; } @@ -1504,15 +1536,15 @@ fn aliased_mapping_field_keeps_the_storage_hash_helper_reachable() { let hull = pretty_src_hull_with_std( "aliased_mapping_field", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -type Balances = mapping(uint256, uint256); +type Balances = mapping(uint256 => uint256); contract C { balances : Balances; - public function roundtrip(k:uint256, v:uint256) -> uint256 { + function roundtrip(k:uint256, v:uint256) public returns (uint256) { balances[k] = v; return balances[k]; } @@ -1529,27 +1561,27 @@ fn contract_field_offsets_honor_custom_storage_size_instances() { let hull = pretty_src_hull_with_std( "custom_contract_field_offset", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data Wide = Wide(word); +enum Wide {Wide(word)} -instance Wide:StorageSize { - function size(x:Proxy(Wide)) -> word { return 7; } +impl StorageSize { + function size(x:Proxy) returns (word) { return 7; } } -instance storage(Wide):CanStore(Wide) { - function store(r:storage(Wide), v:Wide) -> () { +impl CanStore,Wide> { + function store(r:storage, v:Wide) returns () { let slot:word; let value:word; - match r { | storage(x) => slot = x; } - match v { | Wide(x) => value = x; } + match (r) { case storage(x) { slot = x; }} + match (v) { case Wide(x) { value = x; }} assembly { sstore(slot, value) } } - function load(r:storage(Wide)) -> Wide { + function load(r:storage) returns (Wide) { let slot:word; let value:word; - match r { | storage(x) => slot = x; } + match (r) { case storage(x) { slot = x; }} assembly { value := sload(slot) } return Wide(value); } @@ -1559,7 +1591,7 @@ contract C { first : Wide; second : uint256; - public function setAndGet(v:uint256) -> uint256 { + function setAndGet(v:uint256) public returns (uint256) { second = v; return second; } @@ -1575,31 +1607,31 @@ fn compound_contract_field_access_replays_effectful_storage_size() { let hull = pretty_src_hull_with_std( "effectful_contract_field_offset", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data Wide = Wide(word); +enum Wide {Wide(word)} -instance Wide:StorageSize { - function size(x:Proxy(Wide)) -> word { +impl StorageSize { + function size(x:Proxy) returns (word) { let result:word; assembly { result := sload(99) } return result; } } -instance storage(Wide):CanStore(Wide) { - function store(r:storage(Wide), v:Wide) -> () { +impl CanStore,Wide> { + function store(r:storage, v:Wide) returns () { let slot:word; let value:word; - match r { | storage(x) => slot = x; } - match v { | Wide(x) => value = x; } + match (r) { case storage(x) { slot = x; }} + match (v) { case Wide(x) { value = x; }} assembly { sstore(slot, value) } } - function load(r:storage(Wide)) -> Wide { + function load(r:storage) returns (Wide) { let slot:word; let value:word; - match r { | storage(x) => slot = x; } + match (r) { case storage(x) { slot = x; }} assembly { value := sload(slot) } return Wide(value); } @@ -1610,7 +1642,7 @@ contract C { first : Wide; second : uint256; - public function bump(v:uint256) -> uint256 { + function bump(v:uint256) public returns (uint256) { second += v; return v; } @@ -1633,7 +1665,7 @@ fn specialize_src(name: &str, src: &str) -> (&'static TestDb, SpecializeOutput<' } fn parse_module<'db>(db: &'db TestDb, name: &str, src: &str) -> Module<'db> { - let url = format!("memory:///{name}.solc").parse().expect("valid URL"); + let url = format!("memory:///{name}.sol").parse().expect("valid URL"); let file = SourceFile::new(db, url, Some(src.to_owned())); parse_file_to_hir(db, file).module(db) } @@ -1645,7 +1677,7 @@ fn parse_module<'db>(db: &'db TestDb, name: &str, src: &str) -> Module<'db> { fn specialize_src_with_std(name: &str, src: &str) -> (&'static TestDb, SpecializeOutput<'static>) { let main_root = repo_root().join("target/hull-smoke-tmp").join(name); fs::create_dir_all(&main_root).expect("create temp main root"); - let path = main_root.join("main.solc"); + let path = main_root.join("main.sol"); fs::write(&path, src).expect("write temp source"); specialize_fixture(&path) } @@ -1707,7 +1739,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -1861,34 +1893,34 @@ fn dynamic_array_helpers_check_bounds_and_preserve_typedef_representations() { let hull = pretty_src_hull_with_std( "array-checked-typedef", r#" -import std.{*}; +import * from std; -data Shifted = Shifted(word); -instance Shifted:Typedef(word) { - function rep(x:Shifted) -> word { - match x { | Shifted(w) => return w + 100; } +enum Shifted {Shifted(word)} +impl Typedef { + function rep(x:Shifted) returns (word) { + match (x) { case Shifted(w) { return w + 100; }} } - function abs(w:word) -> Shifted { return Shifted(w - 100); } + function abs(w:word) returns (Shifted) { return Shifted(w - 100); } } -data Second = Second(word); -instance Second:Typedef(word) { - function rep(x:Second) -> word { - match x { | Second(w) => return w + 1; } +enum Second {Second(word)} +impl Typedef { + function rep(x:Second) returns (word) { + match (x) { case Second(w) { return w + 1; }} } - function abs(w:word) -> Second { return Second(w - 1); } + function abs(w:word) returns (Second) { return Second(w - 1); } } -type Numbers = array(uint256); +type Numbers = array; contract CheckedArrays { xs : Numbers; seed : word; - function main() -> word { - let m : memory(DynArray(Shifted)) = [Shifted(3), Shifted(4)]; + function main() returns (word) { + let m : memory> = [Shifted(3), Shifted(4)]; xs = [10, 20]; - let p : storage(Numbers) = xs; + let p : storage = xs; let idx : Second = Second(seed); p[idx] += uint256(1); let picked : Shifted = m[idx]; @@ -1926,10 +1958,10 @@ fn storage_array_slot_helper_is_reachable_without_array_fields() { let hull = pretty_src_hull_with_std( "array-local-storage-ref", r#" -import std.{*}; +import * from std; -function main() -> uint256 { - let xs : storage(array(uint256)) = storage(0x100); +function main() returns (uint256) { + let xs : storage> = storage(0x100); return xs[uint256(0)]; } "#, @@ -1947,15 +1979,15 @@ fn nested_and_dynamic_storage_array_values_emit_deep_conversion_paths() { let hull = pretty_src_hull_with_std( "array-nested-dynamic", r#" -import std.{*}; +import * from std; contract CollectionArray { - flags : array(bool); - grid : array(array(uint256)); - names : array(string); - backup : array(string); + flags : array; + grid : array>; + names : array; + backup : array; - function main() -> uint256 { + function main() returns (uint256) { Array.setLength(flags, uint256(0)); ArrayPush.push(flags, true); let flag : bool = flags[uint256(0)]; @@ -1963,17 +1995,17 @@ contract CollectionArray { Array.setLength(grid, uint256(1)); ArrayPush.push(grid[uint256(0)], uint256(7)); grid[uint256(0)][uint256(0)] = uint256(9); - let row : storage(array(uint256)) = grid[uint256(0)]; + let row : storage> = grid[uint256(0)]; ArrayPush.push(row, uint256(11)); - let s : memory(string) = "hello"; + let s : memory = "hello"; ArrayPush.push(names, s); names[uint256(0)] = s; - let loaded : memory(string) = names[uint256(0)]; + let loaded : memory = names[uint256(0)]; backup = names; - let copied : memory(string) = backup[uint256(0)]; + let copied : memory = backup[uint256(0)]; - if flag { + if (flag) { return row[uint256(1)] + uint256(strlen(loaded)) + uint256(strlen(copied)); } return uint256(0); @@ -1994,13 +2026,13 @@ fn public_dynamic_array_return_emits_abi_copy() { let hull = pretty_src_hull_with_std( "array-public-return", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PublicArray { constructor() {} - public function values() -> memory(DynArray(uint256)) { + function values() public returns (memory>) { return [1, 2, 3]; } } @@ -2012,24 +2044,23 @@ contract PublicArray { } const OPERATOR_CUSTOM_UINT_ADD: &str = r#" -import std.{*}; +import * from std; -data uint = u(word); +enum uint {u(word)} -instance uint:Add { - function add(x:uint, y:uint) -> uint { +impl Add { + function add(x:uint, y:uint) returns (uint) { return uint.u(42); } } -function unwrap(x:uint) -> word { - match x { - | uint.u(w) => return w; - } +function unwrap(x:uint) returns (word) { + match (x) { + case uint.u(w) { return w; }} } contract C { - public function main() -> word { + function main() public returns (word) { let a:uint = uint.u(1); let b:uint = uint.u(2); let c:uint = a + b; @@ -2039,34 +2070,33 @@ contract C { "#; const OPERATOR_CUSTOM_BIT_NOT: &str = r#" -import std.{*}; +import * from std; -data mask = mask(word); +enum mask {mask(word)} -instance mask:BitNot { - function bnot(x:mask) -> mask { +impl BitNot { + function bnot(x:mask) returns (mask) { return mask(42); } } -function unwrap(x:mask) -> word { - match x { - | mask(w) => return w; - } +function unwrap(x:mask) returns (word) { + match (x) { + case mask(w) { return w; }} } contract C { - public function main() -> word { + function main() public returns (word) { return unwrap(~mask(0)); } } "#; const OPERATOR_ALL_COMPOUND: &str = r#" -import std.{*}; +import * from std; contract C { - public function main() -> word { + function main() public returns (word) { let acc:word = 6; acc += 4; acc -= 3; @@ -2084,26 +2114,24 @@ contract C { "#; const OPERATOR_METERS_ADD: &str = r#" -import std.{*}; +import * from std; -data meters = meters(word); +enum meters {meters(word)} -instance meters:Add { - function add(x:meters, y:meters) -> meters { - match x, y { - | meters(xw), meters(yw) => return meters(addWord(xw, yw)); - } +impl Add { + function add(x:meters, y:meters) returns (meters) { + match (x, y) { + case (meters(xw), meters(yw)) { return meters(addWord(xw, yw)); }} } } -function unwrap(x:meters) -> word { - match x { - | meters(w) => return w; - } +function unwrap(x:meters) returns (word) { + match (x) { + case meters(w) { return w; }} } contract C { - public function main() -> word { + function main() public returns (word) { let a:meters = meters(1); let b:meters = meters(2); let c:meters = a + b; @@ -2113,28 +2141,26 @@ contract C { "#; const OPERATOR_METERS_ORD: &str = r#" -import std.{*}; +import * from std; -data meters = meters(word); +enum meters {meters(word)} -instance meters:Eq { - function eq(x:meters, y:meters) -> bool { - match x, y { - | meters(xw), meters(yw) => return eqWord(xw, yw); - } +impl Eq { + function eq(x:meters, y:meters) returns (bool) { + match (x, y) { + case (meters(xw), meters(yw)) { return eqWord(xw, yw); }} } } -instance meters:Ord { - function gt(x:meters, y:meters) -> bool { - match x, y { - | meters(xw), meters(yw) => return gtWord(xw, yw); - } +impl Ord { + function gt(x:meters, y:meters) returns (bool) { + match (x, y) { + case (meters(xw), meters(yw)) { return gtWord(xw, yw); }} } } contract C { - public function main() -> word { + function main() public returns (word) { let a:meters = meters(1); let b:meters = meters(2); if (a < b) { @@ -2147,10 +2173,10 @@ contract C { "#; const OPERATOR_WORD_ADD: &str = r#" -import std.{*}; +import * from std; contract C { - public function main() -> word { + function main() public returns (word) { return 1 + 2; } } diff --git a/crates/hull/tests/snapshots.rs b/crates/hull/tests/snapshots.rs index 34e1006c..82ecc0c2 100644 --- a/crates/hull/tests/snapshots.rs +++ b/crates/hull/tests/snapshots.rs @@ -36,7 +36,7 @@ impl parser::Db for TestDb {} fn test_span<'db>(db: &'db TestDb) -> Span<'db> { let file = SourceFile::new( db, - "memory:///hull_snapshots.solc".parse().expect("valid URL"), + "memory:///hull_snapshots.sol".parse().expect("valid URL"), Some(String::new()), ); Span::new(AnchorId::root(db, file), Offset::new(0), Offset::new(0)) @@ -70,6 +70,7 @@ fn identity_function_snapshot() { assert_eq!(check_program_with_db(&db, &program), Vec::new()); assert_eq!( pretty_program(&db, &program), + // syntax-migration: preserve-next-literal "function id (x : word) -> word {\n return x\n}\n" ); } @@ -410,6 +411,7 @@ fn add1_contract_object_snapshot() { " }\n", " object \"Add1_deployed\" {\n", " code {\n", + // syntax-migration: preserve-next-literal " function main () -> word {\n", " let res : word\n", " assembly {\n", From 8c9c5ae4ccef6be93fe1c90ebedd9a15f5b874f5 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 040/110] Switch the compiler and fixtures to canonical syntax: lsp Co-authored-by: Codex --- crates/lsp/src/code_actions.rs | 270 +++++++++++++++------------ crates/lsp/src/completion.rs | 120 ++++-------- crates/lsp/src/definition.rs | 73 +++----- crates/lsp/src/diagnostics.rs | 89 ++++----- crates/lsp/src/document_highlight.rs | 6 +- crates/lsp/src/folding.rs | 12 +- crates/lsp/src/formatting.rs | 26 +-- crates/lsp/src/hover.rs | 177 ++++++++++++------ crates/lsp/src/import_edits.rs | 115 ++++++------ 9 files changed, 453 insertions(+), 435 deletions(-) diff --git a/crates/lsp/src/code_actions.rs b/crates/lsp/src/code_actions.rs index 48b2d265..854b4547 100644 --- a/crates/lsp/src/code_actions.rs +++ b/crates/lsp/src/code_actions.rs @@ -634,7 +634,7 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } @@ -671,8 +671,7 @@ mod tests { #[test] fn typo_diagnostic_becomes_nonpreferred_quick_fix() { - let source = - "function value() -> word { return 1; }\nfunction main() -> word { return vaue(); }\n"; + let source = "function value() returns (word) { return 1; }\nfunction main() returns (word) { return vaue(); }\n"; let (world, uri) = world_with_main(source); let diagnostic = undefined_name_diagnostic(&world, &uri); let requested_range = diagnostic.range; @@ -699,10 +698,10 @@ mod tests { #[test] fn real_uri_and_utf16_range_are_preserved() { - let source = "// 😀\nfunction value() -> word { return 1; }\nfunction main() -> word { return vaue(); }\n"; + let source = "// 😀\nfunction value() returns (word) { return 1; }\nfunction main() returns (word) { return vaue(); }\n"; let root = Url::parse("file:///tmp/solcore%20project/").expect("root uri"); let uri = - Url::parse("file:///tmp/solcore%20project/src/%E6%95%B0.solc").expect("document uri"); + Url::parse("file:///tmp/solcore%20project/src/%E6%95%B0.sol").expect("document uri"); let mut world = WorldState::new(); assert_eq!( world.load_workspace_documents(root, [(uri.clone(), source.to_owned())]), @@ -726,8 +725,7 @@ mod tests { #[test] fn stale_code_or_range_does_not_receive_a_fix() { - let source = - "function value() -> word { return 1; }\nfunction main() -> word { return vaue(); }\n"; + let source = "function value() returns (word) { return 1; }\nfunction main() returns (word) { return vaue(); }\n"; let (world, uri) = world_with_main(source); let diagnostic = undefined_name_diagnostic(&world, &uri); @@ -748,7 +746,7 @@ mod tests { #[test] fn typed_missing_import_lookup_requires_the_same_diagnostic_code() { - let (world, uri) = world_with_main("function main() -> word { return missing; }\n"); + let (world, uri) = world_with_main("function main() returns (word) { return missing; }\n"); let db = world.db(); let module = module_id_for_uri(&world, db, &uri).expect("main module"); let mut diagnostic = compute_vfs_diagnostics(&world, &uri) @@ -773,8 +771,7 @@ mod tests { #[test] fn request_range_and_only_filter_are_respected() { - let source = - "function value() -> word { return 1; }\nfunction main() -> word { return vaue(); }\n"; + let source = "function value() returns (word) { return 1; }\nfunction main() returns (word) { return vaue(); }\n"; let (world, uri) = world_with_main(source); let diagnostic = undefined_name_diagnostic(&world, &uri); @@ -813,11 +810,12 @@ mod tests { #[test] fn unknown_import_item_uses_compiler_suggestion() { - let main = "import math.{doubl};\nfunction main() -> word { return 1; }\n"; - let math = "function double(x: word) -> word { return x + x; }\nexport { double };\n"; + let main = "import {doubl} from math;\nfunction main() returns (word) { return 1; }\n"; + let math = + "function double(x: word) returns (word) { return x + x; }\nexport { double };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); let diagnostic = compute_diagnostics(&world, &main_uri) @@ -856,11 +854,12 @@ mod tests { #[test] fn module_path_typo_is_nonpreferred() { - let main = "import mth;\nfunction main() -> word { return 1; }\n"; - let math = "function double(x: word) -> word { return x + x; }\nexport { double };\n"; + let main = "import mth;\nfunction main() returns (word) { return 1; }\n"; + let math = + "function double(x: word) returns (word) { return x + x; }\nexport { double };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); let diagnostic = compute_diagnostics(&world, &main_uri) @@ -899,11 +898,11 @@ mod tests { #[test] fn qualified_name_suggestion_replaces_only_the_leaf() { - let main = "import math;\nfunction main(x: math.Vaue) -> word { return 1; }\n"; - let math = "data Value = Value(word);\nexport { Value(*) };\n"; + let main = "import math;\nfunction main(x: math.Vaue) returns (word) { return 1; }\n"; + let math = "enum Value {Value(word)}\nexport { Value(*) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); let diagnostic = compute_diagnostics(&world, &main_uri) @@ -942,11 +941,12 @@ mod tests { #[test] fn qualified_name_with_wrong_qualifier_has_no_partial_fix() { - let main = "import math as M;\nfunction main(x: N.Value) -> word { return 1; }\n"; - let math = "data Value = Value(word);\nexport { Value(*) };\n"; + let main = + "import * as M from math;\nfunction main(x: N.Value) returns (word) { return 1; }\n"; + let math = "enum Value {Value(word)}\nexport { Value(*) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); let diagnostic = compute_diagnostics(&world, &main_uri) @@ -973,11 +973,12 @@ mod tests { #[test] fn qualified_name_with_wrong_qualifier_and_leaf_has_no_partial_fix() { - let main = "import math as M;\nfunction main(x: N.Vaue) -> word { return 1; }\n"; - let math = "data Value = Value(word);\nexport { Value(*) };\n"; + let main = + "import * as M from math;\nfunction main(x: N.Vaue) returns (word) { return 1; }\n"; + let math = "enum Value {Value(word)}\nexport { Value(*) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); let diagnostic = compute_diagnostics(&world, &main_uri) @@ -1004,7 +1005,7 @@ mod tests { #[test] fn exact_constructor_qualification_is_preferred() { - let source = "data Option = None | Some(word);\nfunction main(x: word) -> Option { return Some(x); }\n"; + let source = "enum Option {None , Some(word)}\nfunction main(x: word) returns (Option) { return Some(x); }\n"; let (world, uri) = world_with_main(source); let diagnostic = compute_diagnostics(&world, &uri) .into_iter() @@ -1038,7 +1039,7 @@ mod tests { #[test] fn no_op_suggestion_edits_are_not_emitted() { - let source = "function main() -> word { return 1; }\n"; + let source = "function main() returns (word) { return 1; }\n"; let (world, uri) = world_with_main(source); let suggestion = DiagnosticSuggestion { title: "No change".to_owned(), @@ -1058,11 +1059,11 @@ mod tests { #[test] fn unique_exported_term_gets_a_preferred_auto_import() { - let main = "function main() -> word { return value(); }\n"; - let math = "function value() -> word { return 1; }\nexport { value };\n"; + let main = "function main() returns (word) { return value(); }\n"; + let math = "function value() returns (word) { return 1; }\nexport { value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri.clone(), math.to_owned())); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1086,11 +1087,11 @@ mod tests { .and_then(|changes| changes.get(&main_uri)), Some(&vec![TextEdit { range: Range::new(Position::new(0, 0), Position::new(0, 0)), - new_text: "import lib.math.{value};\n".to_owned(), + new_text: "import {value} from lib.math;\n".to_owned(), }]) ); - let fixed = format!("import lib.math.{{value}};\n{main}"); + let fixed = format!("import {{value}} from lib.math;\n{main}"); let mut fixed_world = WorldState::new(); assert!(fixed_world.open_document(main_uri.clone(), fixed)); assert!(fixed_world.open_document(math_uri, math.to_owned())); @@ -1104,17 +1105,17 @@ mod tests { #[test] fn multiple_auto_import_providers_are_sorted_and_nonpreferred() { - let main = "function main() -> word { return value(); }\n"; - let provider = "function value() -> word { return 1; }\nexport { value };\n"; + let main = "function main() returns (word) { return value(); }\n"; + let provider = "function value() returns (word) { return 1; }\nexport { value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/math.solc").expect("math uri"), + Url::parse("file:///main/math.sol").expect("math uri"), provider.to_owned() )); assert!(world.open_document( - Url::parse("file:///main/util.solc").expect("util uri"), + Url::parse("file:///main/util.sol").expect("util uri"), provider.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1157,13 +1158,14 @@ mod tests { } fn auto_import_extends_an_existing_selective_import_inner() { - let main = "import lib.math.{other};\nfunction main() -> word { return value(); }\n"; - let math = "function other() -> word { return 0; }\nfunction value() -> word { return 1; }\nexport { other, value };\n"; + let main = + "import {other} from lib.math;\nfunction main() returns (word) { return value(); }\n"; + let math = "function other() returns (word) { return 0; }\nfunction value() returns (word) { return 1; }\nexport { other, value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/math.solc").expect("math uri"), + Url::parse("file:///main/math.sol").expect("math uri"), math.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1192,14 +1194,14 @@ mod tests { } #[test] - fn exported_types_and_classes_are_auto_importable() { - let type_main = "function keep(x: Token) -> Token { return x; }\n"; - let type_provider = "data Token = Token(word);\nexport { Token };\n"; + fn exported_types_and_traits_are_auto_importable() { + let type_main = "function keep(x: Token) returns (Token) { return x; }\n"; + let type_provider = "enum Token {Token(word)}\nexport { Token };\n"; let mut type_world = WorldState::new(); - let type_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let type_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(type_world.open_document(type_uri.clone(), type_main.to_owned())); assert!(type_world.open_document( - Url::parse("file:///main/model.solc").expect("model uri"), + Url::parse("file:///main/model.sol").expect("model uri"), type_provider.to_owned() )); let type_diagnostic = diagnostic_with_code( @@ -1219,13 +1221,13 @@ mod tests { "Import `Token` from `lib.model`" ); - let class_main = "forall a. a:Comparable =>\nfunction keep(x: a) -> a { return x; }\n"; - let class_provider = "forall a. class a:Comparable {\n function compare(x: a, y: a) -> word;\n}\nexport { Comparable };\n"; + let class_main = "function keep(x: a) returns (a) where a: Comparable { return x; }\n"; + let class_provider = "trait Comparable {\n function compare(x: a, y: a) returns (word) ;\n}\nexport { Comparable };\n"; let mut class_world = WorldState::new(); - let class_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let class_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(class_world.open_document(class_uri.clone(), class_main.to_owned())); assert!(class_world.open_document( - Url::parse("file:///main/classes.solc").expect("classes uri"), + Url::parse("file:///main/classes.sol").expect("classes uri"), class_provider.to_owned() )); let class_diagnostic = diagnostic_with_code( @@ -1239,7 +1241,7 @@ mod tests { class_diagnostic.range, &context(class_diagnostic), ) - .expect("class code actions"); + .expect("trait code actions"); assert_eq!( action(&class_actions).title, "Import `Comparable` from `lib.classes`" @@ -1247,13 +1249,13 @@ mod tests { } #[test] - fn generated_dispatch_missing_type_and_class_have_auto_import_candidates() { - let source = r#"import std.{*}; -import std.opcodes.{address as address_}; + fn generated_dispatch_missing_type_and_trait_have_auto_import_candidates() { + let source = r#"import * from std; +import {address as address_} from std.opcodes; contract C { constructor() {} - public function nothing() -> () {} + function nothing() public returns () {} } "#; let (world, uri) = world_with_main(source); @@ -1279,13 +1281,13 @@ contract C { #[test] fn generated_dispatch_missing_terms_have_auto_import_candidates() { - let source = r#"import std.{*}; -import std.opcodes.{address as address_}; -import std.dispatch.{NonPayable, SigString}; + let source = r#"import * from std; +import {address as address_} from std.opcodes; +import {NonPayable, SigString} from std.dispatch; contract C { constructor() {} - public function nothing() -> () {} + function nothing() public returns () {} } "#; let (world, uri) = world_with_main(source); @@ -1303,10 +1305,30 @@ contract C { "expected generated term diagnostics" ); + for message in [ + "undefined name: Contract", + "undefined name: Fallback", + "undefined name: Method", + ] { + let diagnostic = diagnostics + .iter() + .find(|diagnostic| diagnostic.message.starts_with(message)) + .unwrap_or_else(|| panic!("missing diagnostic `{message}`")) + .clone(); + let actions = + handle_code_action(&world, &uri, diagnostic.range, &context(diagnostic.clone())) + .expect("code actions"); + assert!( + actions.iter().all(|action| !matches!( + action, + CodeActionOrCommand::CodeAction(action) + if action.title == "Import all from `std.dispatch`" + )), + "a selective import must not be rewritten into a mixed name/wildcard selector: {actions:#?}" + ); + } + for (message, expected_title) in [ - ("undefined name: Contract", "Import all from `std.dispatch`"), - ("undefined name: Fallback", "Import all from `std.dispatch`"), - ("undefined name: Method", "Import all from `std.dispatch`"), ( "undefined name: RunContract", "Import `RunContract` from `std.dispatch`", @@ -1345,13 +1367,14 @@ contract C { #[test] fn resolved_member_errors_do_not_offer_term_imports() { let field_main = - "data Local = Present;\nfunction main() -> word { return Local.missing; }\n"; - let exported_missing = "function missing() -> word { return 1; }\nexport { missing };\n"; + "enum Local {Present}\nfunction main() returns (word) { return Local.missing; }\n"; + let exported_missing = + "function missing() returns (word) { return 1; }\nexport { missing };\n"; let mut field_world = WorldState::new(); - let field_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let field_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(field_world.open_document(field_uri.clone(), field_main.to_owned())); assert!(field_world.open_document( - Url::parse("file:///main/symbols.solc").expect("symbols uri"), + Url::parse("file:///main/symbols.sol").expect("symbols uri"), exported_missing.to_owned() )); let field_diagnostic = undefined_name_diagnostic(&field_world, &field_uri); @@ -1368,17 +1391,17 @@ contract C { #[test] fn resolved_module_member_does_not_offer_a_constructor_import() { - let main = "import lib.foo as Math;\nfunction main() -> word { return Math.Value(1); }\n"; + let main = "import * as Math from lib.foo;\nfunction main() returns (word) { return Math.Value(1); }\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/foo.solc").expect("foo uri"), - "function other() -> word { return 0; }\nexport { other };\n".to_owned() + Url::parse("file:///main/foo.sol").expect("foo uri"), + "function other() returns (word) { return 0; }\nexport { other };\n".to_owned() )); assert!(world.open_document( - Url::parse("file:///main/model.solc").expect("model uri"), - "data Math = Value(word);\nexport { Math(*) };\n".to_owned() + Url::parse("file:///main/model.sol").expect("model uri"), + "enum Math {Value(word)}\nexport { Math(*) };\n".to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1392,11 +1415,11 @@ contract C { #[test] fn qualified_constructor_expression_imports_the_visible_type() { - let main = "function main() -> word { let option = Option.Some(1); return 1; }\n"; - let provider = "data Option = None | Some(word);\nexport { Option(*) };\n"; + let main = "function main() returns (word) { let option = Option.Some(1); return 1; }\n"; + let provider = "enum Option {None , Some(word)}\nexport { Option(*) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let model_uri = Url::parse("file:///main/model.solc").expect("model uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let model_uri = Url::parse("file:///main/model.sol").expect("model uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(model_uri.clone(), provider.to_owned())); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1420,14 +1443,14 @@ contract C { .and_then(|changes| changes.get(&main_uri)), Some(&vec![TextEdit { range: Range::new(Position::new(0, 0), Position::new(0, 0)), - new_text: "import lib.model.{Option};\n".to_owned(), + new_text: "import {Option} from lib.model;\n".to_owned(), }]) ); let mut fixed_world = WorldState::new(); assert!(fixed_world.open_document( main_uri.clone(), - format!("import lib.model.{{Option}};\n{main}"), + format!("import {{Option}} from lib.model;\n{main}"), )); assert!(fixed_world.open_document(model_uri, provider.to_owned())); assert!(compute_diagnostics(&fixed_world, &main_uri).iter().all( @@ -1440,11 +1463,11 @@ contract C { #[test] fn qualified_constructor_pattern_imports_the_visible_type() { - let main = "function main(x: word) -> word {\n match x {\n | Option.Some(value) => return value;\n | _ => return 0;\n }\n}\n"; - let provider = "data Option = None | Some(word);\nexport { Option(*) };\n"; + let main = "function main(x: word) returns (word) {\n match (x) {\n case Option.Some(value) { return value; }\ndefault { return 0; }}\n}\n"; + let provider = "enum Option {None , Some(word)}\nexport { Option(*) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let model_uri = Url::parse("file:///main/model.solc").expect("model uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let model_uri = Url::parse("file:///main/model.sol").expect("model uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(model_uri, provider.to_owned())); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1457,13 +1480,13 @@ contract C { #[test] fn resolved_pattern_type_does_not_import_a_conflicting_constructor_owner() { - let main = "data Option = None;\nfunction main(x: word) -> word {\n match x {\n | Option.Some(value) => return value;\n | _ => return 0;\n }\n}\n"; - let provider = "data Option = None | Some(word);\nexport { Option(*) };\n"; + let main = "enum Option {None}\nfunction main(x: word) returns (word) {\n match (x) {\n case Option.Some(value) { return value; }\ndefault { return 0; }}\n}\n"; + let provider = "enum Option {None , Some(word)}\nexport { Option(*) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/model.solc").expect("model uri"), + Url::parse("file:///main/model.sol").expect("model uri"), provider.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1478,13 +1501,13 @@ contract C { #[test] fn qualified_constructor_import_requires_that_constructor_to_be_exported() { - let main = "function main() -> word { let option = Option.Some(1); return 1; }\n"; - let provider = "data Option = None | Some(word);\nexport { Option(None) };\n"; + let main = "function main() returns (word) { let option = Option.Some(1); return 1; }\n"; + let provider = "enum Option {None , Some(word)}\nexport { Option(None) };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/model.solc").expect("model uri"), + Url::parse("file:///main/model.sol").expect("model uri"), provider.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1497,13 +1520,13 @@ contract C { #[test] fn module_import_requires_an_immediate_term_member() { - let main = "function main() -> word { return math.Value; }\n"; - let provider = "data Value = Value(word);\nexport { Value };\n"; + let main = "function main() returns (word) { return math.Value; }\n"; + let provider = "enum Value {Value(word)}\nexport { Value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/math.solc").expect("math uri"), + Url::parse("file:///main/math.sol").expect("math uri"), provider.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1518,11 +1541,11 @@ contract C { #[test] fn missing_module_qualifier_gets_a_plain_module_import() { - let main = "function main() -> word { return math.value(); }\n"; - let provider = "function value() -> word { return 1; }\nexport { value };\n"; + let main = "function main() returns (word) { return math.value(); }\n"; + let provider = "function value() returns (word) { return 1; }\nexport { value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri.clone(), provider.to_owned())); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1563,13 +1586,13 @@ contract C { #[test] fn module_import_stays_separate_from_an_existing_selective_import() { - let main = "import lib.math.{other};\nfunction main() -> word { return math.value(); }\n"; - let provider = "function other() -> word { return 0; }\nfunction value() -> word { return 1; }\nexport { other, value };\n"; + let main = "import {other} from lib.math;\nfunction main() returns (word) { return math.value(); }\n"; + let provider = "function other() returns (word) { return 0; }\nfunction value() returns (word) { return 1; }\nexport { other, value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/math.solc").expect("math uri"), + Url::parse("file:///main/math.sol").expect("math uri"), provider.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1597,13 +1620,13 @@ contract C { #[test] fn module_import_does_not_conflict_with_an_unqualified_term() { - let main = "import lib.math.{other};\nfunction math() -> word { return 0; }\nfunction main() -> word { return math.value(); }\n"; - let provider = "function other() -> word { return 0; }\nfunction value() -> word { return 1; }\nexport { other, value };\n"; + let main = "import {other} from lib.math;\nfunction math() returns (word) { return 0; }\nfunction main() returns (word) { return math.value(); }\n"; + let provider = "function other() returns (word) { return 0; }\nfunction value() returns (word) { return 1; }\nexport { other, value };\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/math.solc").expect("math uri"), + Url::parse("file:///main/math.sol").expect("math uri"), provider.to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1616,17 +1639,18 @@ contract C { #[test] fn module_import_does_not_override_an_existing_path_prefix() { - let main = "import lib.math.deep;\nfunction main() -> word { return math.value(); }\n"; + let main = + "import lib.math.deep;\nfunction main() returns (word) { return math.value(); }\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document( - Url::parse("file:///main/math/deep.solc").expect("deep uri"), - "function old() -> word { return 0; }\nexport { old };\n".to_owned() + Url::parse("file:///main/math/deep.sol").expect("deep uri"), + "function old() returns (word) { return 0; }\nexport { old };\n".to_owned() )); assert!(world.open_document( - Url::parse("file:///main/other/math.solc").expect("candidate uri"), - "function value() -> word { return 1; }\nexport { value };\n".to_owned() + Url::parse("file:///main/other/math.sol").expect("candidate uri"), + "function value() returns (word) { return 1; }\nexport { value };\n".to_owned() )); let diagnostic = undefined_name_diagnostic(&world, &main_uri); @@ -1649,11 +1673,11 @@ contract C { let right_path = base.join("right"); let left_root = Url::from_directory_path(&left_path).expect("left root"); let right_root = Url::from_directory_path(&right_path).expect("right root"); - let left_main = Url::from_file_path(left_path.join("main.solc")).expect("left main"); - let left_math = Url::from_file_path(left_path.join("math.solc")).expect("left math"); - let right_extra = Url::from_file_path(right_path.join("extra.solc")).expect("right extra"); - let main = "function main() -> word { return value(); }\n"; - let provider = "function value() -> word { return 1; }\nexport { value };\n"; + let left_main = Url::from_file_path(left_path.join("main.sol")).expect("left main"); + let left_math = Url::from_file_path(left_path.join("math.sol")).expect("left math"); + let right_extra = Url::from_file_path(right_path.join("extra.sol")).expect("right extra"); + let main = "function main() returns (word) { return value(); }\n"; + let provider = "function value() returns (word) { return 1; }\nexport { value };\n"; let mut world = WorldState::new(); world.load_workspace_roots([ ( diff --git a/crates/lsp/src/completion.rs b/crates/lsp/src/completion.rs index 925d7e20..36aadaba 100644 --- a/crates/lsp/src/completion.rs +++ b/crates/lsp/src/completion.rs @@ -23,16 +23,19 @@ use crate::{ const KEYWORDS: &[&str] = &[ "contract", "import", + "from", + "hiding", "export", "as", "let", - "data", - "class", - "forall", - "instance", + "enum", + "trait", + "impl", + "where", "if", "else", "for", + "while", "switch", "type", "case", @@ -41,6 +44,7 @@ const KEYWORDS: &[&str] = &[ "public", "payable", "function", + "returns", "constructor", "fallback", "return", @@ -50,6 +54,8 @@ const KEYWORDS: &[&str] = &[ "lam", "assembly", "pragma", + "comptime", + "derive", "true", "false", ]; @@ -520,7 +526,7 @@ fn detail_for_resolution(resolution: &Resolution<'_>) -> &'static str { Resolution::Def { kind: DefResolutionKind::Adt, .. - } => "data", + } => "enum", Resolution::Def { kind: DefResolutionKind::TypeAlias, .. @@ -528,23 +534,23 @@ fn detail_for_resolution(resolution: &Resolution<'_>) -> &'static str { Resolution::Def { kind: DefResolutionKind::Class, .. - } => "class", + } => "trait", Resolution::Def { kind: DefResolutionKind::Instance, .. - } => "instance", + } => "impl", Resolution::Ctor { .. } => "constructor", Resolution::Local(LocalBinding::TypeVar(_)) => "type parameter", Resolution::Local(_) => "local", Resolution::Param(_) => "parameter", Resolution::Field(_) => "field", - Resolution::ClassMethod { .. } => "class method", + Resolution::ClassMethod { .. } => "trait method", Resolution::Module(_) => "module", Resolution::Builtin(BuiltinKind::Type(_)) => "builtin type", - Resolution::Builtin(BuiltinKind::Class(_)) => "builtin class", + Resolution::Builtin(BuiltinKind::Class(_)) => "builtin trait", Resolution::Builtin(BuiltinKind::Constructor(_)) => "builtin constructor", Resolution::Builtin(BuiltinKind::Function(_)) => "builtin function", - Resolution::Builtin(BuiltinKind::ClassMethod(_)) => "builtin class method", + Resolution::Builtin(BuiltinKind::ClassMethod(_)) => "builtin trait method", Resolution::DotCtorDeferred => "constructor", Resolution::Err => "unresolved", } @@ -589,23 +595,14 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn function_body_completion_includes_params_locals_and_top_level_items() { - let source = "\ -function helper() -> word { - return 1; -} - -function main(input: word) -> word { - let local = input; - return local; -} -"; + let source = "function helper() returns (word) {\n return 1;\n}\n\nfunction main(input: word) returns (word) {\n let local = input;\n return local;\n}\n"; let (world, uri) = world_with_main(source); let offset = (source.find("return local").expect("return local") + "return ".len()) as u32; let position = world @@ -623,7 +620,7 @@ function main(input: word) -> word { #[test] fn completion_includes_language_keywords() { - let source = "function main() -> word {\n return 1;\n}\n"; + let source = "function main() returns (word) {\n return 1;\n}\n"; let (world, uri) = world_with_main(source); let offset = source.find('1').expect("literal") as u32; let position = world @@ -635,18 +632,18 @@ function main(input: word) -> word { completion_items(handle_completion(&world, &uri, position).expect("completion")); assert_completion(&items, "function", CompletionItemKind::KEYWORD); + assert_completion(&items, "hiding", CompletionItemKind::KEYWORD); + assert_completion(&items, "derive", CompletionItemKind::KEYWORD); } #[test] fn completion_uses_requested_module_when_unrelated_document_opened_first() { - let unrelated = "function unrelated() -> word { return 0; }\n"; - let math = - "function combine(a: word, b: word) -> word { return a + b; }\n\nexport { combine };\n"; - let main = - "import math.{combine};\n\nfunction main() -> word {\n return combine(1, 2);\n}\n"; - let unrelated_uri = Url::parse("file:///main/unrelated.solc").expect("unrelated uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let unrelated = "function unrelated() returns (word) { return 0; }\n"; + let math = "function combine(a: word, b: word) returns (word) { return a + b; }\n\nexport { combine };\n"; + let main = "import {combine} from math;\n\nfunction main() returns (word) {\n return combine(1, 2);\n}\n"; + let unrelated_uri = Url::parse("file:///main/unrelated.sol").expect("unrelated uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); let mut world = WorldState::new(); assert!(world.open_document(unrelated_uri, unrelated.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); @@ -666,19 +663,9 @@ function main(input: word) -> word { #[test] fn trailing_dot_module_completion_is_member_only_and_respects_exports() { - let math = "\ -function visible() -> word { return 1; } -function hidden() -> word { return 2; } -data Color = Red | Green; -export { visible, Color(Red, Green) }; -"; - let main = "\ -import math; -function main() -> word { - return math.; -} -"; - let (world, main_uri) = world_with_module(main, "math.solc", math); + let math = "function visible() returns (word) { return 1; }\nfunction hidden() returns (word) { return 2; }\nenum Color {Red , Green}\nexport { visible, Color(Red, Green) };\n"; + let main = "import math;\nfunction main() returns (word) {\n return math.;\n}\n"; + let (world, main_uri) = world_with_module(main, "math.sol", math); let items = completion_at(&world, &main_uri, main, "math."); assert_completion(&items, "visible", CompletionItemKind::FUNCTION); @@ -694,18 +681,9 @@ function main() -> word { #[test] fn qualified_completion_filters_a_typed_member_prefix() { - let math = "\ -function visible() -> word { return 1; } -function value() -> word { return 2; } -export { visible, value }; -"; - let main = "\ -import math; -function main() -> word { - return math.vis; -} -"; - let (world, main_uri) = world_with_module(main, "math.solc", math); + let math = "function visible() returns (word) { return 1; }\nfunction value() returns (word) { return 2; }\nexport { visible, value };\n"; + let main = "import math;\nfunction main() returns (word) {\n return math.vis;\n}\n"; + let (world, main_uri) = world_with_module(main, "math.sol", math); let items = completion_at(&world, &main_uri, main, "math.vis"); assert_completion(&items, "visible", CompletionItemKind::FUNCTION); @@ -714,15 +692,7 @@ function main() -> word { #[test] fn qualified_completion_includes_contract_local_adt_constructors() { - let source = "\ -contract Palette { - data Color = Red | Green; - - function main() -> word { - return Color.; - } -} -"; + let source = "contract Palette {\n enum Color {Red , Green}\n\n function main() returns (word) {\n return Color.;\n }\n}\n"; let (world, uri) = world_with_main(source); let items = completion_at(&world, &uri, source, "Color."); @@ -732,21 +702,11 @@ contract Palette { } #[test] - fn qualified_completion_includes_imported_class_methods() { - let classes = "\ -forall a . class a : Eq { - function eq(x: a, y: a) -> bool; - function unequal(x: a, y: a) -> bool; -} -export { Eq }; -"; - let main = "\ -import classes.{Eq}; -function main() -> word { - return Eq.; -} -"; - let (world, main_uri) = world_with_module(main, "classes.solc", classes); + fn qualified_completion_includes_imported_trait_methods() { + let classes = "trait Eq {\n function eq(x: a, y: a) returns (bool) ;\n function unequal(x: a, y: a) returns (bool) ;\n}\nexport { Eq };\n"; + let main = + "import {Eq} from classes;\nfunction main() returns (word) {\n return Eq.;\n}\n"; + let (world, main_uri) = world_with_module(main, "classes.sol", classes); let items = completion_at(&world, &main_uri, main, "Eq."); assert_completion(&items, "eq", CompletionItemKind::METHOD); @@ -777,7 +737,7 @@ function main() -> word { fn world_with_module(main: &str, module_path: &str, module_source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); let module_uri = Url::parse(&format!("file:///main/{module_path}")).expect("module uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); assert!(world.open_document(module_uri, module_source.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); (world, main_uri) diff --git a/crates/lsp/src/definition.rs b/crates/lsp/src/definition.rs index c7629cd0..ed659ac6 100644 --- a/crates/lsp/src/definition.rs +++ b/crates/lsp/src/definition.rs @@ -489,15 +489,15 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } fn world_with_main_and_math(main: &str, math: &str) -> (WorldState, Url, Url) { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri.clone(), math.to_owned())); (world, main_uri, math_uri) @@ -509,9 +509,9 @@ mod tests { nested: &str, ) -> (WorldState, Url, Url) { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); let nested_uri = - Url::parse(&format!("file:///main/{nested_path}.solc")).expect("nested uri"); + Url::parse(&format!("file:///main/{nested_path}.sol")).expect("nested uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(nested_uri.clone(), nested.to_owned())); (world, main_uri, nested_uri) @@ -529,7 +529,7 @@ mod tests { #[test] fn definition_of_parameter_use_points_to_parameter_name() { - let source = "function id(x: word) -> word {\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n return x;\n}\n"; let (world, uri) = world_with_main(source); let use_offset = (source.find("return x").expect("return") + "return ".len()) as u32; let param_offset = source.find("x: word").expect("param") as u32; @@ -550,8 +550,10 @@ mod tests { #[test] fn definition_of_import_selector_name_points_to_imported_declaration() { - let main = "import math.{double};\nfunction main() -> word { return double(21); }\n"; - let math = "function double(x: word) -> word { return x + x; }\nexport { double };\n"; + let main = + "import {double} from math;\nfunction main() returns (word) { return double(21); }\n"; + let math = + "function double(x: word) returns (word) { return x + x; }\nexport { double };\n"; let (world, main_uri, math_uri) = world_with_main_and_math(main, math); let main_index = world.line_index(&main_uri).expect("main line index"); let math_index = world.line_index(&math_uri).expect("math line index"); @@ -573,7 +575,7 @@ mod tests { #[test] fn definition_in_embedded_std_is_not_returned_as_an_unopenable_uri() { - let source = "import std.{addWord};\nfunction main() -> word { return addWord(1, 2); }\n"; + let source = "import {addWord} from std;\nfunction main() returns (word) { return addWord(1, 2); }\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let call = source.rfind("addWord").expect("call") as u32; @@ -586,14 +588,8 @@ mod tests { #[test] fn definition_of_cross_file_type_ref_points_to_type_declaration() { - let main = "\ -import models.{Box}; -function wrap(value: word) -> Box { - let boxed: Box = Box(value); - return boxed; -} -"; - let models = "data Box = Box(word);\nexport { Box };\n"; + let main = "import {Box} from models;\nfunction wrap(value: word) returns (Box) {\n let boxed: Box = Box(value);\n return boxed;\n}\n"; + let models = "enum Box {Box(word)}\nexport { Box };\n"; let (world, main_uri, models_uri) = world_with_main_and_nested(main, "models", models); let models_index = world.line_index(&models_uri).expect("models line index"); let type_ref = (main.find("boxed: Box").expect("local type") + "boxed: ".len()) as u32; @@ -610,7 +606,7 @@ function wrap(value: word) -> Box { #[test] fn definition_on_type_declaration_points_to_itself() { - let source = "data Choice = Left | Right;\n"; + let source = "enum Choice {Left , Right}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let declaration = source.find("Choice").expect("declaration") as u32; @@ -625,18 +621,11 @@ function wrap(value: word) -> Box { } #[test] - fn definition_of_predicate_points_to_class_declaration() { - let source = "\ -forall a. class a:Comparable { - function compare(x: a, y: a) -> word; -} - -forall a. a:Comparable => -function keep(x: a) -> a { return x; } -"; + fn definition_of_predicate_points_to_trait_declaration() { + let source = "trait Comparable {\n function compare(x: a, y: a) returns (word) ;\n}\n\nfunction keep(x: a) returns (a) where a: Comparable { return x; }\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); - let declaration = source.find("Comparable").expect("class declaration") as u32; + let declaration = source.find("Comparable").expect("trait declaration") as u32; let predicate = source.rfind("Comparable").expect("predicate") as u32; let location = scalar_definition(&world, &uri, predicate); @@ -650,16 +639,7 @@ function keep(x: a) -> a { return x; } #[test] fn definition_of_constructor_pattern_points_to_constructor_declaration() { - let source = "\ -data Choice = Left(word) | Right; - -function unwrap(value: Choice) -> word { - match value { - | Choice.Left(x) => return x; - | Choice.Right => return 0; - } -} -"; + let source = "enum Choice {Left(word) , Right}\n\nfunction unwrap(value: Choice) returns (word) {\n match (value) {\n case Choice.Left(x) { return x; }\ncase Choice.Right { return 0; }}\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let declaration = source.find("Left").expect("constructor declaration") as u32; @@ -676,8 +656,8 @@ function unwrap(value: Choice) -> word { #[test] fn definition_of_import_path_and_module_qualifier_points_to_module_start() { - let main = "import foo.bar;\nfunction main() -> word { return foo.bar.value(); }\n"; - let bar = "export { value };\nfunction value() -> word { return 7; }\n"; + let main = "import foo.bar;\nfunction main() returns (word) { return foo.bar.value(); }\n"; + let bar = "export { value };\nfunction value() returns (word) { return 7; }\n"; let (world, main_uri, bar_uri) = world_with_main_and_nested(main, "foo/bar", bar); let bar_index = world.line_index(&bar_uri).expect("bar line index"); let expected = bar_index.range(0, 0); @@ -695,14 +675,13 @@ function unwrap(value: Choice) -> word { #[test] fn definition_of_exact_module_qualifier_wins_over_shared_navigation_origin() { - let main = - "import foo.bar;\nimport foo;\nfunction main() -> word { return foo.value(); }\n"; - let foo = "export { value };\nfunction value() -> word { return 1; }\n"; - let bar = "export { value };\nfunction value() -> word { return 2; }\n"; + let main = "import foo.bar;\nimport foo;\nfunction main() returns (word) { return foo.value(); }\n"; + let foo = "export { value };\nfunction value() returns (word) { return 1; }\n"; + let bar = "export { value };\nfunction value() returns (word) { return 2; }\n"; let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let foo_uri = Url::parse("file:///main/foo.solc").expect("foo uri"); - let bar_uri = Url::parse("file:///main/foo/bar.solc").expect("bar uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let foo_uri = Url::parse("file:///main/foo.sol").expect("foo uri"); + let bar_uri = Url::parse("file:///main/foo/bar.sol").expect("bar uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(foo_uri.clone(), foo.to_owned())); assert!(world.open_document(bar_uri, bar.to_owned())); diff --git a/crates/lsp/src/diagnostics.rs b/crates/lsp/src/diagnostics.rs index 74e05e8c..b03c4245 100644 --- a/crates/lsp/src/diagnostics.rs +++ b/crates/lsp/src/diagnostics.rs @@ -164,7 +164,7 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } @@ -208,14 +208,14 @@ mod tests { #[test] fn clean_program_has_no_diagnostics() { - let (world, uri) = world_with_main("function main() -> word {\n return 1;\n}\n"); + let (world, uri) = world_with_main("function main() returns (word) {\n return 1;\n}\n"); assert!(compute_diagnostics(&world, &uri).is_empty()); } #[test] fn type_error_maps_to_lsp_error_with_range() { - let source = "function f() -> word {\n return true;\n}\n"; + let source = "function f() returns (word) {\n return true;\n}\n"; let (world, uri) = world_with_main(source); let diagnostics = compute_diagnostics(&world, &uri); @@ -234,10 +234,10 @@ mod tests { #[test] fn sibling_import_open_in_workspace_has_no_module_not_found_diagnostic() { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; - let math = "function double(x: word) -> word {\n let res: word;\n assembly {\n res := add(x, x)\n }\n return res;\n}\n\nexport { double };\n"; + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; + let math = "function double(x: word) returns (word) {\n let res: word;\n assembly {\n res := add(x, x)\n }\n return res;\n}\n\nexport { double };\n"; assert!(world.open_document(main_uri.clone(), main.to_owned())); let _ = compute_diagnostics(&world, &main_uri); @@ -250,10 +250,10 @@ mod tests { #[test] fn sibling_import_opened_before_importer_has_no_module_not_found_diagnostic() { let mut world = WorldState::new(); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math = "function double(x: word) -> word { return x; }\n\nexport { double };\n"; - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math = "function double(x: word) returns (word) { return x; }\n\nexport { double };\n"; + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; assert!(world.open_document(math_uri, math.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -265,12 +265,12 @@ mod tests { #[test] fn fallback_diagnostics_for_unreachable_importer_update_after_sibling_opens() { let mut world = WorldState::new(); - let entry_uri = Url::parse("file:///main/entry.solc").expect("entry uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let entry = "function entry() -> word { return 0; }\n"; - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; - let math = "function double(x: word) -> word { return x; }\n\nexport { double };\n"; + let entry_uri = Url::parse("file:///main/entry.sol").expect("entry uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let entry = "function entry() returns (word) { return 0; }\n"; + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; + let math = "function double(x: word) returns (word) { return x; }\n\nexport { double };\n"; assert!(world.open_document(entry_uri, entry.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -295,13 +295,14 @@ mod tests { use std::{sync::mpsc, time::Duration}; let mut world = WorldState::new(); - let entry_uri = Url::parse("file:///main/entry.solc").expect("entry uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let entry_uri = Url::parse("file:///main/entry.sol").expect("entry uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); let shadow_uri = Url::parse("file:///main/math.txt").expect("shadow uri"); - let entry = "function entry() -> word { return 0; }\n"; - let main = "import math.{double};\nfunction main() -> word { return double(21); }\n"; - let math = "function double(x: word) -> word { return x; }\nexport { double };\n"; + let entry = "function entry() returns (word) { return 0; }\n"; + let main = + "import {double} from math;\nfunction main() returns (word) { return double(21); }\n"; + let math = "function double(x: word) returns (word) { return x; }\nexport { double };\n"; assert!(world.open_document(entry_uri, entry.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -326,8 +327,8 @@ mod tests { let result = std::thread::Builder::new() .stack_size(1024 * 1024) .spawn(|| { - let mut source = "function main() -> word { return ".to_owned(); - source.push_str(&"if true then 0 else ".repeat(130)); + let mut source = "function main() returns (word) { return ".to_owned(); + source.push_str(&"true ? 0 : ".repeat(130)); source.push_str("0; }\n"); let (world, uri) = world_with_main(&source); @@ -349,14 +350,14 @@ mod tests { #[test] fn open_document_diagnostics_refresh_importer_when_sibling_changes() { let mut world = WorldState::new(); - let entry_uri = Url::parse("file:///main/entry.solc").expect("entry uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let entry = "function entry() -> word { return 0; }\n"; - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; - let math_no_export = "function double(x: word) -> word { return x; }\n"; + let entry_uri = Url::parse("file:///main/entry.sol").expect("entry uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let entry = "function entry() returns (word) { return 0; }\n"; + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; + let math_no_export = "function double(x: word) returns (word) { return x; }\n"; let math_with_export = - "function double(x: word) -> word { return x; }\n\nexport { double };\n"; + "function double(x: word) returns (word) { return x; }\n\nexport { double };\n"; assert!(world.open_document(entry_uri, entry.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -387,12 +388,12 @@ mod tests { #[test] fn adding_export_via_change_clears_unknown_import_item() { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; - let math_no_export = "function double(x: word) -> word { return x; }\n"; + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; + let math_no_export = "function double(x: word) returns (word) { return x; }\n"; let math_with_export = - "function double(x: word) -> word { return x; }\n\nexport { double };\n"; + "function double(x: word) returns (word) { return x; }\n\nexport { double };\n"; assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri.clone(), math_no_export.to_owned())); @@ -417,14 +418,14 @@ mod tests { #[test] fn adding_export_via_change_clears_unknown_import_item_entry_drift() { let mut world = WorldState::new(); - let entry_uri = Url::parse("file:///main/entry.solc").expect("entry uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let entry = "function entry() -> word { return 0; }\n"; - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; - let math_no_export = "function double(x: word) -> word { return x; }\n"; + let entry_uri = Url::parse("file:///main/entry.sol").expect("entry uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let entry = "function entry() returns (word) { return 0; }\n"; + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; + let math_no_export = "function double(x: word) returns (word) { return x; }\n"; let math_with_export = - "function double(x: word) -> word { return x; }\n\nexport { double };\n"; + "function double(x: word) returns (word) { return x; }\n\nexport { double };\n"; assert!(world.open_document(entry_uri, entry.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); diff --git a/crates/lsp/src/document_highlight.rs b/crates/lsp/src/document_highlight.rs index 9cfbc5d7..e2bc7be1 100644 --- a/crates/lsp/src/document_highlight.rs +++ b/crates/lsp/src/document_highlight.rs @@ -46,14 +46,14 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn parameter_highlights_declaration_and_uses_in_current_file() { - let source = "function id(x: word) -> word {\n let y = x;\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n let y = x;\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let first_use = (source.find("let y = x").expect("first use") + "let y = ".len()) as u32; @@ -85,7 +85,7 @@ mod tests { #[test] fn whitespace_returns_none() { - let source = "function id(x: word) -> word {\n let y = x;\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n let y = x;\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let whitespace = (source.find("let y = x").expect("let statement") + "let".len()) as u32; diff --git a/crates/lsp/src/folding.rs b/crates/lsp/src/folding.rs index 928d86da..b24af393 100644 --- a/crates/lsp/src/folding.rs +++ b/crates/lsp/src/folding.rs @@ -350,14 +350,14 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn folds_imports_comments_items_and_nested_blocks() { - let source = "// first\n// second\nimport alpha;\nimport beta;\n\n/* block\n comment */\ncontract Box {\n function get() -> word {\n if true {\n return 1;\n }\n }\n}\n"; + let source = "// first\n// second\nimport alpha;\nimport beta;\n\n/* block\n comment */\ncontract Box {\n function get() returns (word) {\n if (true) {\n return 1;\n }\n }\n}\n"; let (world, uri) = world_with_main(source); let folds = handle_folding_range(&world, &uri).expect("folding ranges"); @@ -385,7 +385,7 @@ mod tests { #[test] fn lexical_folding_ignores_delimiters_in_unicode_strings_and_comments() { - let source = "function main() {\n let label = \"😀 { not a block }\";\n /* { ignored } */\n {\n return 1;\n }\n}\n"; + let source = "function main() returns (word) {\n let label = \"😀 { not a block }\";\n /* { ignored } */\n {\n return 1;\n }\n}\n"; let (world, uri) = world_with_main(source); let folds = handle_folding_range(&world, &uri).expect("folding ranges"); @@ -401,7 +401,7 @@ mod tests { #[test] fn malformed_source_still_returns_balanced_inner_blocks() { - let source = "function main() {\n {\n return 1;\n }\n"; + let source = "function main() returns (word) {\n {\n return 1;\n }\n"; let (world, uri) = world_with_main(source); let folds = handle_folding_range(&world, &uri).expect("folding ranges"); @@ -414,7 +414,7 @@ mod tests { #[test] fn nested_blocks_with_the_same_line_extent_remain_distinct() { - let source = "function main() { if true {\n return 1;\n} }\n"; + let source = "function main() returns (word) { if (true) {\n return 1;\n} }\n"; let (world, uri) = world_with_main(source); let folds = handle_folding_range(&world, &uri).expect("folding ranges"); let structural = folds @@ -429,7 +429,7 @@ mod tests { #[test] fn unknown_document_has_no_folding_result() { let world = WorldState::new(); - let uri = Url::parse("file:///main/missing.solc").expect("uri"); + let uri = Url::parse("file:///main/missing.sol").expect("uri"); assert_eq!(handle_folding_range(&world, &uri), None); } } diff --git a/crates/lsp/src/formatting.rs b/crates/lsp/src/formatting.rs index cf88ee28..c39b5ada 100644 --- a/crates/lsp/src/formatting.rs +++ b/crates/lsp/src/formatting.rs @@ -286,15 +286,15 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn formats_whole_document_without_touching_braces_in_trivia() { - let source = "function main() -> word { \nreturn \"{\";\n/* } { */\nif true {\nreturn 1; // }\n}\n}\n\n"; - let expected = "function main() -> word {\n return \"{\";\n /* } { */\n if true {\n return 1; // }\n }\n}\n"; + let source = "function main() returns (word) { \nreturn \"{\";\n/* } { */\nif (true) {\nreturn 1; // }\n}\n}\n\n"; + let expected = "function main() returns (word) {\n return \"{\";\n /* } { */\n if (true) {\n return 1; // }\n }\n}\n"; let (world, uri) = world_with_main(source); let edits = handle_formatting(&world, &uri, &options(2, true)).expect("formatting"); @@ -311,8 +311,8 @@ mod tests { #[test] fn respects_tabs_and_preserves_crlf() { - let source = "function main() {\r\nreturn \"😀\";\r\n}"; - let expected = "function main() {\r\n\treturn \"😀\";\r\n}\r\n"; + let source = "function main() returns (string) {\r\nreturn \"😀\";\r\n}"; + let expected = "function main() returns (string) {\r\n\treturn \"😀\";\r\n}\r\n"; let (world, uri) = world_with_main(source); let edits = handle_formatting(&world, &uri, &options(8, false)).expect("formatting"); @@ -328,7 +328,7 @@ mod tests { #[test] fn already_formatted_document_needs_no_edit() { - let source = "function main() {\n return 1;\n}\n"; + let source = "function main() returns (word) {\n return 1;\n}\n"; let (world, uri) = world_with_main(source); assert_eq!( @@ -340,15 +340,15 @@ mod tests { #[test] fn formatting_requires_an_open_document() { let world = WorldState::new(); - let uri = Url::parse("file:///main/missing.solc").expect("uri"); + let uri = Url::parse("file:///main/missing.sol").expect("uri"); assert_eq!(handle_formatting(&world, &uri, &options(2, true)), None); } #[test] fn preserves_multiline_string_and_block_comment_payload_whitespace() { for source in [ - "function main() {\nreturn \"first\n second \";\n}\n", - "function main() {\n/* markdown\n indented code \n*/\nreturn 1;\n}\n", + "function main() returns (string) {\nreturn \"first\n second \";\n}\n", + "function main() returns (word) {\n/* markdown\n indented code \n*/\nreturn 1;\n}\n", ] { let (world, uri) = world_with_main(source); assert_eq!( @@ -375,8 +375,8 @@ mod tests { #[test] fn honors_disabled_trailing_whitespace_trimming() { - let source = "function main() { \n \nreturn 1; \n}\n"; - let expected = "function main() { \n \n return 1; \n}\n"; + let source = "function main() returns (word) { \n \nreturn 1; \n}\n"; + let expected = "function main() returns (word) { \n \n return 1; \n}\n"; let (world, uri) = world_with_main(source); let mut options = options(2, true); options.trim_trailing_whitespace = Some(false); @@ -387,8 +387,8 @@ mod tests { #[test] fn dedents_adjacent_leading_closing_braces() { - let source = "function main() {\n{\nreturn 1;\n }}\n"; - let expected = "function main() {\n {\n return 1;\n}}\n"; + let source = "function main() returns (word) {\n{\nreturn 1;\n }}\n"; + let expected = "function main() returns (word) {\n {\n return 1;\n}}\n"; let (world, uri) = world_with_main(source); let edits = handle_formatting(&world, &uri, &options(2, true)).expect("formatting"); diff --git a/crates/lsp/src/hover.rs b/crates/lsp/src/hover.rs index 67ac5a62..56ee2365 100644 --- a/crates/lsp/src/hover.rs +++ b/crates/lsp/src/hover.rs @@ -230,11 +230,11 @@ fn definition_hover<'db>(db: &'db vfs::AnalysisHost, def: DefId<'db>) -> Option< documentation: comments_markdown(found.adt.leading_comments(db)), }), Definition::Class(class) => Some(HoverInfo { - code: format!("class {}", display_pred_ref(db, class.head(db))), + code: format_trait_header(db, class), documentation: comments_markdown(class.leading_comments(db)), }), Definition::Instance(instance) => Some(HoverInfo { - code: format!("instance {}", display_pred_ref(db, instance.head(db))), + code: format_impl_header(db, instance), documentation: comments_markdown(instance.leading_comments(db)), }), Definition::Contract(contract) => { @@ -377,11 +377,30 @@ fn format_source_function_signature<'db>(db: &'db dyn hir_ty::Db, sig: &FuncSig< .map(|param| format_source_param(db, param)) .collect::>() .join(", "); - let ret = sig - .ret - .map(|ret| display_type_ref(db, ret)) - .unwrap_or_else(|| "_".to_owned()); - format!("{}({params}) -> {ret}", sig.name.atom().text(db)) + let type_params = type_parameter_list(db, &sig.type_vars); + let mut signature = format!("{}{type_params}({params})", sig.name.atom().text(db)); + if sig.public.is_some() { + signature.push_str(" public"); + } + if sig.payable.is_some() { + signature.push_str(" payable"); + } + if let Some(ret) = sig.ret { + signature.push_str(" returns ("); + signature.push_str(&display_type_ref(db, ret)); + signature.push(')'); + } + if !sig.preds.is_empty() { + signature.push_str(" where "); + signature.push_str( + &sig.preds + .iter() + .map(|pred| display_pred_ref(db, *pred)) + .collect::>() + .join(", "), + ); + } + signature } fn format_source_param<'db>(db: &'db dyn hir_ty::Db, param: &FuncParam<'db>) -> String { @@ -422,11 +441,11 @@ fn format_adt_declaration<'db>(db: &'db dyn hir_ty::Db, adt: AdtDef<'db>) -> Str } }) .collect::>() - .join(" | "); + .join(", "); if ctors.is_empty() { - format!("data {name}{params}") + format!("enum {name}{params} {{}}") } else { - format!("data {name}{params} = {ctors}") + format!("enum {name}{params} {{ {ctors} }}") } } @@ -437,8 +456,43 @@ fn type_parameter_list<'db>( if params.is_empty() { String::new() } else { - format!("({})", ident_names(db, params).join(", ")) + format!("<{}>", ident_names(db, params).join(", ")) + } +} + +fn format_trait_header<'db>(db: &'db dyn hir_ty::Db, trait_def: ClassDef<'db>) -> String { + let mut header = format!("trait {}", display_trait_ref(db, trait_def.head(db))); + append_where_clause(db, &mut header, trait_def.super_preds(db)); + header +} + +fn format_impl_header<'db>(db: &'db dyn hir_ty::Db, impl_def: InstanceDef<'db>) -> String { + let default = if impl_def.default_kw(db).is_some() { + "default " + } else { + "" + }; + let params = type_parameter_list(db, impl_def.type_var_elems(db)); + let mut header = format!( + "{default}impl{params} {}", + display_trait_ref(db, impl_def.head(db)) + ); + append_where_clause(db, &mut header, impl_def.preds(db)); + header +} + +fn append_where_clause<'db>(db: &'db dyn hir_ty::Db, header: &mut String, preds: &[PredRef<'db>]) { + if preds.is_empty() { + return; } + header.push_str(" where "); + header.push_str( + &preds + .iter() + .map(|pred| display_pred_ref(db, *pred)) + .collect::>() + .join(", "), + ); } fn comments_markdown(comments: &[SourceComment]) -> Option { @@ -886,7 +940,7 @@ fn format_callable_scheme<'db>( .collect::>() .join(", "); let mut signature = format!( - "{name}({params}) -> {}", + "{name}({params}) returns ({})", display_ty(db, ret, type_var_names) ); let predicates = scheme @@ -928,9 +982,15 @@ fn display_ty<'db>(db: &'db dyn hir_ty::Db, ty: Ty<'db>, names: &[String]) -> St }; if args.is_empty() { name + } else if name == "mapping" && args.len() == 2 { + format!( + "mapping({} => {})", + display_ty(db, args[0], names), + display_ty(db, args[1], names) + ) } else { format!( - "{name}({})", + "{name}<{}>", args.iter() .map(|arg| display_ty(db, *arg, names)) .collect::>() @@ -939,7 +999,7 @@ fn display_ty<'db>(db: &'db dyn hir_ty::Db, ty: Ty<'db>, names: &[String]) -> St } } TyKind::Function { params, ret } => format!( - "({}) -> {}", + "function({}) returns ({})", params .iter() .map(|param| display_ty(db, *param, names)) @@ -961,7 +1021,7 @@ fn display_ty<'db>(db: &'db dyn hir_ty::Db, ty: Ty<'db>, names: &[String]) -> St ) } } - TyKind::Comptime(inner) => format!("comptime {}", display_ty(db, *inner, names)), + TyKind::Comptime(inner) => format!("comptime<{}>", display_ty(db, *inner, names)), } } @@ -978,7 +1038,7 @@ fn display_pred<'db>(db: &'db dyn hir_ty::Db, pred: hir_ty::Pred<'db>, names: &[ format!("{}: {class}", display_ty(db, *main, names)) } else { format!( - "{}: {class}({})", + "{}: {class}<{}>", display_ty(db, *main, names), args.iter() .map(|arg| display_ty(db, *arg, names)) @@ -1008,23 +1068,32 @@ fn display_type_ref<'db>(db: &'db dyn hir_ty::Db, ty: TypeRef<'db>) -> String { out.push_str(qualifier.atom().text(db)); out.push('.'); } - out.push_str(name.atom().text(db)); + let name_text = name.atom().text(db); + out.push_str(name_text); if !args.atom().is_empty() { - out.push('('); - out.push_str( - &args - .atom() - .iter() - .map(|arg| display_type_ref(db, *arg)) - .collect::>() - .join(", "), - ); - out.push(')'); + if name_text == "mapping" && args.atom().len() == 2 { + out.push('('); + out.push_str(&display_type_ref(db, args.atom()[0])); + out.push_str(" => "); + out.push_str(&display_type_ref(db, args.atom()[1])); + out.push(')'); + } else { + out.push('<'); + out.push_str( + &args + .atom() + .iter() + .map(|arg| display_type_ref(db, *arg)) + .collect::>() + .join(", "), + ); + out.push('>'); + } } out } TypeRefKind::Fn { params, ret } => format!( - "({}) -> {}", + "function({}) returns ({})", params .atom() .iter() @@ -1034,7 +1103,7 @@ fn display_type_ref<'db>(db: &'db dyn hir_ty::Db, ty: TypeRef<'db>) -> String { display_type_ref(db, *ret) ), TypeRefKind::Comptime { inner, .. } => { - format!("comptime {}", display_type_ref(db, *inner)) + format!("comptime<{}>", display_type_ref(db, *inner)) } TypeRefKind::Tuple { elems } => format!( "({})", @@ -1057,7 +1126,7 @@ fn display_pred_ref<'db>(db: &'db dyn hir_ty::Db, pred: PredRef<'db>) -> String format!("{ty}: {class}") } else { format!( - "{ty}: {class}({})", + "{ty}: {class}<{}>", kind.args .atom() .iter() @@ -1068,6 +1137,18 @@ fn display_pred_ref<'db>(db: &'db dyn hir_ty::Db, pred: PredRef<'db>) -> String } } +fn display_trait_ref<'db>(db: &'db dyn hir_ty::Db, pred: PredRef<'db>) -> String { + let kind = pred.kind(db); + let mut args = vec![display_type_ref(db, kind.ty)]; + args.extend( + kind.args + .atom() + .iter() + .map(|arg| display_type_ref(db, *arg)), + ); + format!("{}<{}>", kind.class.atom().text(db), args.join(", ")) +} + #[cfg(test)] mod tests { use lsp_types::{HoverContents, MarkedString}; @@ -1076,7 +1157,7 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } @@ -1122,7 +1203,7 @@ mod tests { #[test] fn hovers_integer_literal_type() { - let source = "function main() -> word {\n return 42;\n}\n"; + let source = "function main() returns (word) {\n return 42;\n}\n"; let (world, uri) = world_with_main(source); let literal_offset = source.find("42").expect("literal"); @@ -1146,23 +1227,14 @@ mod tests { #[test] fn function_and_parameter_references_show_signatures_and_identifier_ranges() { - let source = "\ -// Returns its input. -function id(x: word) -> word { - return x; -} - -function main() -> word { - return id(42); -} -"; + let source = "// Returns its input.\nfunction id(x: word) returns (word) {\n return x;\n}\n\nfunction main() returns (word) {\n return id(42);\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let call = source.rfind("id(42)").expect("call"); let function_hover = hover_at(source, &world, &uri, call); assert!( - hover_code(&function_hover).contains("id(x: word) -> word"), + hover_code(&function_hover).contains("id(x: word) returns (word)"), "unexpected function hover: {:?}", function_hover.contents ); @@ -1186,12 +1258,7 @@ function main() -> word { #[test] fn inferred_local_reference_hover_uses_local_name_range() { - let source = "\ -function main() -> word { - let result = 42; - return result; -} -"; + let source = "function main() returns (word) {\n let result = 42;\n return result;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let reference = source.rfind("result").expect("local reference"); @@ -1211,20 +1278,14 @@ function main() -> word { #[test] fn type_and_constructor_references_have_rich_hover_and_leaf_ranges() { - let source = "\ -data Maybe = None | Some(word); - -function main() -> Maybe { - return Maybe.Some(42); -} -"; + let source = "enum Maybe {None , Some(word)}\n\nfunction main() returns (Maybe) {\n return Maybe.Some(42);\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let ty_reference = source.rfind("Maybe").expect("type reference"); let ty_hover = hover_at(source, &world, &uri, ty_reference); assert!( - hover_code(&ty_hover).contains("data Maybe = None | Some(word)"), + hover_code(&ty_hover).contains("enum Maybe { None, Some(word) }"), "unexpected type hover: {:?}", ty_hover.contents ); @@ -1237,7 +1298,7 @@ function main() -> Maybe { let ctor_hover = hover_at(source, &world, &uri, ctor_reference); let ctor_code = hover_code(&ctor_hover); assert!( - ctor_code.contains("Some(word) -> Maybe"), + ctor_code.contains("Some(word) returns (Maybe)"), "unexpected constructor hover: {ctor_code}" ); assert_eq!( diff --git a/crates/lsp/src/import_edits.rs b/crates/lsp/src/import_edits.rs index 302c1a7a..4db3b235 100644 --- a/crates/lsp/src/import_edits.rs +++ b/crates/lsp/src/import_edits.rs @@ -26,7 +26,7 @@ pub struct ImportEdit { /// Plans one deterministic edit that brings `public_name` into scope. /// -/// When the target already has a safe explicit `.{...}` import, the name is +/// When the target already has a safe explicit `{...} from` import, the name is /// appended to that selector. Otherwise a separate selective import is placed /// after the existing import block, or after leading pragmas/header comments. /// Malformed source, stale parse metadata, and text that cannot be represented @@ -148,10 +148,10 @@ pub fn plan_import_edit<'db>( /// Plans an import that exposes every public name from `target_import_path`. /// -/// When a selective import for the same target already exists, `*` is appended -/// to its selector. The parser treats a selector containing `*` as a wildcard, -/// which preserves comments and formatting inside the existing declaration. -/// Otherwise a new `import path.{*};` declaration is inserted. +/// A wildcard import already present needs no edit. A selective import for the +/// same module is left untouched because the canonical grammar does not mix +/// names and `*` in one selector; callers may offer a separate rewrite in that +/// case. Otherwise a new `import * from path;` declaration is inserted. pub fn plan_wildcard_import_edit<'db>( db: &'db dyn parser::Db, source: &str, @@ -184,12 +184,7 @@ pub fn plan_wildcard_import_edit<'db>( { match import.selector(db) { Some(ImportSelector::Wildcard) => return None, - Some(ImportSelector::Names(names)) - if import.alias_elem(db).is_none() && import.hiding(db).is_empty() => - { - let offset = selector_append_offset(db, source, import, names)?; - return Some(insertion(offset, ", *".to_owned())); - } + Some(ImportSelector::Names(_)) => return None, _ => {} } } @@ -199,7 +194,7 @@ pub fn plan_wildcard_import_edit<'db>( source, module, &imports, - &format!("import {target_import_path}.{{*}};"), + &format!("import * from {target_import_path};"), ) } @@ -384,7 +379,7 @@ fn plan_new_import( target_import_path: &str, public_name: &str, ) -> Option { - let declaration = format!("import {target_import_path}.{{{public_name}}};"); + let declaration = format!("import {{{public_name}}} from {target_import_path};"); plan_new_import_declaration(db, source, module, imports, &declaration) } @@ -587,7 +582,7 @@ mod tests { fn plan(source: &str, target: &str, name: &str) -> Option { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); let db = world.db(); let path = world.vfs_path_for_uri(&uri).expect("VFS path"); @@ -598,7 +593,7 @@ mod tests { fn plan_module(source: &str, target: &str) -> Option { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); let db = world.db(); let path = world.vfs_path_for_uri(&uri).expect("VFS path"); @@ -609,7 +604,7 @@ mod tests { fn plan_wildcard(source: &str, target: &str) -> Option { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); let db = world.db(); let path = world.vfs_path_for_uri(&uri).expect("VFS path"); @@ -626,190 +621,188 @@ mod tests { #[test] fn appends_to_matching_selective_import() { - let source = "import lib.math.{old};\nfunction main() { value; }\n"; + let source = "import {old} from lib.math;\nfunction main() { value; }\n"; let edit = plan(source, "lib.math", "value").expect("edit"); assert_eq!(edit.start, edit.end); assert_eq!(edit.replacement, ", value"); assert_eq!( apply(source, &edit), - "import lib.math.{old, value};\nfunction main() { value; }\n" + "import {old, value} from lib.math;\nfunction main() { value; }\n" ); } #[test] - fn wildcard_upgrade_preserves_an_existing_selective_import() { - let source = "import std.dispatch.{NonPayable, SigString};\nfunction main() {}\n"; - let edit = plan_wildcard(source, "std.dispatch").expect("edit"); - - assert_eq!( - apply(source, &edit), - "import std.dispatch.{NonPayable, SigString, *};\nfunction main() {}\n" - ); + fn wildcard_upgrade_does_not_create_an_invalid_mixed_selector() { + let source = "import {NonPayable, SigString} from std.dispatch;\nfunction main() {}\n"; + assert_eq!(plan_wildcard(source, "std.dispatch"), None); } #[test] fn wildcard_import_is_inserted_when_target_is_not_selected() { - let source = "import std.{*};\nfunction main() {}\n"; + let source = "import * from std;\nfunction main() {}\n"; let edit = plan_wildcard(source, "std.dispatch").expect("edit"); assert_eq!( apply(source, &edit), - "import std.{*};\nimport std.dispatch.{*};\nfunction main() {}\n" + "import * from std;\nimport * from std.dispatch;\nfunction main() {}\n" ); } #[test] fn existing_wildcard_import_needs_no_edit() { - let source = "import std.dispatch.{*};\nfunction main() {}\n"; + let source = "import * from std.dispatch;\nfunction main() {}\n"; assert_eq!(plan_wildcard(source, "std.dispatch"), None); } #[test] fn appends_after_the_last_alias_without_disturbing_operator_or_hiding() { - let source = - "import lib.{(^^), source as local} hiding {hidden};\nfunction main() { value; }\n"; + let source = "import {(^^), source as local} from lib hiding {hidden};\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{(^^), source as local, value} hiding {hidden};\nfunction main() { value; }\n" + "import {(^^), source as local, value} from lib hiding {hidden};\nfunction main() { value; }\n" ); } #[test] fn appending_keeps_selector_comments_and_crlf_layout() { - let source = "import lib.{old // keep old\r\n}; // keep import\r\n\r\nfunction main() { value; }\r\n"; + let source = "import {old // keep old\r\n} from lib; // keep import\r\n\r\nfunction main() { value; }\r\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{old, value // keep old\r\n}; // keep import\r\n\r\nfunction main() { value; }\r\n" + "import {old, value // keep old\r\n} from lib; // keep import\r\n\r\nfunction main() { value; }\r\n" ); } #[test] fn appending_skips_a_nested_selector_comment() { - let source = - "import lib.{old /* outer /* inner */ still outer */};\nfunction main() { value; }\n"; + let source = "import {old /* outer /* inner */ still outer */} from lib;\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{old, value /* outer /* inner */ still outer */};\nfunction main() { value; }\n" + "import {old, value /* outer /* inner */ still outer */} from lib;\nfunction main() { value; }\n" ); } #[test] fn does_not_duplicate_an_existing_unaliased_name() { - let source = "import lib.{value};\nfunction main() { value; }\n"; + let source = "import {value} from lib;\nfunction main() { value; }\n"; assert_eq!(plan(source, "lib", "value"), None); } #[test] fn existing_source_alias_gets_a_separate_import() { - let source = "import lib.{value as renamed};\nfunction main() { value; }\n"; + let source = "import {value as renamed} from lib;\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{value as renamed};\nimport lib.{value};\nfunction main() { value; }\n" + "import {value as renamed} from lib;\nimport {value} from lib;\nfunction main() { value; }\n" ); } #[test] fn selector_hiding_the_name_gets_a_separate_import() { - let source = "import lib.{old} hiding {value};\nfunction main() { value; }\n"; + let source = "import {old} from lib hiding {value};\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{old} hiding {value};\nimport lib.{value};\nfunction main() { value; }\n" + "import {old} from lib hiding {value};\nimport {value} from lib;\nfunction main() { value; }\n" ); } #[test] fn hidden_selected_name_does_not_suppress_a_clean_import() { - let source = "import lib.{Option} hiding {Option};\nfunction main() { Option; }\n"; + let source = "import {Option} from lib hiding {Option};\nfunction main() { Option; }\n"; let edit = plan(source, "lib", "Option").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{Option} hiding {Option};\nimport lib.{Option};\nfunction main() { Option; }\n" + "import {Option} from lib hiding {Option};\nimport {Option} from lib;\nfunction main() { Option; }\n" ); } #[test] fn hidden_aliased_source_does_not_create_a_local_name_collision() { - let source = "import lib.{Other as Option} hiding {Other};\nfunction main() { Option; }\n"; + let source = + "import {Other as Option} from lib hiding {Other};\nfunction main() { Option; }\n"; let edit = plan(source, "lib", "Option").expect("edit"); assert_eq!( apply(source, &edit), - "import lib.{Other as Option} hiding {Other};\nimport lib.{Option};\nfunction main() { Option; }\n" + "import {Other as Option} from lib hiding {Other};\nimport {Option} from lib;\nfunction main() { Option; }\n" ); } #[test] fn active_alias_still_suppresses_an_ambiguous_selective_import() { - let source = "import lib.{Other as Option};\nfunction main() { Option; }\n"; + let source = "import {Other as Option} from lib;\nfunction main() { Option; }\n"; assert_eq!(plan(source, "lib", "Option"), None); } #[test] fn wildcard_plain_and_module_alias_imports_get_separate_imports() { - for existing in ["import lib.{*};", "import lib;", "import lib as L;"] { + for existing in [ + "import * from lib;", + "import lib;", + "import * as L from lib;", + ] { let source = format!("{existing}\nfunction main() {{ value; }}\n"); let edit = plan(&source, "lib", "value").expect("edit"); assert_eq!( apply(&source, &edit), - format!("{existing}\nimport lib.{{value}};\nfunction main() {{ value; }}\n") + format!("{existing}\nimport {{value}} from lib;\nfunction main() {{ value; }}\n") ); } } #[test] fn new_import_follows_the_complete_import_block_and_keeps_blank_lines() { - let source = - "import first.{a};\nimport second.{b}; // second\n\nfunction main() { value; }\n"; + let source = "import {a} from first;\nimport {b} from second; // second\n\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import first.{a};\nimport second.{b}; // second\nimport lib.{value};\n\nfunction main() { value; }\n" + "import {a} from first;\nimport {b} from second; // second\nimport {value} from lib;\n\nfunction main() { value; }\n" ); } #[test] fn new_import_does_not_split_a_multiline_trailing_block_comment() { - let source = "import first.{a}; /* trailing\n block */\nfunction main() { value; }\n"; + let source = + "import {a} from first; /* trailing\n block */\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import first.{a}; /* trailing\n block */\nimport lib.{value};\nfunction main() { value; }\n" + "import {a} from first; /* trailing\n block */\nimport {value} from lib;\nfunction main() { value; }\n" ); } #[test] fn new_import_does_not_split_a_nested_trailing_block_comment() { - let source = "import first.{a}; /* outer\n /* inner */\n still outer */\nfunction main() { value; }\n"; + let source = "import {a} from first; /* outer\n /* inner */\n still outer */\nfunction main() { value; }\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import first.{a}; /* outer\n /* inner */\n still outer */\nimport lib.{value};\nfunction main() { value; }\n" + "import {a} from first; /* outer\n /* inner */\n still outer */\nimport {value} from lib;\nfunction main() { value; }\n" ); } #[test] fn new_import_preserves_crlf_and_trailing_line_comment() { - let source = "import first.{a}; // first\r\n\r\nfunction main() { value; }\r\n"; + let source = "import {a} from first; // first\r\n\r\nfunction main() { value; }\r\n"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import first.{a}; // first\r\nimport lib.{value};\r\n\r\nfunction main() { value; }\r\n" + "import {a} from first; // first\r\nimport {value} from lib;\r\n\r\nfunction main() { value; }\r\n" ); } @@ -820,7 +813,7 @@ mod tests { assert_eq!( apply(source, &edit), - "// license\npragma no-patterson-condition;\nimport lib.{value};\n\nfunction main() { value; }\n" + "// license\npragma no-patterson-condition;\nimport {value} from lib;\n\nfunction main() { value; }\n" ); } @@ -831,7 +824,7 @@ mod tests { assert_eq!( apply(source, &edit), - "// Copyright\n/* License */\nimport lib.{value};\n\nfunction main() { value; }\n" + "// Copyright\n/* License */\nimport {value} from lib;\n\nfunction main() { value; }\n" ); } @@ -842,7 +835,7 @@ mod tests { assert_eq!( apply(source, &edit), - "/* outer /* inner */ still outer */\nimport lib.{value};\n\nfunction main() { value; }\n" + "/* outer /* inner */ still outer */\nimport {value} from lib;\n\nfunction main() { value; }\n" ); } From 509fe688074c81ed776ed0a3b9b6e079ba23ed0a Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 041/110] Switch the compiler and fixtures to canonical syntax: lsp Co-authored-by: Codex --- crates/lsp/src/import_edits.rs | 23 +++-- crates/lsp/src/inlay_hints.rs | 15 +-- crates/lsp/src/native.rs | 6 +- crates/lsp/src/references.rs | 117 +++++++++------------- crates/lsp/src/rename.rs | 145 +++++++++++++--------------- crates/lsp/src/selection_range.rs | 36 ++++--- crates/lsp/src/semantic_tokens.rs | 16 +-- crates/lsp/src/signature_help.rs | 36 +++---- crates/lsp/src/state.rs | 141 +++++++++++++-------------- crates/lsp/src/symbols.rs | 21 +--- crates/lsp/src/wasm.rs | 62 ++++++------ crates/lsp/src/workspace_symbols.rs | 39 +++----- crates/lsp/tests/stdio_smoke.rs | 30 ++---- 13 files changed, 306 insertions(+), 381 deletions(-) diff --git a/crates/lsp/src/import_edits.rs b/crates/lsp/src/import_edits.rs index 4db3b235..a8cf34be 100644 --- a/crates/lsp/src/import_edits.rs +++ b/crates/lsp/src/import_edits.rs @@ -842,16 +842,19 @@ mod tests { #[test] fn empty_source_gets_a_top_level_import() { let edit = plan("", "lib.math", "value").expect("edit"); - assert_eq!(edit, insertion(0, "import lib.math.{value};\n".to_owned())); + assert_eq!( + edit, + insertion(0, "import {value} from lib.math;\n".to_owned()) + ); } #[test] fn import_at_eof_stays_on_its_own_line() { - let source = "import first.{a}; // first"; + let source = "import {a} from first; // first"; let edit = plan(source, "lib", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import first.{a}; // first\nimport lib.{value};" + "import {a} from first; // first\nimport {value} from lib;" ); } @@ -861,7 +864,7 @@ mod tests { let edit = plan(source, "@dep.util", "value").expect("edit"); assert_eq!( apply(source, &edit), - "import @dep.util.{value};\nfunction main() { value; }\n" + "import {value} from @dep.util;\nfunction main() { value; }\n" ); } @@ -885,10 +888,10 @@ mod tests { #[test] fn selected_wildcard_and_aliased_imports_do_not_count_as_plain() { for existing in [ - "import lib.math.{value};", - "import lib.math.{other} hiding {other};", - "import lib.math.{*};", - "import lib.math as Math;", + "import {value} from lib.math;", + "import {other} from lib.math hiding {other};", + "import * from lib.math;", + "import * as Math from lib.math;", ] { let source = format!("{existing}\nfunction main() {{ lib.value; }}\n"); let edit = @@ -930,7 +933,7 @@ mod tests { assert_eq!(plan_module(source, ""), None); let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); let db = world.db(); let path = world.vfs_path_for_uri(&uri).expect("VFS path"); @@ -958,7 +961,7 @@ mod tests { fn rejects_stale_parse_metadata() { let source = "function main() { value; }\n"; let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); let db = world.db(); let path = world.vfs_path_for_uri(&uri).expect("VFS path"); diff --git a/crates/lsp/src/inlay_hints.rs b/crates/lsp/src/inlay_hints.rs index dcc20c86..f30a6b98 100644 --- a/crates/lsp/src/inlay_hints.rs +++ b/crates/lsp/src/inlay_hints.rs @@ -251,14 +251,14 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn unannotated_let_gets_type_hint() { - let source = "function main() -> word {\n let x = 42;\n return x;\n}\n"; + let source = "function main() returns (word) {\n let x = 42;\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let range = line_index.range(0, source.len() as u32); @@ -285,7 +285,7 @@ mod tests { #[test] fn annotated_let_gets_no_type_hint() { - let source = "function main() -> word {\n let y: word = 42;\n return y;\n}\n"; + let source = "function main() returns (word) {\n let y: word = 42;\n return y;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let range = line_index.range(0, source.len() as u32); @@ -297,13 +297,8 @@ mod tests { #[test] fn range_filters_binding_names() { - let source = "\ -function main() -> word { - let a = 1; - let b = 2; - return b; -} -"; + let source = + "function main() returns (word) {\n let a = 1;\n let b = 2;\n return b;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let start = line_index.byte_to_position(source.find("let b").expect("let b") as u32); diff --git a/crates/lsp/src/native.rs b/crates/lsp/src/native.rs index 868dc7cc..3ff0d378 100644 --- a/crates/lsp/src/native.rs +++ b/crates/lsp/src/native.rs @@ -492,12 +492,12 @@ fn initial_workspace_roots(params: &InitializeParams) -> Vec { fn watched_files_registration() -> Registration { let options = DidChangeWatchedFilesRegistrationOptions { watchers: vec![FileSystemWatcher { - glob_pattern: GlobPattern::String("**/*.solc".to_owned()), + glob_pattern: GlobPattern::String("**/*.sol".to_owned()), kind: Some(WatchKind::Create | WatchKind::Change | WatchKind::Delete), }], }; Registration { - id: "solcore-watch-solc".to_owned(), + id: "solcore-watch-sol".to_owned(), method: "workspace/didChangeWatchedFiles".to_owned(), register_options: serde_json::to_value(options).ok(), } @@ -566,7 +566,7 @@ fn is_solcore_uri(uri: &Url) -> bool { } fn is_solcore_path(path: &Path) -> bool { - path.extension().and_then(|extension| extension.to_str()) == Some("solc") + path.extension().and_then(|extension| extension.to_str()) == Some("sol") } fn is_ignored_directory(path: &Path) -> bool { diff --git a/crates/lsp/src/references.rs b/crates/lsp/src/references.rs index 6753d0cf..99cb635f 100644 --- a/crates/lsp/src/references.rs +++ b/crates/lsp/src/references.rs @@ -32,8 +32,8 @@ use crate::{ /// Semantic identity used by references, highlights, and future rename support. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ReferenceTarget<'db> { - /// A named user definition such as a function, type, contract, class, or - /// instance. + /// A named user definition such as a function, type, contract, trait, or + /// impl. Def(DefId<'db>), /// A data constructor identified by its owning type and constructor index. Ctor { @@ -48,16 +48,16 @@ pub enum ReferenceTarget<'db> { Local(LocalBinding<'db>), /// A contract field. Field(FieldId<'db>), - /// A type-class method. + /// A trait method. ClassMethod { - /// The class that declares the method. + /// The trait that declares the method. class: DefId<'db>, /// The method name. name: String, }, /// A module qualifier binding local to one source module. Module(ModuleRef<'db>), - /// A local alias introduced by `import m.{source as alias}`. + /// A local alias introduced by `import {source as alias} from m;`. ImportAlias { /// Module definition that owns the import declaration. owner: DefId<'db>, @@ -2207,15 +2207,15 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } fn world_with_main_and_math(main: &str, math: &str) -> (WorldState, Url, Url) { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri.clone(), math.to_owned())); (world, main_uri, math_uri) @@ -2223,7 +2223,7 @@ mod tests { #[test] fn parameter_references_include_uses_and_optional_declaration() { - let source = "function id(x: word) -> word {\n let y = x;\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n let y = x;\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let first_use = (source.find("let y = x").expect("first use") + "let y = ".len()) as u32; @@ -2254,15 +2254,7 @@ mod tests { #[test] fn top_level_function_declaration_finds_call_site() { - let source = "\ -function target() -> word { - return 1; -} - -function caller() -> word { - return target(); -} -"; + let source = "function target() returns (word) {\n return 1;\n}\n\nfunction caller() returns (word) {\n return target();\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let declaration = source.find("target").expect("declaration") as u32; @@ -2278,7 +2270,7 @@ function caller() -> word { #[test] fn std_references_exclude_the_unopenable_embedded_declaration() { - let source = "import std.{addWord};\nfunction main() -> word { return addWord(1, 2); }\n"; + let source = "import {addWord} from std;\nfunction main() returns (word) { return addWord(1, 2); }\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let import = source.find("addWord").expect("import") as u32; @@ -2299,8 +2291,10 @@ function caller() -> word { #[test] fn import_and_export_names_are_references_to_exported_item() { - let main = "import math.{double};\nfunction main() -> word { return double(21); }\n"; - let math = "function double(x: word) -> word { return x + x; }\nexport { double };\n"; + let main = + "import {double} from math;\nfunction main() returns (word) { return double(21); }\n"; + let math = + "function double(x: word) returns (word) { return x + x; }\nexport { double };\n"; let (world, main_uri, math_uri) = world_with_main_and_math(main, math); let main_index = world.line_index(&main_uri).expect("main line index"); let math_index = world.line_index(&math_uri).expect("math line index"); @@ -2331,9 +2325,8 @@ function caller() -> word { #[test] fn selected_import_alias_references_do_not_rename_the_source_symbol() { - let main = - "import math.{double as twice};\nfunction main() -> word { return twice(21); }\n"; - let math = "function double(x: word) -> word { return x; }\nexport { double };\n"; + let main = "import {double as twice} from math;\nfunction main() returns (word) { return twice(21); }\n"; + let math = "function double(x: word) returns (word) { return x; }\nexport { double };\n"; let (world, main_uri, math_uri) = world_with_main_and_math(main, math); let main_index = world.line_index(&main_uri).expect("main line index"); let math_index = world.line_index(&math_uri).expect("math line index"); @@ -2380,11 +2373,12 @@ function caller() -> word { #[test] fn module_alias_references_include_declaration_and_qualifier() { - let main = "import math as M;\nfunction main() -> word { return M.value(); }\n"; - let math = "function value() -> word { return 1; }\nexport { value };\n"; + let main = + "import * as M from math;\nfunction main() returns (word) { return M.value(); }\n"; + let math = "function value() returns (word) { return 1; }\nexport { value };\n"; let (world, main_uri, _) = world_with_main_and_math(main, math); let index = world.line_index(&main_uri).expect("main line index"); - let declaration = main.find("M;").expect("module alias") as u32; + let declaration = main.find("M from").expect("module alias") as u32; let qualifier = main.rfind("M.value").expect("module qualifier") as u32; let references = @@ -2402,19 +2396,11 @@ function caller() -> word { #[test] fn module_alias_references_include_type_and_pattern_qualifiers() { - let main = "\ -import math as M; -function unwrap(token: M.Token) -> word { - match token { - | M.Token.Ok(value) => return value; - | M.Token.Err(value) => return value; - } -} -"; - let model = "data Token = Ok(word) | Err(word);\nexport { Token(Ok, Err) };\n"; + let main = "import * as M from math;\nfunction unwrap(token: M.Token) returns (word) {\n match (token) {\n case M.Token.Ok(value) { return value; }\ncase M.Token.Err(value) { return value; }}\n}\n"; + let model = "enum Token {Ok(word) , Err(word)}\nexport { Token(Ok, Err) };\n"; let (world, main_uri, _) = world_with_main_and_math(main, model); let index = world.line_index(&main_uri).expect("main line index"); - let declaration = main.find("M;").expect("module alias") as u32; + let declaration = main.find("M from").expect("module alias") as u32; let type_qualifier = main.find("M.Token").expect("type qualifier") as u32; let ok_qualifier = main.find("M.Token.Ok").expect("Ok qualifier") as u32; let err_qualifier = main.find("M.Token.Err").expect("Err qualifier") as u32; @@ -2440,12 +2426,8 @@ function unwrap(token: M.Token) -> word { #[test] fn local_reexport_of_selected_alias_is_a_local_reference() { - let main = "\ -import math.{double as twice}; -export { twice }; -function main() -> word { return twice(21); } -"; - let math = "function double(x: word) -> word { return x; }\nexport { double };\n"; + let main = "import {double as twice} from math;\nexport { twice };\nfunction main() returns (word) { return twice(21); }\n"; + let math = "function double(x: word) returns (word) { return x; }\nexport { double };\n"; let (world, main_uri, _) = world_with_main_and_math(main, math); let index = world.line_index(&main_uri).expect("main index"); let declaration = main.find("twice").expect("alias declaration") as u32; @@ -2479,15 +2461,16 @@ function main() -> word { return twice(21); } #[test] fn exported_module_alias_references_include_downstream_qualifiers() { let mut world = WorldState::new(); - let util_uri = Url::parse("file:///main/util.solc").expect("util uri"); - let facade_uri = Url::parse("file:///main/facade.solc").expect("facade uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let consumer_uri = Url::parse("file:///main/consumer.solc").expect("consumer uri"); - let util = "function value() -> word { return 1; }\nexport { value };\n"; + let util_uri = Url::parse("file:///main/util.sol").expect("util uri"); + let facade_uri = Url::parse("file:///main/facade.sol").expect("facade uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let consumer_uri = Url::parse("file:///main/consumer.sol").expect("consumer uri"); + let util = "function value() returns (word) { return 1; }\nexport { value };\n"; let facade = "export util as Tools;\n"; - let main = "import facade;\nfunction main() -> word { return facade.Tools.value(); }\n"; + let main = + "import facade;\nfunction main() returns (word) { return facade.Tools.value(); }\n"; let consumer = - "import facade;\nfunction consume() -> word { return facade.Tools.value(); }\n"; + "import facade;\nfunction consume() returns (word) { return facade.Tools.value(); }\n"; assert!(world.open_document(util_uri, util.to_owned())); assert!(world.open_document(facade_uri.clone(), facade.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -2523,12 +2506,8 @@ function main() -> word { return twice(21); } #[test] fn ambiguous_term_and_type_selector_has_no_single_reference_target() { - let main = "import math.{Thing};\nfunction use(x: Thing) -> word { return Thing(); }\n"; - let math = "\ -data Thing = MakeThing; -function Thing() -> word { return 1; } -export { Thing }; -"; + let main = "import {Thing} from math;\nfunction use(x: Thing) returns (word) { return Thing(); }\n"; + let math = "enum Thing {MakeThing}\nfunction Thing() returns (word) { return 1; }\nexport { Thing };\n"; let (world, main_uri, _) = world_with_main_and_math(main, math); let index = world.line_index(&main_uri).expect("main index"); let selector = main.find("Thing").expect("selector") as u32; @@ -2542,15 +2521,14 @@ export { Thing }; #[test] fn exported_module_alias_identity_survives_unaliased_reexport() { let mut world = WorldState::new(); - let util_uri = Url::parse("file:///main/util.solc").expect("util uri"); - let facade_uri = Url::parse("file:///main/facade.solc").expect("facade uri"); - let bridge_uri = Url::parse("file:///main/bridge.solc").expect("bridge uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let util = "function value() -> word { return 1; }\nexport { value };\n"; + let util_uri = Url::parse("file:///main/util.sol").expect("util uri"); + let facade_uri = Url::parse("file:///main/facade.sol").expect("facade uri"); + let bridge_uri = Url::parse("file:///main/bridge.sol").expect("bridge uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let util = "function value() returns (word) { return 1; }\nexport { value };\n"; let facade = "export util as Tools;\n"; let bridge = "export facade;\n"; - let main = - "import bridge;\nfunction main() -> word { return bridge.facade.Tools.value(); }\n"; + let main = "import bridge;\nfunction main() returns (word) { return bridge.facade.Tools.value(); }\n"; assert!(world.open_document(util_uri, util.to_owned())); assert!(world.open_document(facade_uri.clone(), facade.to_owned())); assert!(world.open_document(bridge_uri.clone(), bridge.to_owned())); @@ -2581,13 +2559,12 @@ export { Thing }; #[test] fn constructor_selectors_and_reexports_are_references() { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let bridge_uri = Url::parse("file:///main/bridge.solc").expect("bridge uri"); - let model_uri = Url::parse("file:///main/model.solc").expect("model uri"); - let main = - "import bridge.{Token};\nfunction make(x: word) -> Token { return Token.Ok(x); }\n"; + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let bridge_uri = Url::parse("file:///main/bridge.sol").expect("bridge uri"); + let model_uri = Url::parse("file:///main/model.sol").expect("model uri"); + let main = "import {Token} from bridge;\nfunction make(x: word) returns (Token) { return Token.Ok(x); }\n"; let bridge = "export model.{Token(Ok)};\n"; - let model = "data Token = Ok(word) | Err(word);\nexport { Token(Ok, Err) };\n"; + let model = "enum Token {Ok(word) , Err(word)}\nexport { Token(Ok, Err) };\n"; assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(bridge_uri.clone(), bridge.to_owned())); assert!(world.open_document(model_uri.clone(), model.to_owned())); diff --git a/crates/lsp/src/rename.rs b/crates/lsp/src/rename.rs index 4d7fb0e6..2942848b 100644 --- a/crates/lsp/src/rename.rs +++ b/crates/lsp/src/rename.rs @@ -141,15 +141,15 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } fn world_with_main_and_math(main: &str, math: &str) -> (WorldState, Url, Url) { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(math_uri.clone(), math.to_owned())); (world, main_uri, math_uri) @@ -157,7 +157,7 @@ mod tests { #[test] fn renaming_parameter_edits_declaration_and_uses() { - let source = "function id(x: word) -> word {\n let y = x;\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n let y = x;\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let declaration = source.find("x: word").expect("declaration") as u32; @@ -185,7 +185,7 @@ mod tests { #[test] fn prepare_rename_returns_user_symbol_range_but_not_builtin_or_keyword() { - let source = "function id(x: word) -> word {\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let use_offset = (source.find("return x").expect("use") + "return ".len()) as u32; @@ -213,7 +213,7 @@ mod tests { #[test] fn rename_rejects_invalid_new_name() { - let source = "function id(x: word) -> word {\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n return x;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let use_offset = (source.find("return x").expect("use") + "return ".len()) as u32; @@ -229,8 +229,10 @@ mod tests { #[test] fn renaming_exported_function_edits_import_and_export_names() { - let main = "import math.{double};\nfunction main() -> word { return double(21); }\n"; - let math = "function double(x: word) -> word { return x + x; }\nexport { double };\n"; + let main = + "import {double} from math;\nfunction main() returns (word) { return double(21); }\n"; + let math = + "function double(x: word) returns (word) { return x + x; }\nexport { double };\n"; let (world, main_uri, math_uri) = world_with_main_and_math(main, math); let main_index = world.line_index(&main_uri).expect("main line index"); let math_index = world.line_index(&math_uri).expect("math line index"); @@ -271,7 +273,7 @@ mod tests { #[test] fn embedded_std_symbol_is_not_offered_for_rename() { - let source = "import std.{addWord};\nfunction main() -> word { return addWord(1, 2); }\n"; + let source = "import {addWord} from std;\nfunction main() returns (word) { return addWord(1, 2); }\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let call = source.rfind("addWord").expect("call") as u32; @@ -284,14 +286,11 @@ mod tests { #[test] fn renaming_exported_function_from_defining_module_edits_importer() { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let main = "import math.{double};\nfunction main() -> word { return double(21); }\n"; - let math = "\ -function double(x: word) -> word { return x + x; } -function local() -> word { return double(2); } -export { double }; -"; + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let main = + "import {double} from math;\nfunction main() returns (word) { return double(21); }\n"; + let math = "function double(x: word) returns (word) { return x + x; }\nfunction local() returns (word) { return double(2); }\nexport { double };\n"; assert!(world.open_document(math_uri.clone(), math.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); let main_index = world.line_index(&main_uri).expect("main line index"); @@ -335,9 +334,8 @@ export { double }; #[test] fn renaming_selected_import_alias_only_edits_local_alias_uses() { - let main = - "import math.{double as twice};\nfunction main() -> word { return twice(21); }\n"; - let math = "function double(x: word) -> word { return x; }\nexport { double };\n"; + let main = "import {double as twice} from math;\nfunction main() returns (word) { return twice(21); }\n"; + let math = "function double(x: word) returns (word) { return x; }\nexport { double };\n"; let (world, main_uri, math_uri) = world_with_main_and_math(main, math); let index = world.line_index(&main_uri).expect("main index"); let alias = main.find("twice").expect("alias declaration") as u32; @@ -368,11 +366,12 @@ export { double }; #[test] fn renaming_explicit_module_alias_edits_alias_and_qualifiers() { - let main = "import math as M;\nfunction main() -> word { return M.value(); }\n"; - let math = "function value() -> word { return 1; }\nexport { value };\n"; + let main = + "import * as M from math;\nfunction main() returns (word) { return M.value(); }\n"; + let math = "function value() returns (word) { return 1; }\nexport { value };\n"; let (world, main_uri, _) = world_with_main_and_math(main, math); let index = world.line_index(&main_uri).expect("main index"); - let alias = main.find("M;").expect("alias declaration") as u32; + let alias = main.find("M from").expect("alias declaration") as u32; let use_offset = main.rfind("M.value").expect("alias use") as u32; let edit = handle_rename( @@ -398,19 +397,11 @@ export { double }; #[test] fn renaming_module_alias_updates_type_and_pattern_qualifiers() { - let main = "\ -import math as M; -function unwrap(token: M.Token) -> word { - match token { - | M.Token.Ok(value) => return value; - | M.Token.Err(value) => return value; - } -} -"; - let model = "data Token = Ok(word) | Err(word);\nexport { Token(Ok, Err) };\n"; + let main = "import * as M from math;\nfunction unwrap(token: M.Token) returns (word) {\n match (token) {\n case M.Token.Ok(value) { return value; }\ncase M.Token.Err(value) { return value; }}\n}\n"; + let model = "enum Token {Ok(word) , Err(word)}\nexport { Token(Ok, Err) };\n"; let (world, main_uri, _) = world_with_main_and_math(main, model); let index = world.line_index(&main_uri).expect("main index"); - let declaration = main.find("M;").expect("alias declaration") as u32; + let declaration = main.find("M from").expect("alias declaration") as u32; let type_qualifier = main.find("M.Token").expect("type qualifier") as u32; let ok_qualifier = main.find("M.Token.Ok").expect("Ok qualifier") as u32; let err_qualifier = main.find("M.Token.Err").expect("Err qualifier") as u32; @@ -440,12 +431,8 @@ function unwrap(token: M.Token) -> word { #[test] fn exported_selected_alias_is_not_offered_an_incomplete_text_rename() { - let main = "\ -import math.{double as twice}; -export { twice }; -function main() -> word { return twice(21); } -"; - let math = "function double(x: word) -> word { return x; }\nexport { double };\n"; + let main = "import {double as twice} from math;\nexport { twice };\nfunction main() returns (word) { return twice(21); }\n"; + let math = "function double(x: word) returns (word) { return x; }\nexport { double };\n"; let (world, main_uri, _) = world_with_main_and_math(main, math); let index = world.line_index(&main_uri).expect("main index"); let use_offset = main.rfind("twice").expect("alias use") as u32; @@ -458,15 +445,16 @@ function main() -> word { return twice(21); } #[test] fn renaming_exported_module_alias_updates_downstream_qualifiers() { let mut world = WorldState::new(); - let util_uri = Url::parse("file:///main/util.solc").expect("util uri"); - let facade_uri = Url::parse("file:///main/facade.solc").expect("facade uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let consumer_uri = Url::parse("file:///main/consumer.solc").expect("consumer uri"); - let util = "function value() -> word { return 1; }\nexport { value };\n"; + let util_uri = Url::parse("file:///main/util.sol").expect("util uri"); + let facade_uri = Url::parse("file:///main/facade.sol").expect("facade uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let consumer_uri = Url::parse("file:///main/consumer.sol").expect("consumer uri"); + let util = "function value() returns (word) { return 1; }\nexport { value };\n"; let facade = "export util as Tools;\n"; - let main = "import facade;\nfunction main() -> word { return facade.Tools.value(); }\n"; + let main = + "import facade;\nfunction main() returns (word) { return facade.Tools.value(); }\n"; let consumer = - "import facade;\nfunction consume() -> word { return facade.Tools.value(); }\n"; + "import facade;\nfunction consume() returns (word) { return facade.Tools.value(); }\n"; assert!(world.open_document(util_uri, util.to_owned())); assert!(world.open_document(facade_uri.clone(), facade.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -517,12 +505,13 @@ function main() -> word { return twice(21); } #[test] fn source_definition_rename_is_rejected_across_exported_selected_alias() { let mut world = WorldState::new(); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let bridge_uri = Url::parse("file:///main/bridge.solc").expect("bridge uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let math = "function double(x: word) -> word { return x; }\nexport { double };\n"; - let bridge = "import math.{double as twice};\nexport { twice };\n"; - let main = "import bridge.{twice};\nfunction main() -> word { return twice(1); }\n"; + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let bridge_uri = Url::parse("file:///main/bridge.sol").expect("bridge uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let math = "function double(x: word) returns (word) { return x; }\nexport { double };\n"; + let bridge = "import {double as twice} from math;\nexport { twice };\n"; + let main = + "import {twice} from bridge;\nfunction main() returns (word) { return twice(1); }\n"; assert!(world.open_document(math_uri.clone(), math.to_owned())); assert!(world.open_document(bridge_uri, bridge.to_owned())); assert!(world.open_document(main_uri, main.to_owned())); @@ -541,15 +530,16 @@ function main() -> word { return twice(21); } let right_path = base.join("right"); let left_root = Url::from_directory_path(&left_path).expect("left root"); let right_root = Url::from_directory_path(&right_path).expect("right root"); - let left_main = Url::from_file_path(left_path.join("main.solc")).expect("left main"); - let left_math = Url::from_file_path(left_path.join("math.solc")).expect("left math"); - let right_main = Url::from_file_path(right_path.join("main.solc")).expect("right main"); - let right_math = Url::from_file_path(right_path.join("math.solc")).expect("right math"); - let left_source = "import lib.math.{value};\nfunction left() -> word { return value(); }\n"; + let left_main = Url::from_file_path(left_path.join("main.sol")).expect("left main"); + let left_math = Url::from_file_path(left_path.join("math.sol")).expect("left math"); + let right_main = Url::from_file_path(right_path.join("main.sol")).expect("right main"); + let right_math = Url::from_file_path(right_path.join("math.sol")).expect("right math"); + let left_source = + "import {value} from lib.math;\nfunction left() returns (word) { return value(); }\n"; let right_source = - "import lib.math.{value};\nfunction right() -> word { return value(); }\n"; - let left_library = "function value() -> word { return 1; }\nexport { value };\n"; - let right_library = "function value() -> word { return 2; }\nexport { value };\n"; + "import {value} from lib.math;\nfunction right() returns (word) { return value(); }\n"; + let left_library = "function value() returns (word) { return 1; }\nexport { value };\n"; + let right_library = "function value() returns (word) { return 2; }\nexport { value };\n"; let mut world = WorldState::new(); world.load_workspace_roots([ ( @@ -589,15 +579,14 @@ function main() -> word { return twice(21); } #[test] fn renaming_exported_module_alias_updates_unaliased_reexport_chain() { let mut world = WorldState::new(); - let util_uri = Url::parse("file:///main/util.solc").expect("util uri"); - let facade_uri = Url::parse("file:///main/facade.solc").expect("facade uri"); - let bridge_uri = Url::parse("file:///main/bridge.solc").expect("bridge uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let util = "function value() -> word { return 1; }\nexport { value };\n"; + let util_uri = Url::parse("file:///main/util.sol").expect("util uri"); + let facade_uri = Url::parse("file:///main/facade.sol").expect("facade uri"); + let bridge_uri = Url::parse("file:///main/bridge.sol").expect("bridge uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let util = "function value() returns (word) { return 1; }\nexport { value };\n"; let facade = "export util as Tools;\n"; let bridge = "export facade;\n"; - let main = - "import bridge;\nfunction main() -> word { return bridge.facade.Tools.value(); }\n"; + let main = "import bridge;\nfunction main() returns (word) { return bridge.facade.Tools.value(); }\n"; assert!(world.open_document(util_uri, util.to_owned())); assert!(world.open_document(facade_uri.clone(), facade.to_owned())); assert!(world.open_document(bridge_uri.clone(), bridge.to_owned())); @@ -635,12 +624,13 @@ function main() -> word { return twice(21); } #[test] fn default_module_reexport_without_alias_is_not_text_renameable() { let mut world = WorldState::new(); - let util_uri = Url::parse("file:///main/util.solc").expect("util uri"); - let facade_uri = Url::parse("file:///main/facade.solc").expect("facade uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let util = "function value() -> word { return 1; }\nexport { value };\n"; + let util_uri = Url::parse("file:///main/util.sol").expect("util uri"); + let facade_uri = Url::parse("file:///main/facade.sol").expect("facade uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let util = "function value() returns (word) { return 1; }\nexport { value };\n"; let facade = "export util;\n"; - let main = "import facade;\nfunction main() -> word { return facade.util.value(); }\n"; + let main = + "import facade;\nfunction main() returns (word) { return facade.util.value(); }\n"; assert!(world.open_document(util_uri, util.to_owned())); assert!(world.open_document(facade_uri, facade.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -655,11 +645,10 @@ function main() -> word { return twice(21); } #[test] fn renaming_constructor_updates_import_and_export_selectors() { let mut world = WorldState::new(); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); - let model_uri = Url::parse("file:///main/model.solc").expect("model uri"); - let main = - "import model.{Token};\nfunction make(x: word) -> Token { return Token.Ok(x); }\n"; - let model = "data Token = Ok(word) | Err(word);\nexport { Token(Ok, Err) };\n"; + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); + let model_uri = Url::parse("file:///main/model.sol").expect("model uri"); + let main = "import {Token} from model;\nfunction make(x: word) returns (Token) { return Token.Ok(x); }\n"; + let model = "enum Token {Ok(word) , Err(word)}\nexport { Token(Ok, Err) };\n"; assert!(world.open_document(main_uri.clone(), main.to_owned())); assert!(world.open_document(model_uri.clone(), model.to_owned())); let main_index = world.line_index(&main_uri).expect("main index"); diff --git a/crates/lsp/src/selection_range.rs b/crates/lsp/src/selection_range.rs index 198270f6..55b4e96f 100644 --- a/crates/lsp/src/selection_range.rs +++ b/crates/lsp/src/selection_range.rs @@ -259,10 +259,13 @@ fn is_two_byte_operator(bytes: Option<&[u8]>) -> bool { | b"||" | b"+=" | b"-=" + | b"*=" + | b"/=" | b"^=" | b"&=" | b"|=" | b"%=" + | b"~=" ) ) } @@ -376,7 +379,7 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } @@ -393,8 +396,7 @@ mod tests { #[test] fn builds_unicode_safe_leaf_to_module_chain() { - let source = - "function main(value: word) -> word {\n let café = (value + 1);\n return café;\n}\n"; + let source = "function main(value: word) returns (word) {\n let café = (value + 1);\n return café;\n}\n"; let (world, uri) = world_with_main(source); let line_index = world.line_index(&uri).expect("line index"); let leaf_start = source.find("café").expect("unicode identifier"); @@ -453,14 +455,7 @@ mod tests { #[test] fn overlapping_source_line_does_not_hide_multiline_call_selection() { - let source = "\ -function main() -> word { - let x = add( - 1, - 2); // trailing - return x; -} -"; + let source = "function main() returns (word) {\n let x = add(\n 1,\n 2); // trailing\n return x;\n}\n"; let (world, uri) = world_with_main(source); let position = Position::new(3, 4); let ranges = handle_selection_range(&world, &uri, &[position]).expect("selection ranges"); @@ -479,7 +474,7 @@ function main() -> word { #[test] fn leaf_ranges_follow_identifier_and_operator_token_boundaries() { - let source = "pragma no-bounded-variable-condition;\nfunction main() -> word {\n let value = 1;\n return value-1;\n}\n"; + let source = "pragma no-bounded-variable-condition;\nfunction main() returns (word) {\n let value = 1;\n return value-1;\n}\n"; let (world, uri) = world_with_main(source); let index = world.line_index(&uri).unwrap(); let pragma = source.find("no-bounded").unwrap(); @@ -503,6 +498,21 @@ function main() -> word { ); } + #[test] + fn compound_assignment_leaf_ranges_include_every_canonical_operator() { + let source = "left *= right; left /= right; left ~=;"; + for operator in ["*=", "/=", "~="] { + let start = source.find(operator).expect("operator"); + assert_eq!( + leaf_range_at(source, start + 1), + Some(ByteRange { + start, + end: start + operator.len(), + }) + ); + } + } + #[test] fn rejects_out_of_range_and_mid_surrogate_positions() { let source = "// 😀\n"; @@ -523,7 +533,7 @@ function main() -> word { let (world, uri) = world_with_main(""); assert_eq!(handle_selection_range(&world, &uri, &[]), Some(Vec::new())); - let missing = Url::parse("file:///main/missing.solc").expect("uri"); + let missing = Url::parse("file:///main/missing.sol").expect("uri"); assert_eq!(handle_selection_range(&world, &missing, &[]), None); } } diff --git a/crates/lsp/src/semantic_tokens.rs b/crates/lsp/src/semantic_tokens.rs index ba822d23..b08fb28e 100644 --- a/crates/lsp/src/semantic_tokens.rs +++ b/crates/lsp/src/semantic_tokens.rs @@ -676,14 +676,14 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn semantic_tokens_are_non_empty_ordered_and_start_at_first_named_entity() { - let source = "function main(x: word) -> word {\n let y = x;\n return y;\n}\n"; + let source = "function main(x: word) returns (word) {\n let y = x;\n return y;\n}\n"; let (world, uri) = world_with_main(source); let result = handle_semantic_tokens_full(&world, &uri).expect("semantic tokens"); @@ -704,17 +704,7 @@ mod tests { #[test] fn emitted_token_type_indexes_are_covered_by_the_legend() { - let source = "\ -data Maybe = None | Some(word); - -contract Box { - value: word; - function get(x: word) -> word { - let current = value; - return current + x; - } -} -"; + let source = "enum Maybe {None , Some(word)}\n\ncontract Box {\n value: word;\n function get(x: word) returns (word) {\n let current = value;\n return current + x;\n }\n}\n"; let (world, uri) = world_with_main(source); let result = handle_semantic_tokens_full(&world, &uri).expect("semantic tokens"); diff --git a/crates/lsp/src/signature_help.rs b/crates/lsp/src/signature_help.rs index 3ad0360a..46777d21 100644 --- a/crates/lsp/src/signature_help.rs +++ b/crates/lsp/src/signature_help.rs @@ -324,7 +324,11 @@ fn signature_from_scheme<'db>( .unwrap_or(ty) }) .collect::>(); - let label = format!("{name}({}) -> {}", parameters.join(", "), ret.display(db)); + let label = format!( + "{name}({}) returns ({})", + parameters.join(", "), + ret.display(db) + ); Some(CallableSignature { label, parameters }) } @@ -478,7 +482,7 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } @@ -493,7 +497,7 @@ mod tests { #[test] fn highlights_first_argument() { - let source = "function f(a: word, b: word) -> word {\n return a;\n}\n\nfunction main() -> word {\n return f(1, 2);\n}\n"; + let source = "function f(a: word, b: word) returns (word) {\n return a;\n}\n\nfunction main() returns (word) {\n return f(1, 2);\n}\n"; let (world, uri) = world_with_main(source); let position = position_at(source, &world, &uri, "1, 2"); @@ -506,7 +510,7 @@ mod tests { #[test] fn highlights_second_argument_and_labels_signature() { - let source = "function f(a: word, b: word) -> word {\n return a;\n}\n\nfunction main() -> word {\n return f(1, 2);\n}\n"; + let source = "function f(a: word, b: word) returns (word) {\n return a;\n}\n\nfunction main() returns (word) {\n return f(1, 2);\n}\n"; let (world, uri) = world_with_main(source); let comma_offset = source.find(", 2").expect("comma") as u32 + 1; let position = world @@ -535,7 +539,7 @@ mod tests { signature.label ); assert!( - signature.label.contains("-> word"), + signature.label.contains("returns (word)"), "expected return type in label, got {}", signature.label ); @@ -543,10 +547,10 @@ mod tests { #[test] fn signature_help_uses_requested_module_when_unrelated_document_opened_first() { - let unrelated = "function unrelated() -> word { return 0; }\n"; - let main = "function combine(a: word, b: word) -> word { return a; }\n\nfunction main() -> word {\n return combine(1, 2);\n}\n"; - let unrelated_uri = Url::parse("file:///main/unrelated.solc").expect("unrelated uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let unrelated = "function unrelated() returns (word) { return 0; }\n"; + let main = "function combine(a: word, b: word) returns (word) { return a; }\n\nfunction main() returns (word) {\n return combine(1, 2);\n}\n"; + let unrelated_uri = Url::parse("file:///main/unrelated.sol").expect("unrelated uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); let mut world = WorldState::new(); assert!(world.open_document(unrelated_uri, unrelated.to_owned())); assert!(world.open_document(main_uri.clone(), main.to_owned())); @@ -572,14 +576,12 @@ mod tests { #[test] fn signature_help_resolves_imported_function_in_defining_module() { - let unrelated = "function unrelated() -> word { return 0; }\n"; - let math = - "function combine(a: word, b: word) -> word { return a; }\n\nexport { combine };\n"; - let main = - "import math.{combine};\n\nfunction main() -> word {\n return combine(1, 2);\n}\n"; - let unrelated_uri = Url::parse("file:///main/unrelated.solc").expect("unrelated uri"); - let math_uri = Url::parse("file:///main/math.solc").expect("math uri"); - let main_uri = Url::parse("file:///main/main.solc").expect("main uri"); + let unrelated = "function unrelated() returns (word) { return 0; }\n"; + let math = "function combine(a: word, b: word) returns (word) { return a; }\n\nexport { combine };\n"; + let main = "import {combine} from math;\n\nfunction main() returns (word) {\n return combine(1, 2);\n}\n"; + let unrelated_uri = Url::parse("file:///main/unrelated.sol").expect("unrelated uri"); + let math_uri = Url::parse("file:///main/math.sol").expect("math uri"); + let main_uri = Url::parse("file:///main/main.sol").expect("main uri"); let mut world = WorldState::new(); assert!(world.open_document(unrelated_uri, unrelated.to_owned())); assert!(world.open_document(math_uri, math.to_owned())); diff --git a/crates/lsp/src/state.rs b/crates/lsp/src/state.rs index 74c1c3f3..49bf74e6 100644 --- a/crates/lsp/src/state.rs +++ b/crates/lsp/src/state.rs @@ -557,7 +557,7 @@ impl WorldState { .file_name() .and_then(|name| name.to_str()) .filter(|name| !name.is_empty()) - .unwrap_or("document.solc") + .unwrap_or("document.sol") .to_owned(); (hex_encode(identity.as_bytes()), filename) }); @@ -605,7 +605,7 @@ impl WorldState { .extension() .and_then(|extension| extension.to_str()) .filter(|extension| !extension.is_empty()) - .unwrap_or("solc"); + .unwrap_or("sol"); Some(format!("/main/__virtual__/{id}.{extension}")) } } @@ -731,22 +731,22 @@ mod tests { #[test] fn maps_main_file_uris_to_vfs_paths() { - let uri = Url::parse("file:///main/main.solc").expect("uri"); - assert_eq!(uri_to_vfs_path(&uri), Some("/main/main.solc".to_owned())); + let uri = Url::parse("file:///main/main.sol").expect("uri"); + assert_eq!(uri_to_vfs_path(&uri), Some("/main/main.sol".to_owned())); - let std_uri = Url::parse("file:///std/std.solc").expect("uri"); + let std_uri = Url::parse("file:///std/std.sol").expect("uri"); assert_eq!(uri_to_vfs_path(&std_uri), None); - let memory_uri = Url::parse("memory:///main/main.solc").expect("uri"); + let memory_uri = Url::parse("memory:///main/main.sol").expect("uri"); assert_eq!(uri_to_vfs_path(&memory_uri), None); } #[test] fn open_change_and_close_document() { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); - let clean = "function main() -> word {\n return 1;\n}\n"; - let changed = "function main() -> word {\n return 2;\n}\n"; + let uri = Url::parse("file:///main/main.sol").expect("uri"); + let clean = "function main() returns (word) {\n return 1;\n}\n"; + let changed = "function main() returns (word) {\n return 2;\n}\n"; assert!(world.open_document(uri.clone(), clean.to_owned())); assert_eq!(world.document_text(&uri), Some(clean)); @@ -763,7 +763,7 @@ mod tests { use lsp_types::{Position, Range}; let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), "a😀c\n".to_owned())); assert!(world.apply_document_changes( @@ -799,8 +799,8 @@ mod tests { let mut world = WorldState::new(); let root_path = std::env::temp_dir().join("solcore-lsp-state-project"); let root = Url::from_directory_path(&root_path).expect("root uri"); - let main_uri = Url::from_file_path(root_path.join("src/main.solc")).expect("main uri"); - let util_uri = Url::from_file_path(root_path.join("src/util.solc")).expect("util uri"); + let main_uri = Url::from_file_path(root_path.join("src/main.sol")).expect("main uri"); + let util_uri = Url::from_file_path(root_path.join("src/util.sol")).expect("util uri"); assert_eq!( world.load_workspace_documents( @@ -808,11 +808,11 @@ mod tests { [ ( main_uri.clone(), - "function main() -> word { return 1; }\n".to_owned() + "function main() returns (word) { return 1; }\n".to_owned() ), ( util_uri.clone(), - "function util() -> word { return 2; }\n".to_owned() + "function util() returns (word) { return 2; }\n".to_owned() ), ], ), @@ -820,15 +820,15 @@ mod tests { ); assert_eq!( world.vfs_path_for_uri(&main_uri), - Some("/main/src/main.solc".to_owned()) + Some("/main/src/main.sol".to_owned()) ); assert_eq!( - world.client_uri_for_vfs_url("file:///main/src/util.solc"), + world.client_uri_for_vfs_url("file:///main/src/util.sol"), Some(util_uri) ); assert!(world.open_document( main_uri.clone(), - "function main() -> word { return 1; }\n".to_owned() + "function main() returns (word) { return 1; }\n".to_owned() )); assert_eq!(world.open_document_uris(), vec![main_uri]); assert_eq!(world.workspace_document_uris().len(), 2); @@ -839,23 +839,23 @@ mod tests { let mut world = WorldState::new(); let root_path = std::env::temp_dir().join("solcore-lsp-state-encoded-project"); let root = Url::from_directory_path(&root_path).expect("root uri"); - let uri = Url::from_file_path(root_path.join("src/数 学.solc")).expect("encoded uri"); + let uri = Url::from_file_path(root_path.join("src/数 学.sol")).expect("encoded uri"); assert_eq!( world.load_workspace_documents( root, [( uri.clone(), - "function value() -> word { return 1; }\n".to_owned() + "function value() returns (word) { return 1; }\n".to_owned() )] ), 1 ); assert_eq!( world.vfs_path_for_uri(&uri), - Some("/main/src/数 学.solc".to_owned()) + Some("/main/src/数 学.sol".to_owned()) ); assert_eq!( - world.client_uri_for_vfs_url("file:///main/src/%E6%95%B0%20%E5%AD%A6.solc"), + world.client_uri_for_vfs_url("file:///main/src/%E6%95%B0%20%E5%AD%A6.sol"), Some(uri) ); } @@ -867,9 +867,9 @@ mod tests { let right_path = base.join("right"); let left_root = Url::from_directory_path(&left_path).expect("left root uri"); let right_root = Url::from_directory_path(&right_path).expect("right root uri"); - let left_uri = Url::from_file_path(left_path.join("src/main.solc")).expect("left uri"); - let right_uri = Url::from_file_path(right_path.join("src/main.solc")).expect("right uri"); - let source = "function value() -> word { return 1; }\n"; + let left_uri = Url::from_file_path(left_path.join("src/main.sol")).expect("left uri"); + let right_uri = Url::from_file_path(right_path.join("src/main.sol")).expect("right uri"); + let source = "function value() returns (word) { return 1; }\n"; let mut world = WorldState::new(); assert_eq!( @@ -890,8 +890,8 @@ mod tests { let right_vfs = world.vfs_path_for_uri(&right_uri).expect("right vfs path"); assert!(left_vfs.starts_with("/main/__solcore_workspace__/")); assert!(right_vfs.starts_with("/main/__solcore_workspace__/")); - assert!(left_vfs.ends_with("/src/main.solc")); - assert!(right_vfs.ends_with("/src/main.solc")); + assert!(left_vfs.ends_with("/src/main.sol")); + assert!(right_vfs.ends_with("/src/main.sol")); assert_ne!(left_vfs, right_vfs); assert_eq!(world.workspace_root_count(), 2); assert_eq!( @@ -916,8 +916,8 @@ mod tests { fn configured_main_file_root_uses_multi_root_namespace_before_virtual_mapping() { let main_root = Url::parse("file:///main/").expect("main root"); let other_root = Url::parse("file:///workspace/other/").expect("other root"); - let main_uri = Url::parse("file:///main/project.solc").expect("main uri"); - let other_uri = Url::parse("file:///workspace/other/project.solc").expect("other uri"); + let main_uri = Url::parse("file:///main/project.sol").expect("main uri"); + let other_uri = Url::parse("file:///workspace/other/project.sol").expect("other uri"); let mut world = WorldState::new(); world.load_workspace_roots([ @@ -942,15 +942,15 @@ mod tests { fn rootless_main_document_is_remapped_when_workspace_folders_arrive() { let main_root = Url::parse("file:///main/").expect("main root"); let other_root = Url::parse("file:///workspace/other/").expect("other root"); - let main_uri = Url::parse("file:///main/project.solc").expect("main uri"); + let main_uri = Url::parse("file:///main/project.sol").expect("main uri"); let mut world = WorldState::new(); assert!(world.open_document( main_uri.clone(), - "function value() -> word { return 1; }\n".to_owned() + "function value() returns (word) { return 1; }\n".to_owned() )); assert_eq!( world.vfs_path_for_uri(&main_uri), - Some("/main/project.solc".to_owned()) + Some("/main/project.sol".to_owned()) ); world.update_workspace_roots( @@ -973,16 +973,16 @@ mod tests { let right_path = base.join("right"); let left_root = Url::from_directory_path(&left_path).expect("left root uri"); let right_root = Url::from_directory_path(&right_path).expect("right root uri"); - let left_main = Url::from_file_path(left_path.join("main.solc")).expect("left main uri"); - let left_math = Url::from_file_path(left_path.join("math.solc")).expect("left math uri"); - let right_main = Url::from_file_path(right_path.join("main.solc")).expect("right main uri"); - let right_math = Url::from_file_path(right_path.join("math.solc")).expect("right math uri"); - let left_source = - "import lib.math.{leftValue};\nfunction runLeft() -> word { return leftValue(); }\n"; - let left_library = "function leftValue() -> word { return 1; }\nexport { leftValue };\n"; - let right_source = - "import lib.math.{rightValue};\nfunction runRight() -> word { return rightValue(); }\n"; - let right_library = "function rightValue() -> word { return 2; }\nexport { rightValue };\n"; + let left_main = Url::from_file_path(left_path.join("main.sol")).expect("left main uri"); + let left_math = Url::from_file_path(left_path.join("math.sol")).expect("left math uri"); + let right_main = Url::from_file_path(right_path.join("main.sol")).expect("right main uri"); + let right_math = Url::from_file_path(right_path.join("math.sol")).expect("right math uri"); + let left_source = "import {leftValue} from lib.math;\nfunction runLeft() returns (word) { return leftValue(); }\n"; + let left_library = + "function leftValue() returns (word) { return 1; }\nexport { leftValue };\n"; + let right_source = "import {rightValue} from lib.math;\nfunction runRight() returns (word) { return rightValue(); }\n"; + let right_library = + "function rightValue() returns (word) { return 2; }\nexport { rightValue };\n"; let mut world = WorldState::new(); world.load_workspace_roots([ @@ -1036,10 +1036,10 @@ mod tests { let right_path = base.join("right"); let left_root = Url::from_directory_path(&left_path).expect("left root uri"); let right_root = Url::from_directory_path(&right_path).expect("right root uri"); - let left_uri = Url::from_file_path(left_path.join("shared.solc")).expect("left uri"); - let right_uri = Url::from_file_path(right_path.join("shared.solc")).expect("right uri"); + let left_uri = Url::from_file_path(left_path.join("shared.sol")).expect("left uri"); + let right_uri = Url::from_file_path(right_path.join("shared.sol")).expect("right uri"); let generated_uri = - Url::from_file_path(right_path.join("generated.solc")).expect("generated uri"); + Url::from_file_path(right_path.join("generated.sol")).expect("generated uri"); let mut world = WorldState::new(); world.load_workspace_roots([ @@ -1083,11 +1083,11 @@ mod tests { let right_path = base.join("right"); let left_root = Url::from_directory_path(&left_path).expect("left root uri"); let right_root = Url::from_directory_path(&right_path).expect("right root uri"); - let left_main = Url::from_file_path(left_path.join("main.solc")).expect("left main uri"); - let left_util = Url::from_file_path(left_path.join("util.solc")).expect("left util uri"); - let right_main = Url::from_file_path(right_path.join("main.solc")).expect("right main uri"); - let disk_source = "function value() -> word { return 1; }\n"; - let unsaved_source = "function value() -> word { return 99; }\n"; + let left_main = Url::from_file_path(left_path.join("main.sol")).expect("left main uri"); + let left_util = Url::from_file_path(left_path.join("util.sol")).expect("left util uri"); + let right_main = Url::from_file_path(right_path.join("main.sol")).expect("right main uri"); + let disk_source = "function value() returns (word) { return 1; }\n"; + let unsaved_source = "function value() returns (word) { return 99; }\n"; let mut world = WorldState::new(); world.load_workspace_roots([ @@ -1164,14 +1164,15 @@ mod tests { let left_root = Url::from_directory_path(&left_path).expect("left root"); let right_root = Url::from_directory_path(&right_path).expect("right root"); let third_root = Url::from_directory_path(&third_path).expect("third root"); - let left_main = Url::from_file_path(left_path.join("main.solc")).expect("left main"); - let left_math = Url::from_file_path(left_path.join("math.solc")).expect("left math"); - let right_math = Url::from_file_path(right_path.join("math.solc")).expect("right math"); - let third_file = Url::from_file_path(third_path.join("third.solc")).expect("third file"); - let main_source = - "import lib.math.{leftValue};\nfunction main() -> word { return leftValue(); }\n"; - let left_source = "function leftValue() -> word { return 1; }\nexport { leftValue };\n"; - let right_source = "function rightValue() -> word { return 2; }\nexport { rightValue };\n"; + let left_main = Url::from_file_path(left_path.join("main.sol")).expect("left main"); + let left_math = Url::from_file_path(left_path.join("math.sol")).expect("left math"); + let right_math = Url::from_file_path(right_path.join("math.sol")).expect("right math"); + let third_file = Url::from_file_path(third_path.join("third.sol")).expect("third file"); + let main_source = "import {leftValue} from lib.math;\nfunction main() returns (word) { return leftValue(); }\n"; + let left_source = + "function leftValue() returns (word) { return 1; }\nexport { leftValue };\n"; + let right_source = + "function rightValue() returns (word) { return 2; }\nexport { rightValue };\n"; let mut world = WorldState::new(); world.load_workspace_roots([ @@ -1207,7 +1208,7 @@ mod tests { third_root, vec![( third_file, - "function third() -> word { return 3; }\n".to_owned(), + "function third() returns (word) { return 3; }\n".to_owned(), )], )], ); @@ -1240,13 +1241,13 @@ mod tests { fn file_uri_drive_letters_are_normalized_without_folding_path_case() { let root = Url::parse("file:///c:/CaseSensitive/Project").expect("root uri"); let matching = - Url::parse("file:///C:/CaseSensitive/Project/main.solc").expect("matching uri"); + Url::parse("file:///C:/CaseSensitive/Project/main.sol").expect("matching uri"); let wrong_case = - Url::parse("file:///C:/casesensitive/Project/main.solc").expect("wrong-case uri"); + Url::parse("file:///C:/casesensitive/Project/main.sol").expect("wrong-case uri"); assert_eq!( workspace_relative_path(&root, &matching).as_deref(), - Some("main.solc") + Some("main.sol") ); assert_eq!(workspace_relative_path(&root, &wrong_case), None); } @@ -1256,18 +1257,18 @@ mod tests { let mut world = WorldState::new(); let file = std::env::temp_dir() .join("solcore-lsp-inferred-root") - .join("main.solc"); + .join("main.sol"); let uri = Url::from_file_path(file).expect("real file uri"); assert!(world.open_document( uri.clone(), - "function main() -> word { return 1; }\n".to_owned() + "function main() returns (word) { return 1; }\n".to_owned() )); assert!(world.has_workspace_root()); assert_eq!( world.vfs_path_for_uri(&uri), - Some("/main/main.solc".to_owned()) + Some("/main/main.sol".to_owned()) ); } @@ -1277,14 +1278,14 @@ mod tests { let uri = Url::parse("untitled:Untitled-1").expect("untitled uri"); assert!(world.open_document( uri.clone(), - "function main() -> word { return 1; }\n".to_owned() + "function main() returns (word) { return 1; }\n".to_owned() )); assert_eq!( world.vfs_path_for_uri(&uri), - Some("/main/__virtual__/0.solc".to_owned()) + Some("/main/__virtual__/0.sol".to_owned()) ); assert_eq!( - world.client_uri_for_vfs_url("file:///main/__virtual__/0.solc"), + world.client_uri_for_vfs_url("file:///main/__virtual__/0.sol"), Some(uri) ); } @@ -1295,7 +1296,7 @@ mod tests { let uri = Url::parse("untitled:Untitled-1").expect("untitled uri"); assert!(world.open_document( uri.clone(), - "function main() -> word { return 1; }\n".to_owned() + "function main() returns (word) { return 1; }\n".to_owned() )); world.close_document(&uri); @@ -1308,8 +1309,8 @@ mod tests { #[test] fn unix_backslash_in_filename_does_not_become_a_path_separator() { assert_eq!( - relative_url_path("src/name\\part.solc"), - Some("src/name\\part.solc".to_owned()) + relative_url_path("src/name\\part.sol"), + Some("src/name\\part.sol".to_owned()) ); } } diff --git a/crates/lsp/src/symbols.rs b/crates/lsp/src/symbols.rs index 5c5be4ce..e8297834 100644 --- a/crates/lsp/src/symbols.rs +++ b/crates/lsp/src/symbols.rs @@ -166,7 +166,7 @@ fn instance_symbol<'db>( Some(document_symbol( db, line_index, - format!("instance {}", class.atom().text(db)), + format!("impl {}", class.atom().text(db)), SymbolKind::OBJECT, instance.span(db), class.span(db), @@ -214,29 +214,14 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn document_symbols_include_top_level_items_and_contract_children() { - let source = "\ -function foo(x: word) -> word { - return x; -} - -type Pair = pair(word, word); - -data Maybe = None | Some(word); - -contract Box { - item: word; - function get() -> word { - return item; - } -} -"; + let source = "function foo(x: word) returns (word) {\n return x;\n}\n\ntype Pair = pair;\n\nenum Maybe {None , Some(word)}\n\ncontract Box {\n item: word;\n function get() returns (word) {\n return item;\n }\n}\n"; let (world, uri) = world_with_main(source); let response = handle_document_symbol(&world, &uri).expect("symbols"); let DocumentSymbolResponse::Nested(symbols) = response else { diff --git a/crates/lsp/src/wasm.rs b/crates/lsp/src/wasm.rs index ec619b41..9c7c1ac6 100644 --- a/crates/lsp/src/wasm.rs +++ b/crates/lsp/src/wasm.rs @@ -582,8 +582,8 @@ fn json_string(value: Value) -> String { mod tests { use super::*; - const URI: &str = "file:///main/main.solc"; - const MATH_URI: &str = "file:///main/math.solc"; + const URI: &str = "file:///main/main.sol"; + const MATH_URI: &str = "file:///main/math.sol"; #[test] fn initialize_returns_capabilities_response() { @@ -660,7 +660,7 @@ mod tests { #[test] fn did_open_publishes_diagnostics() { let mut world = WorldState::new(); - let source = "function f() -> word {\n return true;\n}\n"; + let source = "function f() returns (word) {\n return true;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -679,10 +679,10 @@ mod tests { #[test] fn did_change_republishes_importer_diagnostics_when_sibling_exports_change() { let mut world = WorldState::new(); - let main = "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n"; - let math_no_export = "function double(x: word) -> word { return x; }\n"; + let main = "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n"; + let math_no_export = "function double(x: word) returns (word) { return x; }\n"; let math_with_export = - "function double(x: word) -> word { return x; }\n\nexport { double };\n"; + "function double(x: word) returns (word) { return x; }\n\nexport { double };\n"; let _ = dispatch(&mut world, &did_open_uri_message(URI, main)); let opened_math = dispatch(&mut world, &did_open_uri_message(MATH_URI, math_no_export)); @@ -719,7 +719,7 @@ mod tests { #[test] fn hover_and_document_symbol_requests_return_results() { let mut world = WorldState::new(); - let source = "function main() -> word {\n return 42;\n}\n"; + let source = "function main() returns (word) {\n return 42;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -768,7 +768,7 @@ mod tests { #[test] fn completion_request_returns_items() { let mut world = WorldState::new(); - let source = "function helper() -> word { return 1; }\nfunction main(x: word) -> word { return x; }\n"; + let source = "function helper() returns (word) { return 1; }\nfunction main(x: word) returns (word) { return x; }\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); let character = source @@ -807,7 +807,7 @@ mod tests { #[test] fn references_request_returns_locations() { let mut world = WorldState::new(); - let source = "function id(x: word) -> word {\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n return x;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -842,7 +842,7 @@ mod tests { #[test] fn signature_help_request_returns_active_parameter() { let mut world = WorldState::new(); - let source = "function f(a: word, b: word) -> word {\n return a;\n}\n\nfunction main() -> word {\n return f(1, 2);\n}\n"; + let source = "function f(a: word, b: word) returns (word) {\n return a;\n}\n\nfunction main() returns (word) {\n return f(1, 2);\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -877,7 +877,7 @@ mod tests { #[test] fn semantic_tokens_full_request_returns_tokens() { let mut world = WorldState::new(); - let source = "function main(x: word) -> word {\n return x;\n}\n"; + let source = "function main(x: word) returns (word) {\n return x;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -910,7 +910,7 @@ mod tests { #[test] fn inlay_hint_request_returns_results() { let mut world = WorldState::new(); - let source = "function main() -> word {\n let x = 42;\n return x;\n}\n"; + let source = "function main() returns (word) {\n let x = 42;\n return x;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -941,7 +941,7 @@ mod tests { #[test] fn workspace_symbol_request_returns_matching_symbols() { let mut world = WorldState::new(); - let source = "function target() -> word {\n return 42;\n}\n"; + let source = "function target() returns (word) {\n return 42;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -971,7 +971,7 @@ mod tests { #[test] fn code_action_formatting_folding_and_selection_requests_return_results() { let mut world = WorldState::new(); - let source = "function value() -> word { return 1; }\nfunction main() -> word {\n/* 😀 */ return vaue();\n}\n"; + let source = "function value() returns (word) { return 1; }\nfunction main() returns (word) {\n/* 😀 */ return vaue();\n}\n"; let opened = dispatch(&mut world, &did_open_message(source)); let notification = diagnostic_notification_for_uri(&opened, URI); let diagnostic = notification["params"]["diagnostics"] @@ -1077,8 +1077,8 @@ mod tests { #[test] fn missing_import_code_action_round_trips_over_wasm_dispatch() { let mut world = WorldState::new(); - let provider = "function value() -> word { return 1; }\n\nexport { value };\n"; - let main = "function main() -> word { return value(); }\n"; + let provider = "function value() returns (word) { return 1; }\n\nexport { value };\n"; + let main = "function main() returns (word) { return value(); }\n"; let _ = dispatch(&mut world, &did_open_uri_message(MATH_URI, provider)); let opened = dispatch(&mut world, &did_open_uri_message(URI, main)); @@ -1124,7 +1124,7 @@ mod tests { "start": { "line": 0, "character": 0 }, "end": { "line": 0, "character": 0 } }, - "newText": "import lib.math.{value};\n" + "newText": "import {value} from lib.math;\n" }) ); } @@ -1133,14 +1133,14 @@ mod tests { fn qualified_import_code_actions_round_trip_over_wasm_dispatch() { let cases = [ ( - "data Option = None | Some(word);\nexport { Option(*) };\n", - "function main() -> word { let option = Option.Some(1); return 1; }\n", + "enum Option {None , Some(word)}\nexport { Option(*) };\n", + "function main() returns (word) { let option = Option.Some(1); return 1; }\n", "Import `Option` from `lib.math`", - "import lib.math.{Option};\n", + "import {Option} from lib.math;\n", ), ( - "function value() -> word { return 1; }\nexport { value };\n", - "function main() -> word { return math.value(); }\n", + "function value() returns (word) { return 1; }\nexport { value };\n", + "function main() returns (word) { return math.value(); }\n", "Import module `math` from `lib.math`", "import lib.math;\n", ), @@ -1193,7 +1193,7 @@ mod tests { #[test] fn standard_library_missing_import_round_trips_over_wasm_dispatch() { let mut world = WorldState::new(); - let source = "function main() -> word { assert(true); return 1; }\n"; + let source = "function main() returns (word) { assert(true); return 1; }\n"; let opened = dispatch(&mut world, &did_open_message(source)); let notification = diagnostic_notification_for_uri(&opened, URI); let diagnostic = notification["params"]["diagnostics"] @@ -1232,7 +1232,7 @@ mod tests { assert_eq!(actions[0]["title"], "Import `assert` from `std`"); assert_eq!( actions[0]["edit"]["changes"][URI][0]["newText"], - "import std.{assert};\n" + "import {assert} from std;\n" ); } @@ -1240,7 +1240,7 @@ mod tests { fn closing_untitled_document_removes_it_from_workspace_symbols() { let mut world = WorldState::new(); let uri = "untitled:Untitled-1"; - let source = "function ghost() -> word { return 42; }\n"; + let source = "function ghost() returns (word) { return 42; }\n"; let _ = dispatch(&mut world, &did_open_uri_message(uri, source)); let _ = dispatch( @@ -1275,8 +1275,8 @@ mod tests { #[test] fn closing_workspace_document_removes_it_from_workspace_symbols() { let mut world = WorldState::new(); - let uri = "file:///main/ghost.solc"; - let source = "function ghost() -> word { return 42; }\n"; + let uri = "file:///main/ghost.sol"; + let source = "function ghost() returns (word) { return 42; }\n"; let _ = dispatch(&mut world, &did_open_uri_message(uri, source)); let _ = dispatch( @@ -1312,7 +1312,7 @@ mod tests { fn closing_file_detached_from_removed_workspace_discards_it() { let mut world = WorldState::new(); let root = "file:///main/"; - let uri = "file:///main/ghost.solc"; + let uri = "file:///main/ghost.sol"; let _ = dispatch( &mut world, &serde_json::json!({ @@ -1328,7 +1328,7 @@ mod tests { ); let _ = dispatch( &mut world, - &did_open_uri_message(uri, "function ghost() -> word { return 42; }\n"), + &did_open_uri_message(uri, "function ghost() returns (word) { return 42; }\n"), ); let _ = dispatch( &mut world, @@ -1367,7 +1367,7 @@ mod tests { #[test] fn document_highlight_request_returns_highlights() { let mut world = WorldState::new(); - let source = "function id(x: word) -> word {\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n return x;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); @@ -1405,7 +1405,7 @@ mod tests { #[test] fn rename_requests_return_workspace_edit_and_prepare_range() { let mut world = WorldState::new(); - let source = "function id(x: word) -> word {\n let y = x;\n return x;\n}\n"; + let source = "function id(x: word) returns (word) {\n let y = x;\n return x;\n}\n"; let outgoing = dispatch(&mut world, &did_open_message(source)); assert_eq!(outgoing.len(), 1); diff --git a/crates/lsp/src/workspace_symbols.rs b/crates/lsp/src/workspace_symbols.rs index 2636328e..943b3c44 100644 --- a/crates/lsp/src/workspace_symbols.rs +++ b/crates/lsp/src/workspace_symbols.rs @@ -208,7 +208,7 @@ fn instance_symbol<'db>( db, line_index, uri, - format!("instance {}", class.atom().text(db)), + format!("impl {}", class.atom().text(db)), SymbolKind::OBJECT, class.span(db), None, @@ -267,17 +267,17 @@ mod tests { fn world_with_main(source: &str) -> (WorldState, Url) { let mut world = WorldState::new(); - let uri = Url::parse("file:///main/main.solc").expect("uri"); + let uri = Url::parse("file:///main/main.sol").expect("uri"); assert!(world.open_document(uri.clone(), source.to_owned())); (world, uri) } #[test] fn query_returns_matching_functions_from_each_open_document() { - let main_source = "function target_main() -> word {\n return 1;\n}\n"; - let util_source = "function target_util() -> word {\n return 2;\n}\n"; + let main_source = "function target_main() returns (word) {\n return 1;\n}\n"; + let util_source = "function target_util() returns (word) {\n return 2;\n}\n"; let (mut world, main_uri) = world_with_main(main_source); - let util_uri = Url::parse("file:///main/util.solc").expect("uri"); + let util_uri = Url::parse("file:///main/util.sol").expect("uri"); assert!(world.open_document(util_uri.clone(), util_source.to_owned())); let symbols = handle_workspace_symbol(&world, "TARGET").expect("workspace symbols"); @@ -305,19 +305,19 @@ mod tests { let mut world = WorldState::new(); let root_path = std::env::temp_dir().join("solcore-lsp-symbol-project"); let root = Url::from_directory_path(&root_path).expect("root uri"); - let main_uri = Url::from_file_path(root_path.join("main.solc")).expect("main uri"); - let util_uri = Url::from_file_path(root_path.join("util.solc")).expect("util uri"); + let main_uri = Url::from_file_path(root_path.join("main.sol")).expect("main uri"); + let util_uri = Url::from_file_path(root_path.join("util.sol")).expect("util uri"); assert_eq!( world.load_workspace_documents( root, [ ( main_uri, - "function main_symbol() -> word { return 1; }\n".to_owned() + "function main_symbol() returns (word) { return 1; }\n".to_owned() ), ( util_uri.clone(), - "function unopened_symbol() -> word { return 2; }\n".to_owned() + "function unopened_symbol() returns (word) { return 2; }\n".to_owned() ), ] ), @@ -335,17 +335,7 @@ mod tests { #[test] fn empty_query_returns_top_level_symbols_and_non_matching_query_is_empty() { - let source = "\ -function alpha() -> word { - return 1; -} - -type Alias = word; - -data Choice = One | Two; - -contract Vault {} -"; + let source = "function alpha() returns (word) {\n return 1;\n}\n\ntype Alias = word;\n\nenum Choice {One , Two}\n\ncontract Vault {}\n"; let (world, uri) = world_with_main(source); let symbols = handle_workspace_symbol(&world, "").expect("workspace symbols"); @@ -372,14 +362,7 @@ contract Vault {} #[test] fn contract_member_symbols_keep_container_name() { - let source = "\ -contract Vault { - balance: word; - function read() -> word { - return balance; - } -} -"; + let source = "contract Vault {\n balance: word;\n function read() returns (word) {\n return balance;\n }\n}\n"; let (world, uri) = world_with_main(source); let field = handle_workspace_symbol(&world, "balance") diff --git a/crates/lsp/tests/stdio_smoke.rs b/crates/lsp/tests/stdio_smoke.rs index 0b820951..72e06b1b 100644 --- a/crates/lsp/tests/stdio_smoke.rs +++ b/crates/lsp/tests/stdio_smoke.rs @@ -13,21 +13,11 @@ use std::{ use lsp_types::Url; use serde_json::{Value, json}; -const MAIN_SOURCE: &str = "\ -import math.{double}; - -function f() -> word { - return double(true); -} -"; -const MATH_SOURCE: &str = "\ -function double(x: word) -> word { - return x; -} - -export { double }; -"; -const SECONDARY_SOURCE: &str = "function secondaryValue() -> word { return 2; }\n"; +const MAIN_SOURCE: &str = + "import {double} from math;\n\nfunction f() returns (word) {\n return double(true);\n}\n"; +const MATH_SOURCE: &str = + "function double(x: word) returns (word) {\n return x;\n}\n\nexport { double };\n"; +const SECONDARY_SOURCE: &str = "function secondaryValue() returns (word) { return 2; }\n"; struct TestWorkspace { root: PathBuf, @@ -50,8 +40,8 @@ impl TestWorkspace { std::process::id() )); fs::create_dir_all(&root).expect("create test workspace"); - let main = root.join("main.solc"); - let math = root.join("math.solc"); + let main = root.join("main.sol"); + let math = root.join("math.sol"); fs::write(&main, MAIN_SOURCE).expect("write main source"); fs::write(&math, MATH_SOURCE).expect("write math source"); let secondary_root = std::env::temp_dir().join(format!( @@ -59,7 +49,7 @@ impl TestWorkspace { std::process::id() )); fs::create_dir_all(&secondary_root).expect("create secondary workspace"); - let secondary = secondary_root.join("secondary.solc"); + let secondary = secondary_root.join("secondary.sol"); fs::write(&secondary, SECONDARY_SOURCE).expect("write secondary source"); Self { @@ -344,8 +334,8 @@ fn run_lsp_smoke( Some(&workspace.secondary_uri), )?; - fs::remove_file(workspace.root.join("math.solc")) - .map_err(|error| format!("failed to remove watched math.solc: {error}"))?; + fs::remove_file(workspace.root.join("math.sol")) + .map_err(|error| format!("failed to remove watched math.sol: {error}"))?; send_message( stdin, &json!({ From 8925d065a0ec6cfe72767dbcfc1c997130a73b53 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 042/110] Switch the compiler and fixtures to canonical syntax: nameres Co-authored-by: Codex --- crates/nameres/src/item_refs.rs | 14 +- crates/nameres/src/model.rs | 4 +- crates/nameres/src/util.rs | 8 +- crates/nameres/tests/incremental_cache.rs | 22 +- crates/nameres/tests/module_system.rs | 416 +++++++++++----------- 5 files changed, 243 insertions(+), 221 deletions(-) diff --git a/crates/nameres/src/item_refs.rs b/crates/nameres/src/item_refs.rs index 94526f5b..e3e0c169 100644 --- a/crates/nameres/src/item_refs.rs +++ b/crates/nameres/src/item_refs.rs @@ -412,12 +412,19 @@ pub(super) fn select_import_refs<'db>( .iter() .map(|hidden| spanned_name_text(db, &hidden.name)) .collect(); - let mut selected = match selector { - ImportSelector::Wildcard => available.to_vec(), + let selected = match selector { + ImportSelector::Wildcard => available + .iter() + .filter(|item_ref| !hidden.contains(&item_ref.public_name)) + .cloned() + .collect(), ImportSelector::Names(names) => names .iter() - .flat_map(|selected| { + .filter_map(|selected| { let source_name = spanned_name_text(db, &selected.name); + (!hidden.contains(&source_name)).then_some((selected, source_name)) + }) + .flat_map(|(selected, source_name)| { let local_name = selected .alias .as_ref() @@ -449,7 +456,6 @@ pub(super) fn select_import_refs<'db>( }) .collect(), }; - selected.retain(|item_ref| !hidden.contains(&item_ref.public_name)); let selected = unique_import_bindings(selected); tracing::trace!( target: "nameres::imports", diff --git a/crates/nameres/src/model.rs b/crates/nameres/src/model.rs index 85bafc98..9d1026ed 100644 --- a/crates/nameres/src/model.rs +++ b/crates/nameres/src/model.rs @@ -40,11 +40,11 @@ pub struct ModuleTree { /// expected to use the same normalized roots as [`ModuleTree`]. #[salsa::input(debug)] pub struct ModuleFsSnapshot { - /// Absolute `.solc` source files observed on disk. + /// Absolute `.sol` source files observed on disk. #[returns(ref)] pub existing_files: BTreeSet, - /// Sibling `.solc` file stems by parent directory. + /// Sibling `.sol` file stems by parent directory. #[returns(ref)] pub sibling_stems: BTreeMap>, } diff --git a/crates/nameres/src/util.rs b/crates/nameres/src/util.rs index 3dab1c8e..a856b82f 100644 --- a/crates/nameres/src/util.rs +++ b/crates/nameres/src/util.rs @@ -194,13 +194,13 @@ pub(super) fn main_workspace_prefix(logical_path: &[String]) -> &[String] { /// Converts a logical module path into the conventional source file path. /// /// Each logical segment becomes a path component and the file extension is -/// `.solc`. +/// `.sol`. pub fn module_file_path(logical_path: &[String]) -> PathBuf { let mut path = PathBuf::new(); for segment in logical_path { path.push(segment); } - path.set_extension("solc"); + path.set_extension("sol"); path } @@ -288,7 +288,7 @@ fn virtual_module_id_for_source_file<'db>( _ => return None, }; let last = logical_path.last_mut()?; - *last = last.strip_suffix(".solc")?.to_owned(); + *last = last.strip_suffix(".sol")?.to_owned(); if last.is_empty() { return None; } @@ -505,7 +505,7 @@ fn namespace_name(namespace: Namespace) -> &'static str { match namespace { Namespace::Term => "term", Namespace::Type => "type", - Namespace::Class => "class", + Namespace::Class => "trait", } } diff --git a/crates/nameres/tests/incremental_cache.rs b/crates/nameres/tests/incremental_cache.rs index 5f40a924..2fd6b891 100644 --- a/crates/nameres/tests/incremental_cache.rs +++ b/crates/nameres/tests/incremental_cache.rs @@ -107,8 +107,8 @@ impl solcore_nameres::Db for TestDb { #[test] fn module_diagnostics_backdates_after_same_module_body_literal_edit() { - let before = "function main() -> word {\n return 1;\n}\n"; - let after = "function main() -> word {\n return 2;\n}\n"; + let before = "function main() returns (word) {\n return 1;\n}\n"; + let after = "function main() returns (word) {\n return 2;\n}\n"; let (mut db, file, key) = db_with_main(before); { @@ -150,7 +150,7 @@ fn module_diagnostics_backdates_after_same_module_body_literal_edit() { #[test] fn body_diagnostics_key_excludes_module_env_diagnostics() { - let (db, file, key) = db_with_main("function main() -> word { return 1; }\n"); + let (db, file, key) = db_with_main("function main() returns (word) { return 1; }\n"); let module = module_id_from_key(&db, &key); let hir_module = parse_file_to_hir(&db, file).module(&db); let body = hir_module @@ -206,9 +206,9 @@ fn body_diagnostics_key_excludes_module_env_diagnostics() { #[test] fn duplicate_export_diagnostics_backdate_after_unrelated_body_length_edit() { - let before = "export a.{f};\nexport b.{f};\n\nfunction unrelated() -> word {\n return 1;\n}\n"; - let after = - "export a.{f};\nexport b.{f};\n\nfunction unrelated() -> word {\n return 123456789;\n}\n"; + let before = + "export a.{f};\nexport b.{f};\n\nfunction unrelated() returns (word) {\n return 1;\n}\n"; + let after = "export a.{f};\nexport b.{f};\n\nfunction unrelated() returns (word) {\n return 123456789;\n}\n"; let (mut db, file, key) = db_with_duplicate_export_main(before); let before_ids = { @@ -299,7 +299,7 @@ fn db_with_main(content: &str) -> (TestDb, SourceFile, ModuleKey) { db.module_fs_snapshot = Some(empty_module_fs_snapshot(&db)); let file = SourceFile::new( &db, - "memory:///main.solc".parse().expect("valid URL"), + "memory:///main.sol".parse().expect("valid URL"), Some(content.to_owned()), ); let key = ModuleKey { @@ -322,11 +322,11 @@ fn db_with_duplicate_export_main(content: &str) -> (TestDb, SourceFile, ModuleKe for (path, source) in [ ( vec!["a"], - "function f() -> word { return 0; }\nexport { f };\n", + "function f() returns (word) { return 0; }\nexport { f };\n", ), ( vec!["b"], - "function f() -> word { return 0; }\nexport { f };\n", + "function f() returns (word) { return 0; }\nexport { f };\n", ), ] { let key = ModuleKey { @@ -339,7 +339,7 @@ fn db_with_duplicate_export_main(content: &str) -> (TestDb, SourceFile, ModuleKe let file = SourceFile::new( &db, - "memory:///main.solc".parse().expect("valid URL"), + "memory:///main.sol".parse().expect("valid URL"), Some(content.to_owned()), ); let key = ModuleKey { @@ -355,7 +355,7 @@ fn empty_module_fs_snapshot(db: &TestDb) -> ModuleFsSnapshot { } fn source_file(db: &TestDb, key: &ModuleKey, content: &str) -> SourceFile { - let url = format!("memory:///{}.solc", key.logical_path.join("/")) + let url = format!("memory:///{}.sol", key.logical_path.join("/")) .parse() .expect("valid URL"); SourceFile::new(db, url, Some(content.to_owned())) diff --git a/crates/nameres/tests/module_system.rs b/crates/nameres/tests/module_system.rs index 727995c8..a59e3ddc 100644 --- a/crates/nameres/tests/module_system.rs +++ b/crates/nameres/tests/module_system.rs @@ -98,7 +98,7 @@ impl solcore_nameres::Db for TestDb { #[test] fn module_keys_reject_parent_directory_components() { let root = Path::new("workspace"); - let spelled_with_parent = Path::new("workspace/src/../src/main.solc"); + let spelled_with_parent = Path::new("workspace/src/../src/main.sol"); assert!( module_key_for_path(LibraryId::Main, root, spelled_with_parent).is_none(), @@ -130,17 +130,20 @@ fn auto_imports_index_unreachable_public_symbols_and_rank_direct_exports_first() let (db, entry) = load_sources([ ( vec!["main"], - "export { wanted }; function wanted() -> word { return 0; }", + "export { wanted }; function wanted() returns (word) { return 0; }", ), ( vec!["direct"], - "export { wanted, Thing, Eqish }; function wanted() -> word { return 1; } data Thing = Thing; class a:Eqish {}", + "export { wanted, Thing, Eqish }; function wanted() returns (word) { return 1; } enum Thing { Thing } trait Eqish {}", ), (vec!["wrapper"], "export direct.{wanted};"), - (vec!["private"], "function wanted() -> word { return 2; }"), + ( + vec!["private"], + "function wanted() returns (word) { return 2; }", + ), ( vec!["broken"], - "export { wanted }; lost(x: word) -> word { return 0; } function wanted() -> word { return 3; }", + "export { wanted }; lost(x) returns (word) { return 0; } function wanted() returns (word) { return 3; }", ), (vec!["broken_wrapper"], "export broken.{wanted};"), ( @@ -149,15 +152,15 @@ fn auto_imports_index_unreachable_public_symbols_and_rank_direct_exports_first() ), ( vec!["other"], - "export { wanted }; function wanted() -> word { return 4; }", + "export { wanted }; function wanted() returns (word) { return 4; }", ), ( vec!["term_collision"], - "export { Clash }; function Clash() -> word { return 5; }", + "export { Clash }; function Clash() returns (word) { return 5; }", ), ( vec!["type_collision"], - "export { Clash }; data Clash = Clash;", + "export { Clash }; enum Clash { Clash }", ), ( vec!["namespace_ambiguous"], @@ -246,15 +249,15 @@ fn constructor_auto_imports_require_the_requested_constructor_to_be_visible() { (vec!["main"], "function main() {}"), ( vec!["full"], - "export { Option(*) }; data Option = None | Some(word);", + "export { Option(*) }; enum Option { None, Some(word) }", ), ( vec!["opaque"], - "export { Option }; data Option = None | Some(word);", + "export { Option }; enum Option { None, Some(word) }", ), ( vec!["partial"], - "export { Option(Some) }; data Option = None | Some(word);", + "export { Option(Some) }; enum Option { None, Some(word) }", ), (vec!["wrapper"], "export full.{Option(Some)};"), ]); @@ -281,24 +284,24 @@ fn module_auto_imports_match_the_default_qualifier_and_public_member() { (vec!["main"], "function main() {}"), ( vec!["one", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ( vec!["two", "math"], - "export { value }; function value() -> word { return 2; }", + "export { value }; function value() returns (word) { return 2; }", ), (vec!["aaa", "math"], "export lib.one.math.{value};"), ( vec!["private", "math"], - "function value() -> word { return 3; }", + "function value() returns (word) { return 3; }", ), ( vec!["broken", "math"], - "export { value }; lost(x: word) -> word { return 0; } function value() -> word { return 4; }", + "export { value }; lost(x) returns (word) { return 0; } function value() returns (word) { return 4; }", ), ( vec!["other"], - "export { value }; function value() -> word { return 5; }", + "export { value }; function value() returns (word) { return 5; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -324,12 +327,12 @@ fn module_auto_imports_require_an_immediate_term_member() { (vec!["main"], "function main() {}"), ( vec!["types", "math"], - "export { Value }; data Value = Value(word);", + "export { Value }; enum Value { Value(word) }", ), (vec!["aliases", "math"], "export lib.target as nested;"), ( vec!["target"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -344,11 +347,11 @@ fn module_auto_imports_do_not_create_duplicate_default_qualifiers() { (vec!["main"], "import lib.existing.math; function main() {}"), ( vec!["existing", "math"], - "export { old }; function old() -> word { return 1; }", + "export { old }; function old() returns (word) { return 1; }", ), ( vec!["candidate", "math"], - "export { value }; function value() -> word { return 2; }", + "export { value }; function value() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -357,15 +360,15 @@ fn module_auto_imports_do_not_create_duplicate_default_qualifiers() { let (db, entry) = load_sources([ ( vec!["main"], - "import lib.existing as math; function main() {}", + "import * as math from lib.existing; function main() {}", ), ( vec!["existing"], - "export { old }; function old() -> word { return 1; }", + "export { old }; function old() returns (word) { return 1; }", ), ( vec!["candidate", "math"], - "export { value }; function value() -> word { return 2; }", + "export { value }; function value() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -375,11 +378,11 @@ fn module_auto_imports_do_not_create_duplicate_default_qualifiers() { (vec!["main"], "import lib.math.deep; function main() {}"), ( vec!["math", "deep"], - "export { old }; function old() -> word { return 1; }", + "export { old }; function old() returns (word) { return 1; }", ), ( vec!["other", "math"], - "export { value }; function value() -> word { return 2; }", + "export { value }; function value() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -391,25 +394,28 @@ fn module_auto_imports_do_not_conflict_with_unqualified_bindings() { let (db, entry) = load_sources([ ( vec!["main"], - "function math() -> word { return 0; } function main() {}", + "function math() returns (word) { return 0; } function main() {}", ), ( vec!["candidate", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); assert!(auto_import_module_candidates(&db, importing, "math", "value").is_empty()); let (db, entry) = load_sources([ - (vec!["main"], "import lib.names.{math}; function main() {}"), + ( + vec!["main"], + "import {math} from lib.names; function main() {}", + ), ( vec!["names"], - "export { math }; function math() -> word { return 0; }", + "export { math }; function math() returns (word) { return 0; }", ), ( vec!["candidate", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -419,16 +425,19 @@ fn module_auto_imports_do_not_conflict_with_unqualified_bindings() { #[test] fn module_qualifier_conflicts_with_selected_term_in_either_import_order() { for imports in [ - "import util; import other.{util};", - "import other.{util}; import util;", + "import util; import {util} from other;", + "import {util} from other; import util;", ] { let main = format!("{imports} function main() {{}}"); let (db, entry) = load_sources([ (vec!["main"], main.as_str()), - (vec!["util"], "function value() -> word { return 0; }"), + ( + vec!["util"], + "function value() returns (word) { return 0; }", + ), ( vec!["other"], - "export { util }; function util() -> word { return 1; }", + "export { util }; function util() returns (word) { return 1; }", ), ]); let module = module_id_from_key(&db, &entry); @@ -445,15 +454,15 @@ fn module_auto_imports_check_every_generated_prefix_binding() { let (db, entry) = load_sources([ ( vec!["main"], - "function one() -> word { return 0; } function main() {}", + "function one() returns (word) { return 0; } function main() {}", ), ( vec!["one", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ( vec!["two", "math"], - "export { value }; function value() -> word { return 2; }", + "export { value }; function value() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -464,24 +473,27 @@ fn module_auto_imports_check_every_generated_prefix_binding() { assert_eq!(paths, ["lib.two.math"]); let (db, entry) = load_sources([ - (vec!["main"], "data one = One; function main() {}"), + (vec!["main"], "enum one { One } function main() {}"), ( vec!["one", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); assert!(auto_import_module_candidates(&db, importing, "math", "value").is_empty()); let (db, entry) = load_sources([ - (vec!["main"], "import lib.names.{one}; function main() {}"), + ( + vec!["main"], + "import {one} from lib.names; function main() {}", + ), ( vec!["names"], - "export { one }; function one() -> word { return 0; }", + "export { one }; function one() returns (word) { return 0; }", ), ( vec!["one", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -493,24 +505,19 @@ fn module_auto_imports_check_contract_local_prefix_bindings() { let (db, entry) = load_sources([ ( vec!["main"], - "contract C { - one: word; - data two = Two; - function three() -> word { return 0; } - function main() {} - }", + "contract C {\n one: word;\n enum two {Two}\n function three() returns (word) { return 0; }\n function main() {}\n }", ), ( vec!["one", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ( vec!["two", "math"], - "export { value }; function value() -> word { return 2; }", + "export { value }; function value() returns (word) { return 2; }", ), ( vec!["three", "math"], - "export { value }; function value() -> word { return 3; }", + "export { value }; function value() returns (word) { return 3; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -523,11 +530,11 @@ fn module_auto_imports_check_resolved_and_unresolved_plain_import_prefixes() { (vec!["main"], "import lib.one.deep; function main() {}"), ( vec!["one", "deep"], - "export { old }; function old() -> word { return 0; }", + "export { old }; function old() returns (word) { return 0; }", ), ( vec!["one", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -537,7 +544,7 @@ fn module_auto_imports_check_resolved_and_unresolved_plain_import_prefixes() { (vec!["main"], "import lib.missing.deep; function main() {}"), ( vec!["missing", "math"], - "export { value }; function value() -> word { return 1; }", + "export { value }; function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -549,11 +556,11 @@ fn module_auto_imports_allow_a_separate_plain_import_after_a_selective_import() let (db, entry) = load_sources([ ( vec!["main"], - "import lib.one.math.{other}; function main() {}", + "import {other} from lib.one.math; function main() {}", ), ( vec!["one", "math"], - "export { other, value }; function other() -> word { return 0; } function value() -> word { return 1; }", + "export { other, value }; function other() returns (word) { return 0; } function value() returns (word) { return 1; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -568,11 +575,7 @@ fn auto_imports_exclude_namespace_blind_selector_collisions_within_one_provider( (vec!["main"], "function main() {}"), ( vec!["provider"], - "export { Shared, term_only, TypeOnly }; - function Shared() -> word { return 1; } - data Shared = Shared; - function term_only() -> word { return 2; } - data TypeOnly = TypeOnly;", + "export { Shared, term_only, TypeOnly };\n function Shared() returns (word) { return 1; }\n enum Shared {Shared}\n function term_only() returns (word) { return 2; }\n enum TypeOnly {TypeOnly}", ), ]); let importing = module_id_from_key(&db, &entry); @@ -595,14 +598,14 @@ fn auto_imports_exclude_namespace_blind_selector_collisions_within_one_provider( #[test] fn auto_imports_suppress_different_target_for_explicit_selector_but_keep_same_target() { let (db, entry) = load_sources([ - (vec!["main"], "import lib.a.{Foo}; function main() {}"), + (vec!["main"], "import {Foo} from lib.a; function main() {}"), ( vec!["a"], - "export { Foo }; function Foo() -> word { return 1; }", + "export { Foo }; function Foo() returns (word) { return 1; }", ), ( vec!["b"], - "export { Foo }; function Foo() -> word { return 2; }", + "export { Foo }; function Foo() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -620,15 +623,15 @@ fn auto_imports_consider_selector_aliases_by_their_local_name() { let (db, entry) = load_sources([ ( vec!["main"], - "import lib.a.{Original as Foo}; function main() {}", + "import {Original as Foo} from lib.a; function main() {}", ), ( vec!["a"], - "export { Original }; function Original() -> word { return 1; }", + "export { Original }; function Original() returns (word) { return 1; }", ), ( vec!["b"], - "export { Foo }; function Foo() -> word { return 2; }", + "export { Foo }; function Foo() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -639,14 +642,14 @@ fn auto_imports_consider_selector_aliases_by_their_local_name() { #[test] fn auto_imports_consider_bindings_from_wildcard_selectors() { let (db, entry) = load_sources([ - (vec!["main"], "import lib.a.{*}; function main() {}"), + (vec!["main"], "import * from lib.a; function main() {}"), ( vec!["a"], - "export { Foo }; function Foo() -> word { return 1; }", + "export { Foo }; function Foo() returns (word) { return 1; }", ), ( vec!["b"], - "export { Foo }; function Foo() -> word { return 2; }", + "export { Foo }; function Foo() returns (word) { return 2; }", ), ]); let importing = module_id_from_key(&db, &entry); @@ -659,12 +662,12 @@ fn auto_imports_consider_bindings_from_wildcard_selectors() { #[test] fn auto_imports_suppress_cross_namespace_collisions_from_different_targets() { let (db, entry) = load_sources([ - (vec!["main"], "import lib.a.{Foo}; function main() {}"), + (vec!["main"], "import {Foo} from lib.a; function main() {}"), ( vec!["a"], - "export { Foo }; function Foo() -> word { return 1; }", + "export { Foo }; function Foo() returns (word) { return 1; }", ), - (vec!["b"], "export { Foo }; data Foo = Foo;"), + (vec!["b"], "export { Foo }; enum Foo { Foo }"), ]); let importing = module_id_from_key(&db, &entry); @@ -683,11 +686,11 @@ fn auto_imports_keep_main_workspace_namespaces_isolated() { ), ( vec!["__solcore_workspace__", workspace_a, "nested", "util"], - "export { wanted }; function wanted() -> word { return 1; }", + "export { wanted }; function wanted() returns (word) { return 1; }", ), ( vec!["__solcore_workspace__", workspace_b, "nested", "util"], - "export { wanted }; function wanted() -> word { return 2; }", + "export { wanted }; function wanted() returns (word) { return 2; }", ), ( vec!["__solcore_detached__", detached, "main"], @@ -695,7 +698,7 @@ fn auto_imports_keep_main_workspace_namespaces_isolated() { ), ( vec!["__solcore_detached__", detached, "nested", "util"], - "export { wanted }; function wanted() -> word { return 3; }", + "export { wanted }; function wanted() returns (word) { return 3; }", ), ]); let importing = module_id_from_key( @@ -788,8 +791,8 @@ fn source_import_paths_use_canonical_library_syntax() { let sources = [ "function main() {}", "function local_only() {}", - "export { std_value }; function std_value() -> word { return 1; }", - "export { external_value }; function external_value() -> word { return 2; }", + "export { std_value }; function std_value() returns (word) { return 1; }", + "export { external_value }; function external_value() returns (word) { return 2; }", ]; for (key, source) in keys.iter().zip(sources) { let file = SourceFile::new(&db, fixture_url(key), Some(source.to_owned())); @@ -823,7 +826,7 @@ fn source_import_paths_use_canonical_library_syntax() { { let file = SourceFile::new( &db, - format!("memory:///roundtrip-{index}.solc") + format!("memory:///roundtrip-{index}.sol") .parse() .expect("round-trip test URL"), Some(format!("import {path};")), @@ -928,18 +931,15 @@ fn glob_hiding_uses_the_renamed_reexport_name() { let (db, entry) = load_sources([ ( vec!["main"], - "import lib.wrapper.{*} hiding {renamed};\n\ - function renamed() -> word { return 1; }", + "import * from lib.wrapper hiding {renamed};\nfunction renamed() returns (word) { return 1; }", ), ( vec!["base"], - "export { original };\n\ - function original() -> word { return 0; }", + "export { original };\nfunction original() returns (word) { return 0; }", ), ( vec!["wrapper"], - "import lib.base.{original as renamed};\n\ - export { renamed };", + "import {original as renamed} from lib.base;\nexport { renamed };", ), ]); @@ -990,11 +990,29 @@ fn wildcard_hiding_validates_against_source_interface() { assert_no_diagnostics(&db, &diagnostics); } +#[test] +fn selective_alias_hiding_uses_the_source_name() { + let (db, entry) = load_sources([ + ( + vec!["main"], + "import {original as renamed} from lib hiding {original};\n\ + function renamed() returns (word) { return 1; }\n\ + function main() returns (word) { return renamed(); }", + ), + ( + vec!["lib"], + "export {original}; function original() returns (word) { return 0; }", + ), + ]); + + let (_, diagnostics) = run(&db, &entry); + assert_no_diagnostics(&db, &diagnostics); +} + #[test] fn parse_broken_selected_import_does_not_blame_importer() { let (db, entry) = load_sources(parse_broken_provider_sources( - "import util.{lost}; - function main() -> word { return lost(0); }", + "import {lost} from util;\n function main() returns (word) { return lost(0); }", )); let main = module_id_from_key(&db, &entry); assert_eq!(module_diagnostic_codes(&db, main), Vec::::new()); @@ -1011,8 +1029,7 @@ fn parse_broken_selected_import_does_not_blame_importer() { #[test] fn parse_broken_qualified_import_does_not_blame_importer() { let (db, entry) = load_sources(parse_broken_provider_sources( - "import util; - function main() -> word { return util.lost(0); }", + "import util;\n function main() returns (word) { return util.lost(0); }", )); let main = module_id_from_key(&db, &entry); assert_eq!(module_diagnostic_codes(&db, main), Vec::::new()); @@ -1023,13 +1040,16 @@ fn parse_broken_leaf_does_not_mark_unrelated_module_prefixes_incomplete() { let (db, entry) = load_sources([ ( vec!["main"], - "import lib.a.b.c; import lib.a.x; function main() -> word { return a.missing(); }", + "import lib.a.b.c; import lib.a.x; function main() returns (word) { return a.missing(); }", ), ( vec!["a", "b", "c"], - "function value() -> word { let broken = ; return 1; }", + "function value() returns (word) { let broken = ; return 1; }", + ), + ( + vec!["a", "x"], + "function other() returns (word) { return 2; }", ), - (vec!["a", "x"], "function other() -> word { return 2; }"), ]); let main = module_id_from_key(&db, &entry); let leaf = module_id_from_key(&db, &module_key(["a", "b", "c"])); @@ -1061,10 +1081,7 @@ fn parse_broken_leaf_does_not_mark_unrelated_module_prefixes_incomplete() { fn parse_broken_module_diagnostics_publish_only_parse_errors() { let (db, entry) = load_sources([( vec!["main"], - "function main() -> word { - let x = ; - return missing; - }", + "function main() returns (word) {\n let x = ;\n return missing;\n }", )]); let main = module_id_from_key(&db, &entry); let diagnostics = lowered_module_diagnostics(&db, main); @@ -1186,7 +1203,7 @@ fn load_fixture(root: &Path, external_roots: BTreeMap) -> (Test ); } - let entry_path = root.join("main.solc"); + let entry_path = root.join("main.sol"); let entry_key = module_key_for_path(LibraryId::Main, root, &entry_path).expect("entry key"); (db, entry_key) } @@ -1227,8 +1244,7 @@ fn parse_broken_provider_sources(main: &str) -> [(Vec<&str>, &str); 2] { (vec!["main"], main), ( vec!["util"], - "lost(x: word) -> word { return 0; } - function other() {}", + "lost(x) returns (word) { return 0; }\n function other() {}", ), ] } @@ -1352,7 +1368,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -1374,7 +1390,7 @@ fn load_library_files(db: &mut TestDb, library: LibraryId, root: &Path, dir: &Pa let path = entry.expect("fixture entry").path(); if path.is_dir() { load_library_files(db, library.clone(), root, &path); - } else if path.extension().and_then(|ext| ext.to_str()) == Some("solc") { + } else if path.extension().and_then(|ext| ext.to_str()) == Some("sol") { let key = module_key_for_path(library.clone(), root, &path).expect("module key"); let source = fs::read_to_string(&path).expect("fixture source"); let url = fixture_url(&key); @@ -1391,7 +1407,7 @@ fn fixture_url(key: &ModuleKey) -> Url { LibraryId::External(name) => format!("external/{name}"), }; let path = key.logical_path.join("/"); - format!("memory:///{library}/{path}.solc") + format!("memory:///{library}/{path}.sol") .parse() .expect("fixture memory URL") } @@ -1476,398 +1492,398 @@ fn known_divergence(path: &str) -> Option { const KNOWN_DIVERGENCES: &[KnownDivergence] = &[ KnownDivergence { - path: "hidden_ctor_nonexhaustive_fail.solc", + path: "hidden_ctor_nonexhaustive_fail.sol", reason: "reference fails later exhaustiveness checking for partial constructor visibility; Rust nameres records partial-data metadata but does not run exhaustiveness", }, KnownDivergence { - path: "symlink_identity_fail.solc", + path: "symlink_identity_fail.sol", reason: "reference rejects distinct module identities for equivalent helper sources; Rust nameres does not canonicalize/symlink-check type identity in this pass", }, KnownDivergence { - path: "private_bad_main.solc", + path: "private_bad_main.sol", reason: "reference type-checks private helper bodies and rejects the unexported broken function; Rust nameres intentionally reports only name-resolution diagnostics", }, KnownDivergence { - path: "pragma_scope_main.solc", + path: "pragma_scope_main.sol", reason: "reference fails pragma-scoped typeclass/termination validation; Rust nameres does not implement that semantic check", }, ]; const IMPORT_CORPUS_CASES: &[ImportCorpusCase] = &[ ImportCorpusCase { - path: "booldef.solc", + path: "booldef.sol", expected_failure: false, }, ImportCorpusCase { - path: "boolmain.solc", + path: "boolmain.sol", expected_failure: false, }, ImportCorpusCase { - path: "unordered_imports_main.solc", + path: "unordered_imports_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "boolalias.solc", + path: "boolalias.sol", expected_failure: false, }, ImportCorpusCase { - path: "alias_hides_original_fail.solc", + path: "alias_hides_original_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "boolalias_open_fail.solc", + path: "boolalias_open_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "boolqualified.solc", + path: "boolqualified.sol", expected_failure: false, }, ImportCorpusCase { - path: "boolqualifiedtype.solc", + path: "boolqualifiedtype.sol", expected_failure: false, }, ImportCorpusCase { - path: "boolaliastype.solc", + path: "boolaliastype.sol", expected_failure: false, }, ImportCorpusCase { - path: "module_unqualified_fun_fail.solc", + path: "module_unqualified_fun_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "alias_unqualified_fun_fail.solc", + path: "alias_unqualified_fun_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "module_unqualified_type_fail.solc", + path: "module_unqualified_type_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "alias_unqualified_type_fail.solc", + path: "alias_unqualified_type_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "module_unqualified_constr_fail.solc", + path: "module_unqualified_constr_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "alias_unqualified_constr_fail.solc", + path: "alias_unqualified_constr_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "selective_unqualified_fun_ok.solc", + path: "selective_unqualified_fun_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "transitive_dep_main_module.solc", + path: "transitive_dep_main_module.sol", expected_failure: false, }, ImportCorpusCase { - path: "transitive_dep_main_select.solc", + path: "transitive_dep_main_select.sol", expected_failure: false, }, ImportCorpusCase { - path: "opaque_alias_main.solc", + path: "opaque_alias_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "opaque_select_alias_main.solc", + path: "opaque_select_alias_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "opaque_alias_leak_fail.solc", + path: "opaque_alias_leak_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "opaque_alias_qualifier_leak_fail.solc", + path: "opaque_alias_qualifier_leak_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "opaque_select_direct_leak_fail.solc", + path: "opaque_select_direct_leak_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "module_name_shadow.solc", + path: "module_name_shadow.sol", expected_failure: true, }, ImportCorpusCase { - path: "wrapper_shadow_success.solc", + path: "wrapper_shadow_success.sol", expected_failure: false, }, ImportCorpusCase { - path: "ns_cross_ok.solc", + path: "ns_cross_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "ns_constr_dup.solc", + path: "ns_constr_dup.sol", expected_failure: false, }, ImportCorpusCase { - path: "strict_open_fail.solc", + path: "strict_open_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "boolselect.solc", + path: "boolselect.sol", expected_failure: false, }, ImportCorpusCase { - path: "boolconselect_ok.solc", + path: "boolconselect_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "boolconselect_fail.solc", + path: "boolconselect_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "nested_alias.solc", + path: "nested_alias.sol", expected_failure: false, }, ImportCorpusCase { - path: "nested_select.solc", + path: "nested_select.sol", expected_failure: false, }, ImportCorpusCase { - path: "nested_foo_and_bar.solc", + path: "nested_foo_and_bar.sol", expected_failure: false, }, ImportCorpusCase { - path: "nested_direct_qualifier.solc", + path: "nested_direct_qualifier.sol", expected_failure: false, }, ImportCorpusCase { - path: "nested_deep_qualifier.solc", + path: "nested_deep_qualifier.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_import_ok.solc", + path: "glob_import_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_import_mixed.solc", + path: "glob_import_mixed.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_import_hiding.solc", + path: "glob_import_hiding.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_hiding_amb_ok.solc", + path: "glob_hiding_amb_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_import_dup.solc", + path: "glob_import_dup.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_export_mixed.solc", + path: "glob_export_mixed.sol", expected_failure: false, }, ImportCorpusCase { - path: "glob_amb_main_fail.solc", + path: "glob_amb_main_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "glob_import_hiding_unknown_fail.solc", + path: "glob_import_hiding_unknown_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "select_hiding_ok.solc", + path: "select_hiding_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "select_hiding_fail.solc", + path: "select_hiding_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "export_item_dup_fail.solc", + path: "export_item_dup_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "export_module_dup_fail.solc", + path: "export_module_dup_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "select_ok.solc", + path: "select_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "select_shadow_local.solc", + path: "select_shadow_local.sol", expected_failure: true, }, ImportCorpusCase { - path: "select_shadow_param_ok.solc", + path: "select_shadow_param_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "select_fail.solc", + path: "select_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "select_unknown.solc", + path: "select_unknown.sol", expected_failure: true, }, ImportCorpusCase { - path: "select_dup_item.solc", + path: "select_dup_item.sol", expected_failure: true, }, ImportCorpusCase { - path: "alias_dup.solc", + path: "alias_dup.sol", expected_failure: true, }, ImportCorpusCase { - path: "amb_main.solc", + path: "amb_main.sol", expected_failure: true, }, ImportCorpusCase { - path: "amb_ok.solc", + path: "amb_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "dupqual_main.solc", + path: "dupqual_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "dupqual_module_main.solc", + path: "dupqual_module_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "private_helper_main.solc", + path: "private_helper_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "module_qualified_constructor.solc", + path: "module_qualified_constructor.sol", expected_failure: false, }, ImportCorpusCase { - path: "module_qualified_constructor_pattern.solc", + path: "module_qualified_constructor_pattern.sol", expected_failure: false, }, ImportCorpusCase { - path: "module_qualified_constructor_alias.solc", + path: "module_qualified_constructor_alias.sol", expected_failure: false, }, ImportCorpusCase { - path: "type_collision_main.solc", + path: "type_collision_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "dot_context_expr.solc", + path: "dot_context_expr.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_items_main.solc", + path: "reexport_items_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_select_main.solc", + path: "reexport_select_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_select_alias_main.solc", + path: "reexport_select_alias_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_module_main.solc", + path: "reexport_module_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_module_alias_main.solc", + path: "reexport_module_alias_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_ctor_pattern.solc", + path: "reexport_ctor_pattern.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_ctor_expr_ok.solc", + path: "reexport_ctor_expr_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "reexport_ctor_expr_hidden_fail.solc", + path: "reexport_ctor_expr_hidden_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "reexport_ctor_hidden_fail.solc", + path: "reexport_ctor_hidden_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "hidden_ctor_expr_fail.solc", + path: "hidden_ctor_expr_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "hidden_ctor_dot_fail.solc", + path: "hidden_ctor_dot_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "hidden_ctor_pattern_fail.solc", + path: "hidden_ctor_pattern_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "hidden_ctor_nonexhaustive_fail.solc", + path: "hidden_ctor_nonexhaustive_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "hidden_ctor_wildcard_ok.solc", + path: "hidden_ctor_wildcard_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "rootcheck/nested/main.solc", + path: "rootcheck/nested/main.sol", expected_failure: false, }, ImportCorpusCase { - path: "rootcheck/nested/relative_and_lib_main.solc", + path: "rootcheck/nested/relative_and_lib_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "external_lib_main.solc", + path: "external_lib_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "external_lib_alias_main.solc", + path: "external_lib_alias_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "import_std_minimal.solc", + path: "import_std_minimal.sol", expected_failure: false, }, ImportCorpusCase { - path: "select_alias_item_ok.solc", + path: "select_alias_item_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "select_alias_multi_ok.solc", + path: "select_alias_multi_ok.sol", expected_failure: false, }, ImportCorpusCase { - path: "external_lib_missing_fail.solc", + path: "external_lib_missing_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "symlink_identity_fail.solc", + path: "symlink_identity_fail.sol", expected_failure: true, }, ImportCorpusCase { - path: "private_bad_main.solc", + path: "private_bad_main.sol", expected_failure: true, }, ImportCorpusCase { - path: "pragma_scope_main.solc", + path: "pragma_scope_main.sol", expected_failure: true, }, ImportCorpusCase { - path: "selfcycle.solc", + path: "selfcycle.sol", expected_failure: false, }, ImportCorpusCase { - path: "cycle_main.solc", + path: "cycle_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "wild_main.solc", + path: "wild_main.sol", expected_failure: false, }, ImportCorpusCase { - path: "leak_main.solc", + path: "leak_main.sol", expected_failure: true, }, ]; From 4faaf94088b189d59a97059e523beb8db266ed16 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 043/110] Switch the compiler and fixtures to canonical syntax: nameres fixtures Co-authored-by: Codex --- crates/nameres/tests/fixtures/ok/alias/main.sol | 2 +- crates/nameres/tests/fixtures/ok/cycle/main.sol | 2 +- crates/nameres/tests/fixtures/ok/external/main.sol | 2 +- crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol | 4 ++-- .../nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol | 2 +- crates/nameres/tests/fixtures/ok/plain/main.sol | 2 +- crates/nameres/tests/fixtures/ok/reexport_chain/main.sol | 2 +- crates/nameres/tests/fixtures/ok/selective_hiding/main.sol | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/nameres/tests/fixtures/ok/alias/main.sol b/crates/nameres/tests/fixtures/ok/alias/main.sol index 985ec04a..a2a878d8 100644 --- a/crates/nameres/tests/fixtures/ok/alias/main.sol +++ b/crates/nameres/tests/fixtures/ok/alias/main.sol @@ -1,3 +1,3 @@ -import util as U; +import * as U from util; export util as PublicUtil; diff --git a/crates/nameres/tests/fixtures/ok/cycle/main.sol b/crates/nameres/tests/fixtures/ok/cycle/main.sol index 9b89b000..f88cb703 100644 --- a/crates/nameres/tests/fixtures/ok/cycle/main.sol +++ b/crates/nameres/tests/fixtures/ok/cycle/main.sol @@ -1,3 +1,3 @@ -import a.{fb}; +import {fb} from a; function main() {} diff --git a/crates/nameres/tests/fixtures/ok/external/main.sol b/crates/nameres/tests/fixtures/ok/external/main.sol index a84946ad..24eb4225 100644 --- a/crates/nameres/tests/fixtures/ok/external/main.sol +++ b/crates/nameres/tests/fixtures/ok/external/main.sol @@ -1,3 +1,3 @@ -import @pkg.extmod.{ext}; +import {ext} from @pkg.extmod; function main() {} diff --git a/crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol b/crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol index f1af761a..53699d87 100644 --- a/crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol +++ b/crates/nameres/tests/fixtures/ok/local_std_subpath/main.sol @@ -1,5 +1,5 @@ -import std.a.b.{value}; +import {value} from std.a.b; -function main(x: word) -> word { +function main(x: word) returns (word) { return value(x); } diff --git a/crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol b/crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol index 0d203179..36dd500c 100644 --- a/crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol +++ b/crates/nameres/tests/fixtures/ok/local_std_subpath/std/a/b.sol @@ -1,4 +1,4 @@ -function value(x: word) -> word { +function value(x: word) returns (word) { return x; } diff --git a/crates/nameres/tests/fixtures/ok/plain/main.sol b/crates/nameres/tests/fixtures/ok/plain/main.sol index 47d7583c..d8afb553 100644 --- a/crates/nameres/tests/fixtures/ok/plain/main.sol +++ b/crates/nameres/tests/fixtures/ok/plain/main.sol @@ -1,3 +1,3 @@ -import util.{value}; +import {value} from util; function main() {} diff --git a/crates/nameres/tests/fixtures/ok/reexport_chain/main.sol b/crates/nameres/tests/fixtures/ok/reexport_chain/main.sol index 882df435..253d0f2f 100644 --- a/crates/nameres/tests/fixtures/ok/reexport_chain/main.sol +++ b/crates/nameres/tests/fixtures/ok/reexport_chain/main.sol @@ -1,3 +1,3 @@ -import b.{value}; +import {value} from b; function main() {} diff --git a/crates/nameres/tests/fixtures/ok/selective_hiding/main.sol b/crates/nameres/tests/fixtures/ok/selective_hiding/main.sol index 282f035e..a7c9bc0c 100644 --- a/crates/nameres/tests/fixtures/ok/selective_hiding/main.sol +++ b/crates/nameres/tests/fixtures/ok/selective_hiding/main.sol @@ -1,3 +1,3 @@ -import util.{*} hiding {hidden}; +import * from util hiding {hidden}; function main() {} From eb777e5d5035f02e2defd3029d64169b06707f3c Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 044/110] Switch the compiler and fixtures to canonical syntax: parser Co-authored-by: Codex --- crates/parser/src/lexer.rs | 36 +- crates/parser/src/lower/body.rs | 51 +-- crates/parser/src/lower/items.rs | 17 +- crates/parser/src/parse/common.rs | 68 ++-- crates/parser/src/parse/expr_pat.rs | 130 +++----- crates/parser/src/parse/imports.rs | 55 ++-- crates/parser/src/parse/items.rs | 490 +++++++++++++++------------- crates/parser/src/parse/mod.rs | 44 ++- 8 files changed, 478 insertions(+), 413 deletions(-) diff --git a/crates/parser/src/lexer.rs b/crates/parser/src/lexer.rs index 891653e8..c77841f8 100644 --- a/crates/parser/src/lexer.rs +++ b/crates/parser/src/lexer.rs @@ -421,11 +421,12 @@ mod tests { assert_eq!(tokenize("export"), vec![Token::Export]); assert_eq!(tokenize("as"), vec![Token::As]); assert_eq!(tokenize("let"), vec![Token::Let]); - assert_eq!(tokenize("data"), vec![Token::Data]); assert_eq!(tokenize("derive"), vec![Token::Ident("derive")]); - assert_eq!(tokenize("class"), vec![Token::Class]); - assert_eq!(tokenize("forall"), vec![Token::Forall]); - assert_eq!(tokenize("instance"), vec![Token::Instance]); + for keyword in [ + "enum", "trait", "impl", "from", "returns", "where", "mapping", "while", + ] { + assert_eq!(tokenize(keyword), vec![Token::Ident(keyword)]); + } assert_eq!(tokenize("if"), vec![Token::If]); assert_eq!(tokenize("else"), vec![Token::Else]); assert_eq!(tokenize("for"), vec![Token::For]); @@ -453,6 +454,8 @@ mod tests { #[test] fn test_multi_char_operators() { + // `:=` remains a token for inline Yul, even though Core declarations + // and assignments reject it. assert_eq!(tokenize(":="), vec![Token::ColonEq]); assert_eq!(tokenize("->"), vec![Token::Arrow]); assert_eq!(tokenize("=>"), vec![Token::FatArrow]); @@ -715,17 +718,23 @@ mod tests { ); assert_eq!( - tokenize("function foo(a, b) -> c"), + tokenize("function foo(a: word, b: word) returns (word)"), vec![ Token::Function, Token::Ident("foo"), Token::LParen, Token::Ident("a"), + Token::Colon, + Token::Ident("word"), Token::Comma, Token::Ident("b"), + Token::Colon, + Token::Ident("word"), + Token::RParen, + Token::Ident("returns"), + Token::LParen, + Token::Ident("word"), Token::RParen, - Token::Arrow, - Token::Ident("c"), ] ); } @@ -734,9 +743,9 @@ mod tests { fn test_contract_snippet() { let input = r#" contract Foo { - function bar() -> u256 { - let x := 0x1234; - return x + function bar() returns (u256) { + let x = 0x1234; + return x; } } "#; @@ -752,16 +761,19 @@ mod tests { Token::Ident("bar"), Token::LParen, Token::RParen, - Token::Arrow, + Token::Ident("returns"), + Token::LParen, Token::Ident("u256"), + Token::RParen, Token::LBrace, Token::Let, Token::Ident("x"), - Token::ColonEq, + Token::Eq, Token::HexLit("0x1234"), Token::Semi, Token::Return, Token::Ident("x"), + Token::Semi, Token::RBrace, Token::RBrace, ] diff --git a/crates/parser/src/lower/body.rs b/crates/parser/src/lower/body.rs index 781b2e7f..077feb89 100644 --- a/crates/parser/src/lower/body.rs +++ b/crates/parser/src/lower/body.rs @@ -20,17 +20,38 @@ use crate::{parse::parse_body_statements, types::*}; const MAX_EXPRESSION_NESTING: usize = 32; fn apply_implicit_return(stmts: &mut Vec>) { - let [stmt] = stmts.as_mut_slice() else { + let Some(stmt) = stmts.last_mut() else { return; }; let kind = std::mem::replace(&mut stmt.kind, ParsedStmtKind::Error); stmt.kind = match kind { - ParsedStmtKind::Expr(expr) => ParsedStmtKind::Return(Some(expr)), + ParsedStmtKind::Expr { + expr, + trailing_semi: false, + } => ParsedStmtKind::Return(Some(expr)), other => other, }; } +fn reject_unterminated_tail_expr(parsed: &mut ParseOutput>) { + let Some(ParsedStmt { + span, + kind: ParsedStmtKind::Expr { + trailing_semi: false, + .. + }, + }) = parsed.output.last() + else { + return; + }; + + parsed.errors.push(ParsedError::new( + *span, + "expression statement requires trailing `;`", + )); +} + fn lower_parsed_lit(lit: ParsedLitKind<'_>) -> function::LitKind { match lit { ParsedLitKind::Number(n) => function::LitKind::Number(n.to_owned()), @@ -150,9 +171,6 @@ impl<'db, 'a> LoweringCtx<'db, 'a> { ParsedExprKind::Field { base, field } => { self.lower_field_expr(anchor, base_start, *base, field, arenas) } - ParsedExprKind::TypeAnnot { expr, ty } => { - self.lower_type_annot_expr(anchor, base_start, *expr, ty, arenas) - } ParsedExprKind::UnaryOp { op, expr } => { self.lower_unary_expr(anchor, base_start, op, *expr, arenas) } @@ -242,19 +260,6 @@ impl<'db, 'a> LoweringCtx<'db, 'a> { function::ExprKind::Field { base, field } } - fn lower_type_annot_expr( - &mut self, - anchor: AnchorId<'db>, - base_start: usize, - expr: ParsedExpr<'_>, - ty: ParsedTy<'_>, - arenas: &mut BodyArenas<'db>, - ) -> function::ExprKind<'db> { - let expr = self.lower_expr(anchor, base_start, expr, arenas); - let ty = lower_type_ref(self.db, anchor, base_start, ty); - function::ExprKind::TypeAnnot { expr, ty } - } - fn lower_unary_expr( &mut self, anchor: AnchorId<'db>, @@ -327,7 +332,8 @@ impl<'db, 'a> LoweringCtx<'db, 'a> { ); let body_anchor = AnchorId::def(self.db, body_def); - let parsed_body = parse_body_statements(self.source, body_span); + let mut parsed_body = parse_body_statements(self.source, body_span); + reject_unterminated_tail_expr(&mut parsed_body); self.parse_errors.extend(parsed_body.errors); let mut lambda_arenas = BodyArenas::new(); @@ -414,7 +420,7 @@ impl<'db, 'a> LoweringCtx<'db, 'a> { ParsedStmtKind::Return(expr) => function::StmtKind::Return( expr.map(|expr| self.lower_expr(anchor, base_start, expr, arenas)), ), - ParsedStmtKind::Expr(expr) => { + ParsedStmtKind::Expr { expr, .. } => { function::StmtKind::Expr(self.lower_expr(anchor, base_start, expr, arenas)) } ParsedStmtKind::Assign { op, lhs, rhs } => function::StmtKind::Assign { @@ -527,6 +533,9 @@ impl<'db, 'a> LoweringCtx<'db, 'a> { implicit_return: bool, ) -> Vec>> { let mut parsed = parse_body_statements(self.source, body_span); + if !implicit_return { + reject_unterminated_tail_expr(&mut parsed); + } self.parse_errors.extend(parsed.errors); if implicit_return { @@ -563,7 +572,7 @@ fn drop_parsed_expr_iteratively(root: ParsedExpr<'_>) { pending.extend(args); } ParsedExprKind::Field { base, .. } => pending.push(*base), - ParsedExprKind::TypeAnnot { expr, .. } | ParsedExprKind::UnaryOp { expr, .. } => { + ParsedExprKind::UnaryOp { expr, .. } => { pending.push(*expr); } ParsedExprKind::If { diff --git a/crates/parser/src/lower/items.rs b/crates/parser/src/lower/items.rs index 5f882081..48df0764 100644 --- a/crates/parser/src/lower/items.rs +++ b/crates/parser/src/lower/items.rs @@ -272,21 +272,6 @@ pub(super) fn lower_type_ref<'db>( params_span, ret, } => { - // A comma-separated outer domain denotes source parameters, while - // another grouping keeps a tuple-valued unary domain: - // `(a, b) -> c` versus `((a, b)) -> c`. - // Keep the raw parser's unary domain node so the grouping remains - // observable until this lowering boundary. - let params = match params.len() { - 1 => match params.into_iter().next().expect("single arrow domain") { - ParsedTy { - kind: ParsedTyKind::Tuple { elems }, - .. - } if elems.len() != 1 => elems, - param => vec![param], - }, - _ => params, - }; let params = params .into_iter() .map(|param| lower_type_ref(db, anchor, base_start, param)) @@ -643,7 +628,7 @@ pub(super) fn lower_function<'db>( let body_anchor = AnchorId::def(ctx.db, body_def); let mut arenas = BodyArenas::new(); - let implicit_return = matches!(kind, item::FuncKind::Function | item::FuncKind::Fallback); + let implicit_return = matches!(kind, item::FuncKind::Function); let top_level_stmts = ctx.with_owner(body_def, |ctx| { ctx.lower_body_statements(body_anchor, body_span, &mut arenas, implicit_return) }); diff --git a/crates/parser/src/parse/common.rs b/crates/parser/src/parse/common.rs index 27839fdf..9fa77e3a 100644 --- a/crates/parser/src/parse/common.rs +++ b/crates/parser/src/parse/common.rs @@ -6,13 +6,7 @@ pub(super) fn ident_parser<'src, I>() -> impl Parser<'src, I, SpannedStr<'src>, where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - select! { - Token::Ident(name) => name, - Token::True => "true", - Token::False => "false", - Token::Fallback => "fallback", - } - .validate(|name, e, emitter| { + select! { Token::Ident(name) => name }.validate(|name, e, emitter| { if name.contains('-') { emitter.emit(Rich::custom( e.span(), @@ -23,6 +17,24 @@ where }) } +/// Parses one of the built-in Boolean values while retaining the identifier- +/// shaped node expected by the current name-resolution and type-inference +/// representation. +/// +/// Keeping this separate from [`ident_parser`] prevents `true` and `false` +/// from being accepted in declaration, import, or type-name positions. +pub(super) fn boolean_value_parser<'src, I>() +-> impl Parser<'src, I, SpannedStr<'src>, ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + select! { + Token::True => "true", + Token::False => "false", + } + .map_with(|name, e| (name, e.span())) +} + pub(super) fn pragma_ident_parser<'src, I>() -> impl Parser<'src, I, SpannedStr<'src>, ParserErr<'src>> where @@ -65,18 +77,31 @@ where select! { Token::Ident(name) if name == "comptime" => () }.map_with(|_, e| e.span()) } -pub(super) fn hiding_kw_parser<'src, I>() -> impl Parser<'src, I, (), ParserErr<'src>> -where - I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, -{ - select! { Token::Ident(name) if name == "hiding" => () } +macro_rules! contextual_keyword_parser { + ($name:ident, $keyword:literal) => { + pub(super) fn $name<'src, I>() -> impl Parser<'src, I, LexSpan, ParserErr<'src>> + where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, + { + select! { Token::Ident(name) if name == $keyword => () }.map_with(|_, e| e.span()) + } + }; } -pub(super) fn then_kw_parser<'src, I>() -> impl Parser<'src, I, (), ParserErr<'src>> +contextual_keyword_parser!(from_kw_parser, "from"); +contextual_keyword_parser!(returns_kw_parser, "returns"); +contextual_keyword_parser!(where_kw_parser, "where"); +contextual_keyword_parser!(enum_kw_parser, "enum"); +contextual_keyword_parser!(trait_kw_parser, "trait"); +contextual_keyword_parser!(impl_kw_parser, "impl"); +contextual_keyword_parser!(mapping_kw_parser, "mapping"); +contextual_keyword_parser!(while_kw_parser, "while"); + +pub(super) fn hiding_kw_parser<'src, I>() -> impl Parser<'src, I, (), ParserErr<'src>> where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - select! { Token::Ident(name) if name == "then" => () }.labelled("then") + select! { Token::Ident(name) if name == "hiding" => () } } pub(super) fn top_level_item_start_token_parser<'src, I>() @@ -84,12 +109,15 @@ pub(super) fn top_level_item_start_token_parser<'src, I>() where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - select! { - Token::Hash | Token::Import | Token::Export | Token::Pragma | Token::Type | Token::Data - | Token::Class | Token::Instance | Token::Contract | Token::Public - | Token::Payable | Token::Function | Token::Constructor | Token::Fallback - | Token::Forall | Token::Default => (), - } + choice(( + select! { + Token::Hash | Token::Import | Token::Export | Token::Pragma | Token::Type + | Token::Contract | Token::Function | Token::Default => (), + }, + enum_kw_parser().ignored(), + trait_kw_parser().ignored(), + impl_kw_parser().ignored(), + )) } pub(super) fn top_level_semicolon_parser<'src, I>( diff --git a/crates/parser/src/parse/expr_pat.rs b/crates/parser/src/parse/expr_pat.rs index b6871f95..ed1841c6 100644 --- a/crates/parser/src/parse/expr_pat.rs +++ b/crates/parser/src/parse/expr_pat.rs @@ -3,7 +3,7 @@ use hir::ast::function; use super::{ common::*, - items::{body_span_parser, param_parser}, + items::{body_span_parser, lambda_param_parser}, recovery::trace_recovery, types::type_parser, }; @@ -74,7 +74,7 @@ where let mut pat = Recursive::declare(); expr.define({ - let lambda_param = param_parser().boxed(); + let lambda_param = lambda_param_parser().boxed(); let lambda_params = lambda_param .separated_by(just(Token::Comma)) @@ -99,49 +99,12 @@ where }) .boxed(); - // Parse a right-nested `else if ...` chain as a flat list of heads. - // Recursing through the complete expression grammar once per `else` - // gives each level a very large Chumsky stack frame; folding the heads - // back into the same AST keeps ordinary else-if chains stack-bounded. - let if_head = just(Token::If) - .ignore_then(expr.clone()) - .then_ignore(then_kw_parser()) - .then(expr.clone()) - .then_ignore(just(Token::Else)) - .map_with(|(cond, then_expr), e| (e.span(), cond, then_expr)) - .boxed(); - let if_expr = if_head - .repeated() - .at_least(1) - .collect::>() - .then(expr.clone()) - .map(|(heads, tail)| { - heads.into_iter().rev().fold( - tail, - |else_expr, - (head_span, cond, then_expr): ( - LexSpan, - ParsedExpr<'src>, - ParsedExpr<'src>, - )| ParsedExpr { - span: LexSpan::from(head_span.start..else_expr.span.end), - kind: ParsedExprKind::If { - cond: Box::new(cond), - then_expr: Box::new(then_expr), - else_expr: Box::new(else_expr), - }, - }, - ) - }) - .boxed(); - let boundary = choice(( just(Token::Semi).ignored(), just(Token::Comma).ignored(), just(Token::RParen).ignored(), just(Token::RBracket).ignored(), just(Token::RBrace).ignored(), - then_kw_parser(), just(Token::Else).ignored(), just(Token::Question).ignored(), just(Token::Colon).ignored(), @@ -201,9 +164,13 @@ where span: e.span(), kind: ParsedExprKind::Lit(lit), }) + .or(boolean_value_parser().map(|ident| ParsedExpr { + span: ident.1, + kind: ParsedExprKind::Ident(ident), + })) .or(just(Token::Dot) .map_with(|_, e| e.span()) - .then(ident_parser()) + .then(ident_parser().or(boolean_value_parser())) .then( expr.clone() .separated_by(just(Token::Comma)) @@ -224,7 +191,6 @@ where .or(tuple_or_paren_expr) .or(array_expr) .or(lambda_expr) - .or(if_expr) .recover_with(via_parser(atom_recovery)) .boxed(); @@ -320,20 +286,7 @@ where parsed_bin_op_expr(lhs, op, rhs, e.span()) }); - let match_arm_separator = just(Token::Pipe) - .ignore_then( - pat.clone() - .separated_by(just(Token::Comma)) - .at_least(1) - .collect::>(), - ) - .then_ignore(just(Token::FatArrow)) - .ignored(); let bit_or_op = just(Token::Pipe) - // In a match body, `| pat =>` starts the next arm; without this - // guard the expression parser could consume the separator as a - // bitwise-or operator while recovering from the previous arm body. - .and_is(match_arm_separator.not()) .to(function::BinOp::BitOr) .map_with(|op, e| ParsedSpanned::new(op, e.span())); let bit_or = bit_xor @@ -391,43 +344,31 @@ where parsed_bin_op_expr(lhs, op, rhs, e.span()) }); - let ternary = recursive(|ternary| { - or.clone() - .then( - just(Token::Question) - .ignore_then(ternary.clone()) - .then_ignore(just(Token::Colon)) - .then(ternary) - .or_not(), - ) - .map_with(|(cond, arms), e| match arms { - Some((then_expr, else_expr)) => ParsedExpr { - span: e.span(), - kind: ParsedExprKind::If { - cond: Box::new(cond), - then_expr: Box::new(then_expr), - else_expr: Box::new(else_expr), - }, + // A conditional expression is right-associative. Parse the common + // `a ? b : c ? d : e` shape as a flat sequence and fold it from the + // right so a long chain does not recurse through Chumsky once per + // `else` arm. The then arm still uses the complete expression grammar, + // which preserves nested conditionals such as `a ? b ? c : d : e`. + let ternary_head = or + .clone() + .then_ignore(just(Token::Question)) + .then(expr.clone()) + .then_ignore(just(Token::Colon)); + let ternary = ternary_head + .repeated() + .foldr(or, |(cond, then_expr), else_expr| { + let span = LexSpan::from(cond.span.start..else_expr.span.end); + ParsedExpr { + span, + kind: ParsedExprKind::If { + cond: Box::new(cond), + then_expr: Box::new(then_expr), + else_expr: Box::new(else_expr), }, - None => cond, - }) - }) - .boxed(); + } + }); - let type_annot = just(Token::Colon).ignore_then(type_parser()).or_not(); ternary - .then(type_annot) - .map_with(|(expr, ty), e| match ty { - Some(ty) => ParsedExpr { - span: e.span(), - kind: ParsedExprKind::TypeAnnot { - expr: Box::new(expr), - ty, - }, - }, - None => expr, - }) - .boxed() }); pat.define({ @@ -445,6 +386,16 @@ where }) .boxed(); + // Boolean values are represented as variable-shaped patterns in HIR; + // name resolution recognizes these two reserved spellings as the + // builtin nullary constructors rather than introducing bindings. + let bool_pat = boolean_value_parser() + .map(|name| ParsedPat { + span: name.1, + kind: ParsedPatKind::Var(name), + }) + .boxed(); + let tuple_or_paren_pat = pat .clone() .separated_by(just(Token::Comma)) @@ -471,7 +422,7 @@ where let dot_ctor = just(Token::Dot) .map_with(|_, e| e.span()) - .then(ident_parser()) + .then(ident_parser().or(boolean_value_parser())) .then(ctor_args.clone()) .map_with(|((dot, name), args), e| ParsedPat { span: e.span(), @@ -539,6 +490,7 @@ where wildcard .or(lit_pat) + .or(bool_pat) .or(tuple_or_paren_pat) .or(dot_ctor) .or(comptime_pat) diff --git a/crates/parser/src/parse/imports.rs b/crates/parser/src/parse/imports.rs index dc1b4847..0929e905 100644 --- a/crates/parser/src/parse/imports.rs +++ b/crates/parser/src/parse/imports.rs @@ -109,18 +109,12 @@ where alias, constructors: None, }); - let selected_or_wildcard = just(Token::Star).to(None).or(selected_item.map(Some)); - let named_selector = selected_or_wildcard + let named_selector = selected_item .separated_by(just(Token::Comma)) .at_least(1) + .allow_trailing() .collect::>() - .map(|entries| { - if entries.iter().any(Option::is_none) { - ParsedImportSelector::Wildcard - } else { - ParsedImportSelector::Names(entries.into_iter().flatten().collect()) - } - }); + .map(ParsedImportSelector::Names); let selector = named_selector .delimited_by(just(Token::LBrace), just(Token::RBrace)) .boxed(); @@ -128,21 +122,23 @@ where .ignore_then( import_name_parser() .separated_by(just(Token::Comma)) + .at_least(1) .allow_trailing() .collect::>() .delimited_by(just(Token::LBrace), just(Token::RBrace)), ) .or_not() - .map(Option::unwrap_or_default); + .map(Option::unwrap_or_default) + .boxed(); let selective = just(Token::Import) - .ignore_then(path.clone()) - .then_ignore(just(Token::Dot)) - .then(selector) - .then(hiding) + .ignore_then(selector) + .then_ignore(from_kw_parser()) + .then(path.clone()) + .then(hiding.clone()) .then_ignore(top_level_semicolon_parser("import declaration")) .map_with( - |(((external, path), selector), hiding), e| ParsedTopItem::Import { + |((selector, (external, path)), hiding), e| ParsedTopItem::Import { span: e.span(), leading_comments: Vec::new(), external, @@ -154,12 +150,14 @@ where ) .boxed(); - let with_alias = just(Token::Import) - .ignore_then(path.clone()) + let namespace_alias = just(Token::Import) + .ignore_then(just(Token::Star)) .then_ignore(just(Token::As)) - .then(ident_parser()) + .ignore_then(ident_parser()) + .then_ignore(from_kw_parser()) + .then(path.clone()) .then_ignore(top_level_semicolon_parser("import declaration")) - .map_with(|((external, path), alias), e| ParsedTopItem::Import { + .map_with(|(alias, (external, path)), e| ParsedTopItem::Import { span: e.span(), leading_comments: Vec::new(), external, @@ -170,6 +168,23 @@ where }) .boxed(); + let wildcard = just(Token::Import) + .ignore_then(just(Token::Star)) + .ignore_then(from_kw_parser()) + .ignore_then(path.clone()) + .then(hiding) + .then_ignore(top_level_semicolon_parser("import declaration")) + .map_with(|((external, path), hiding), e| ParsedTopItem::Import { + span: e.span(), + leading_comments: Vec::new(), + external, + path, + alias: None, + selector: Some(ParsedImportSelector::Wildcard), + hiding, + }) + .boxed(); + let plain = just(Token::Import) .ignore_then(path) .then_ignore(top_level_semicolon_parser("import declaration")) @@ -184,7 +199,7 @@ where }) .boxed(); - choice((selective, with_alias, plain)) + choice((namespace_alias, wildcard, selective, plain)) .labelled("import declaration") .as_context() .boxed() diff --git a/crates/parser/src/parse/items.rs b/crates/parser/src/parse/items.rs index 320a88fb..8b42569f 100644 --- a/crates/parser/src/parse/items.rs +++ b/crates/parser/src/parse/items.rs @@ -6,11 +6,11 @@ use super::{ expr_pat::parsed_expr_parser, imports::{export_parser, import_parser, pragma_parser}, recovery::trace_recovery, - types::{forall_clause_parser, pred_list_parser, pred_parser, type_parser}, + types::{pred_list_parser, type_parser}, }; use crate::{lexer::Token, types::*}; -pub(super) fn param_parser<'src, I>() -> impl Parser<'src, I, ParsedFuncParam<'src>, ParserErr<'src>> +fn param_parser<'src, I>() -> impl Parser<'src, I, ParsedFuncParam<'src>, ParserErr<'src>> where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { @@ -75,11 +75,69 @@ where }); choice((comptime_typed, comptime_untyped, typed, untyped)) + .validate(|param, _, emitter| { + if let ParsedFuncParam::Typed { ty, .. } = ¶m + && matches!(ty.kind, ParsedTyKind::Comptime { .. }) + { + emitter.emit(Rich::custom( + ty.span, + "`comptime` is not a parameter type; write `comptime name: T`", + )); + } + param + }) .recover_with(via_parser(recovery)) .labelled("function parameter") .as_context() } +/// Parses a parameter of a named function-like declaration. +/// +/// Named functions, trait methods, constructors, and fallbacks require an +/// explicit type for every parameter. Keeping the untyped shape as an error +/// node lets parsing recover at the following comma without exposing inferred +/// named parameters to later semantic phases. +fn named_param_parser<'src, I>() -> impl Parser<'src, I, ParsedFuncParam<'src>, ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + param_parser().validate(|param, extra, emitter| match param { + ParsedFuncParam::Untyped { .. } => { + let span = extra.span(); + emitter.emit(Rich::custom( + span, + "named function parameter requires an explicit type", + )); + ParsedFuncParam::Error { span } + } + param => param, + }) +} + +/// Parses a lambda parameter. +/// +/// Ordinary lambda parameters may omit their type for inference. A `comptime` +/// parameter is still required to carry an explicit type. +pub(super) fn lambda_param_parser<'src, I>() +-> impl Parser<'src, I, ParsedFuncParam<'src>, ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + param_parser().validate(|param, extra, emitter| match param { + ParsedFuncParam::Untyped { + comptime: Some(_), .. + } => { + let span = extra.span(); + emitter.emit(Rich::custom( + span, + "`comptime` parameter requires an explicit type", + )); + ParsedFuncParam::Error { span } + } + param => param, + }) +} + #[derive(Debug, Clone, Copy, Default)] struct ParsedFuncModifiers { public: Option, @@ -98,6 +156,73 @@ impl FunctionContext { } } +fn generic_param_list_parser<'src, I>() +-> impl Parser<'src, I, (Vec>, LexSpan), ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + ident_parser() + .separated_by(just(Token::Comma)) + .at_least(1) + .allow_trailing() + .collect::>() + .delimited_by(just(Token::Less), just(Token::Greater)) + .map_with(|params, e| (params, e.span())) +} + +fn optional_generic_params_parser<'src, I>() +-> impl Parser<'src, I, (Vec>, Option), ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + generic_param_list_parser() + .or_not() + .map(|params| match params { + Some((params, span)) => (params, Some(span)), + None => (Vec::new(), None), + }) +} + +fn return_type_parser<'src, I>() -> impl Parser<'src, I, ParsedTy<'src>, ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + type_parser() + .separated_by(just(Token::Comma)) + .allow_trailing() + .collect::>() + .delimited_by(just(Token::LParen), just(Token::RParen)) + .map_with(|elems, e| match <[_; 1]>::try_from(elems) { + Ok([elem]) => elem, + Err(elems) => ParsedTy { + span: e.span(), + kind: ParsedTyKind::Tuple { elems }, + }, + }) +} + +fn where_clause_parser<'src, I>() -> impl Parser<'src, I, Vec>, ParserErr<'src>> +where + I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, +{ + where_kw_parser() + .ignore_then(pred_list_parser()) + .or_not() + .map(Option::unwrap_or_default) +} + +fn parsed_ident_type<'src>(ident: SpannedStr<'src>) -> ParsedTy<'src> { + ParsedTy { + span: ident.1, + kind: ParsedTyKind::Named { + qualifiers: Vec::new(), + name: ident, + args: Vec::new(), + args_span: None, + }, + } +} + fn contract_modifiers_parser<'src, I>( context: FunctionContext, ) -> impl Parser<'src, I, ParsedFuncModifiers, ParserErr<'src>> @@ -168,17 +293,9 @@ fn signature_parser<'src, I>( where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let forall = forall_clause_parser().boxed(); - - let preds = pred_list_parser() - .then_ignore(just(Token::FatArrow)) - .or_not() - .map(|preds| preds.unwrap_or_default()) - .boxed(); - let modifiers = contract_modifiers_parser(context).boxed(); - let params = param_parser() + let params = named_param_parser() .separated_by(just(Token::Comma)) .allow_trailing() .collect::>() @@ -186,26 +303,28 @@ where .map_with(|params, e| (params, e.span())) .boxed(); - let ret = just(Token::Arrow) - .ignore_then(type_parser()) + let ret = returns_kw_parser() + .ignore_then(return_type_parser()) .or_not() .boxed(); - forall - .then(preds) - .then(modifiers) - .then_ignore(just(Token::Function)) - .then(ident_parser()) + just(Token::Function) + .ignore_then(ident_parser()) + .then(optional_generic_params_parser()) .then(params) + .then(modifiers) .then(ret) + .then(where_clause_parser()) .map_with( - |(((((forall_info, mut preds), modifiers), name), (params, params_span)), ret), e| { - let (type_vars, mut forall_preds) = forall_info; - forall_preds.append(&mut preds); + |(((((name, (type_vars, _)), (params, params_span)), modifiers), ret), preds), e| { + let ret = Some(ret.unwrap_or_else(|| ParsedTy { + span: e.span(), + kind: ParsedTyKind::Tuple { elems: Vec::new() }, + })); ParsedFuncSig { span: e.span(), type_vars, - preds: forall_preds, + preds, public: modifiers.public, payable: modifiers.payable, name, @@ -274,7 +393,7 @@ where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { let modifiers = implicit_public_modifiers_parser(context, "constructor").boxed(); - let params = param_parser() + let params = named_param_parser() .separated_by(just(Token::Comma)) .allow_trailing() .collect::>() @@ -282,12 +401,13 @@ where .map_with(|params, e| (params, e.span())) .boxed(); - modifiers - .then(just(Token::Constructor).map_with(|_, e| e.span())) + just(Token::Constructor) + .map_with(|_, e| e.span()) .then(params) + .then(modifiers) .then(body_span_parser()) .map_with( - |(((modifiers, name_span), (params, params_span)), body_span), e| ParsedFunctionDef { + |(((name_span, (params, params_span)), modifiers), body_span), e| ParsedFunctionDef { span: e.span(), kind: FuncKind::Constructor, leading_comments: Vec::new(), @@ -310,31 +430,15 @@ where .boxed() } -fn parsed_ty_is_unit(ty: &ParsedTy<'_>) -> bool { - match &ty.kind { - ParsedTyKind::Tuple { elems } if elems.is_empty() => true, - ParsedTyKind::Tuple { elems } if elems.len() == 1 => parsed_ty_is_unit(&elems[0]), - _ => false, - } -} - fn fallback_def_parser<'src, I>( context: FunctionContext, ) -> impl Parser<'src, I, ParsedFunctionDef<'src>, ParserErr<'src>> where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let forall = forall_clause_parser().boxed(); - - let preds = pred_list_parser() - .then_ignore(just(Token::FatArrow)) - .or_not() - .map(|preds| preds.unwrap_or_default()) - .boxed(); - let modifiers = implicit_public_modifiers_parser(context, "fallback").boxed(); - let params = param_parser() + let params = named_param_parser() .separated_by(just(Token::Comma)) .allow_trailing() .collect::>() @@ -342,18 +446,11 @@ where .map_with(|params, e| (params, e.span())) .boxed(); - let ret = just(Token::Arrow) - .ignore_then(type_parser()) - .or_not() - .boxed(); - - forall - .then(preds) - .then(modifiers) - .then(just(Token::Fallback).map_with(|_, e| e.span())) + just(Token::Fallback) + .map_with(|_, e| e.span()) .then(params) .validate(|value, _, emitter| { - let ((((_, _), _), _), (params, params_span)) = &value; + let (_, (params, params_span)) = &value; if !params.is_empty() { emitter.emit(Rich::custom( *params_span, @@ -362,44 +459,25 @@ where } value }) - .then(ret) - .validate(|value, _, emitter| { - if let Some(ret_ty) = &value.1 - && !parsed_ty_is_unit(ret_ty) - { - emitter.emit(Rich::custom( - ret_ty.span, - "fallback function must return unit (`()`)", - )); - } - value - }) + .then(modifiers) .then(body_span_parser()) .map_with( - |( - (((((forall_info, mut preds), modifiers), name_span), (params, params_span)), ret), - body_span, - ), - e| { - let (type_vars, mut forall_preds) = forall_info; - forall_preds.append(&mut preds); - ParsedFunctionDef { + |(((name_span, (params, params_span)), modifiers), body_span), e| ParsedFunctionDef { + span: e.span(), + kind: FuncKind::Fallback, + leading_comments: Vec::new(), + sig: ParsedFuncSig { span: e.span(), - kind: FuncKind::Fallback, - leading_comments: Vec::new(), - sig: ParsedFuncSig { - span: e.span(), - type_vars, - preds: forall_preds, - public: modifiers.public, - payable: modifiers.payable, - name: ("fallback", name_span), - params, - params_span, - ret, - }, - body_span, - } + type_vars: Vec::new(), + preds: Vec::new(), + public: modifiers.public, + payable: modifiers.payable, + name: ("fallback", name_span), + params, + params_span, + ret: None, + }, + body_span, }, ) .labelled("fallback definition") @@ -492,7 +570,7 @@ where .map_with(|(name, fields), e| ParsedAdtCtor { span: e.span(), // Filled by `adt_payload_parser`, which owns the introducing - // `=`/`|` token. + // `{`/`,` token. introducer: None, leading_comments: Vec::new(), name, @@ -501,13 +579,6 @@ where .boxed() } -fn data_terminator_parser<'src, I>() -> impl Parser<'src, I, (), ParserErr<'src>> -where - I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, -{ - just(Token::Semi).ignored() -} - fn derive_target_parser<'src, I>() -> impl Parser<'src, I, ParsedDeriveTarget<'src>, ParserErr<'src>> where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, @@ -534,7 +605,7 @@ where if reserved { emitter.emit(Rich::custom( e.span(), - format!("reserved keyword `{name}` cannot name a derived class"), + format!("reserved keyword `{name}` cannot name a derived trait"), )); } if name.contains('-') { @@ -591,7 +662,7 @@ where if attr.targets.is_empty() { emitter.emit(Rich::custom( attr.span, - "derive attribute requires at least one class path", + "derive attribute requires at least one trait path", )); } attr @@ -618,7 +689,7 @@ where .validate(|attr, _, emitter| { emitter.emit(Rich::custom( attr.span, - "malformed derive attribute; expected `#[derive(Class, ...)]`", + "malformed derive attribute; expected `#[derive(Trait, ...)]`", )); attr }); @@ -670,16 +741,7 @@ fn adt_payload_parser<'src, I>() -> impl Parser< where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let ty_params = ident_parser() - .separated_by(just(Token::Comma)) - .allow_trailing() - .collect::>() - .delimited_by(just(Token::LParen), just(Token::RParen)) - .or_not() - .map(|params| params.unwrap_or_default()) - .boxed(); - - let following_ctor = just(Token::Pipe) + let following_ctor = just(Token::Comma) .map_with(|_, e| e.span()) .then(data_ctor_parser()) .map(|(introducer, mut ctor)| { @@ -688,32 +750,31 @@ where }); let ctor_list = data_ctor_parser() .then(following_ctor.repeated().collect::>()) + .then_ignore(just(Token::Comma).or_not()) .map(|(first, mut rest)| { let mut ctors = Vec::with_capacity(rest.len() + 1); ctors.push(first); ctors.append(&mut rest); ctors }); - let ctors = just(Token::Eq) + let ctors = just(Token::LBrace) .map_with(|_, e| e.span()) - .then(ctor_list) - .map(|(introducer, mut ctors)| { - ctors - .first_mut() - .expect("constructor list parser always returns one constructor") - .introducer = Some(introducer); + .then(ctor_list.or_not()) + .then_ignore(just(Token::RBrace)) + .map(|(introducer, ctors)| { + let mut ctors = ctors.unwrap_or_default(); + if let Some(first) = ctors.first_mut() { + first.introducer = Some(introducer); + } ctors }) - .or_not() - .map(|ctors| ctors.unwrap_or_default()) .boxed(); - just(Token::Data) + enum_kw_parser() .ignore_then(ident_parser()) - .then(ty_params) + .then(optional_generic_params_parser()) .then(ctors) - .then_ignore(data_terminator_parser()) - .map(|((name, ty_params), ctors)| (name, ty_params, ctors)) + .map(|((name, (ty_params, _)), ctors)| (name, ty_params, ctors)) } fn adt_parser<'src, I>() -> impl Parser<'src, I, ParsedTopItem<'src>, ParserErr<'src>> @@ -729,7 +790,7 @@ where ty_params, ctors, }) - .labelled("data declaration") + .labelled("enum declaration") .as_context() .boxed() } @@ -751,38 +812,41 @@ fn class_parser<'src, I>() -> impl Parser<'src, I, ParsedTopItem<'src>, ParserEr where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let forall = forall_clause_parser().boxed(); - - let super_preds = pred_list_parser() - .then_ignore(just(Token::FatArrow)) - .or_not() - .map(|preds| preds.unwrap_or_default()) - .boxed(); - let methods = method_sig_parser() .repeated() .collect::>() .delimited_by(just(Token::LBrace), just(Token::RBrace)) .boxed(); - forall - .then(super_preds) - .then_ignore(just(Token::Class)) - .then(pred_parser()) + trait_kw_parser() + .ignore_then(ident_parser()) + .then(generic_param_list_parser()) + .then(where_clause_parser()) .then(methods) - .map_with(|(((forall_info, mut super_preds), head), methods), e| { - let (type_vars, mut forall_preds) = forall_info; - forall_preds.append(&mut super_preds); - ParsedTopItem::Class { - span: e.span(), - leading_comments: Vec::new(), - type_vars, - super_preds: forall_preds, - head, - methods, - } - }) - .labelled("class declaration") + .map_with( + |(((name, (type_vars, args_span)), super_preds), methods), e| { + let mut head_types = type_vars.iter().copied().map(parsed_ident_type); + let subject = head_types + .next() + .expect("trait generic parameter parser is non-empty"); + let args = head_types.collect::>(); + let head = ParsedPred { + ty: subject, + class: name, + args, + args_span: Some(args_span), + }; + ParsedTopItem::Class { + span: e.span(), + leading_comments: Vec::new(), + type_vars, + super_preds, + head, + methods, + } + }, + ) + .labelled("trait declaration") .as_context() .boxed() } @@ -791,14 +855,6 @@ fn instance_parser<'src, I>() -> impl Parser<'src, I, ParsedTopItem<'src>, Parse where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let forall = forall_clause_parser().boxed(); - - let preds = pred_list_parser() - .then_ignore(just(Token::FatArrow)) - .or_not() - .map(|preds| preds.unwrap_or_default()) - .boxed(); - let default_kw = just(Token::Default) .map_with(|_, e| e.span()) .or_not() @@ -810,55 +866,45 @@ where .delimited_by(just(Token::LBrace), just(Token::RBrace)) .boxed(); - let pre_instance_preds = forall - .clone() - .then(preds.clone()) - .then(default_kw.clone()) - .then_ignore(just(Token::Instance)) - .then(pred_parser()) - .then(methods.clone()) - .map_with( - |((((forall_info, mut preds), default_kw), head), methods), e| { - let (type_vars, mut forall_preds) = forall_info; - forall_preds.append(&mut preds); - ParsedTopItem::Instance { - span: e.span(), - leading_comments: Vec::new(), - type_vars, - preds: forall_preds, - default_kw, - head, - methods, - } - }, + let head = ident_parser() + .then( + type_parser() + .separated_by(just(Token::Comma)) + .at_least(1) + .allow_trailing() + .collect::>() + .delimited_by(just(Token::Less), just(Token::Greater)) + .map_with(|args, e| (args, e.span())), ) + .map(|(class, (mut args, args_span))| { + let ty = args.remove(0); + ParsedPred { + ty, + class, + args, + args_span: Some(args_span), + } + }) .boxed(); - let post_instance_preds = forall - .then(default_kw) - .then_ignore(just(Token::Instance)) - .then(preds) - .then(pred_parser()) + default_kw + .then_ignore(impl_kw_parser()) + .then(optional_generic_params_parser()) + .then(head) + .then(where_clause_parser()) .then(methods) .map_with( - |((((forall_info, default_kw), mut preds), head), methods), e| { - let (type_vars, mut forall_preds) = forall_info; - forall_preds.append(&mut preds); - ParsedTopItem::Instance { - span: e.span(), - leading_comments: Vec::new(), - type_vars, - preds: forall_preds, - default_kw, - head, - methods, - } + |((((default_kw, (type_vars, _)), head), preds), methods), e| ParsedTopItem::Instance { + span: e.span(), + leading_comments: Vec::new(), + type_vars, + preds, + default_kw, + head, + methods, }, ) - .boxed(); - - choice((pre_instance_preds, post_instance_preds)) - .labelled("instance declaration") + .labelled("impl declaration") .as_context() .boxed() } @@ -928,15 +974,13 @@ where }) .boxed(); - let item_start = just(Token::Hash) - .or(just(Token::Public)) - .or(just(Token::Payable)) - .or(just(Token::Function)) - .or(just(Token::Constructor)) - .or(just(Token::Fallback)) - .or(just(Token::Type)) - .or(just(Token::Data)) - .or(just(Token::RBrace)); + let item_start = choice(( + select! { + Token::Hash | Token::Function | Token::Constructor | Token::Fallback + | Token::Type | Token::RBrace => (), + }, + enum_kw_parser().ignored(), + )); let recovery = any() .and_is(item_start.not()) .repeated() @@ -990,7 +1034,7 @@ where _ => { emitter.emit(Rich::custom( attr.span, - "derive attribute is only allowed on data declarations", + "derive attribute is only allowed on enum declarations", )); let span = match &mut member { ParsedContractMember::Field(field) => &mut field.span, @@ -1017,15 +1061,6 @@ fn contract_parser<'src, I>() -> impl Parser<'src, I, ParsedTopItem<'src>, Parse where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let ty_params = ident_parser() - .separated_by(just(Token::Comma)) - .allow_trailing() - .collect::>() - .delimited_by(just(Token::LParen), just(Token::RParen)) - .or_not() - .map(|params| params.unwrap_or_default()) - .boxed(); - let members = contract_member_parser() .repeated() .collect::>() @@ -1034,9 +1069,9 @@ where just(Token::Contract) .ignore_then(ident_parser()) - .then(ty_params) + .then(optional_generic_params_parser()) .then(body) - .map_with(|((name, ty_params), members), e| { + .map_with(|((name, (ty_params, _)), members), e| { let mut fields = Vec::new(); let mut items = Vec::new(); for member in members { @@ -1064,20 +1099,7 @@ pub(super) fn top_item_parser<'src, I>() where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { - let item_start = just(Token::Hash) - .or(just(Token::Import)) - .or(just(Token::Export)) - .or(just(Token::Pragma)) - .or(just(Token::Type)) - .or(just(Token::Data)) - .or(just(Token::Class)) - .or(just(Token::Instance)) - .or(just(Token::Contract)) - .or(just(Token::Public)) - .or(just(Token::Payable)) - .or(just(Token::Function)) - .or(just(Token::Forall)) - .or(just(Token::Default)); + let item_start = top_level_item_start_token_parser(); let recovery = any() .and_is(item_start.not()) .repeated() @@ -1121,7 +1143,7 @@ where _ => { emitter.emit(Rich::custom( attr.span, - "derive attribute is only allowed on data declarations", + "derive attribute is only allowed on enum declarations", )); let span = match &mut item { ParsedTopItem::Import { span, .. } diff --git a/crates/parser/src/parse/mod.rs b/crates/parser/src/parse/mod.rs index a2b654d3..04d4474a 100644 --- a/crates/parser/src/parse/mod.rs +++ b/crates/parser/src/parse/mod.rs @@ -430,6 +430,9 @@ pub(crate) fn parse_body_statements<'src>( }) .collect::>(); nesting_errors.extend(suppress_body_cascades(parse_errors)); + if let Some(output) = output.as_deref() { + validate_expression_statement_terminators(output, true, &mut nesting_errors); + } ParseOutput { output: output.unwrap_or_default(), @@ -437,6 +440,44 @@ pub(crate) fn parse_body_statements<'src>( } } +fn validate_expression_statement_terminators( + stmts: &[ParsedStmt<'_>], + allow_final_unterminated: bool, + errors: &mut Vec, +) { + for (index, stmt) in stmts.iter().enumerate() { + let is_final = index + 1 == stmts.len(); + match &stmt.kind { + ParsedStmtKind::Expr { + trailing_semi: false, + .. + } if !(allow_final_unterminated && is_final) => errors.push(ParsedError::new( + stmt.span, + "expression statement requires trailing `;`; only a final named function body expression may omit it", + )), + ParsedStmtKind::Match { arms, .. } => { + for arm in arms { + validate_expression_statement_terminators(&arm.body, false, errors); + } + } + ParsedStmtKind::For { body, .. } | ParsedStmtKind::Block { body } => { + validate_expression_statement_terminators(body, false, errors); + } + ParsedStmtKind::If { + then_body, + else_body, + .. + } => { + validate_expression_statement_terminators(then_body, false, errors); + if let Some(else_body) = else_body { + validate_expression_statement_terminators(else_body, false, errors); + } + } + _ => {} + } + } +} + #[cfg(test)] mod tests { use chumsky::prelude::*; @@ -742,6 +783,7 @@ mod tests { "unexpected function definition: {stmt:#?}" ); + // syntax-migration: preserve-next-literal let stmt = parse_yul_stmt("function _(_) -> _ { _ := _ }"); assert!( matches!( @@ -937,7 +979,7 @@ mod tests { #[test] fn unicode_identifier_parses() { - let source = "function fλ(x: word) -> word { return x; }"; + let source = "function fλ(x: word) returns (word) { return x; }"; let parsed = parse_supported_items(source); assert!( parsed.errors.is_empty(), From b751b6f92123d3e2733d8a2e0440d8525bcf7bdb Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 045/110] Switch the compiler and fixtures to canonical syntax: parser Co-authored-by: Codex --- crates/parser/src/parse/mod.rs | 408 ++++++++++++++++++++++- crates/parser/src/parse/recovery.rs | 11 +- crates/parser/src/parse/stmt.rs | 144 ++++++-- crates/parser/src/parse/types.rs | 235 ++++++------- crates/parser/src/parse/yul.rs | 3 + crates/parser/src/types.rs | 45 ++- crates/parser/tests/def_identity.rs | 38 +-- crates/parser/tests/diagnostics.rs | 10 +- crates/parser/tests/incremental_spans.rs | 2 +- 9 files changed, 661 insertions(+), 235 deletions(-) diff --git a/crates/parser/src/parse/mod.rs b/crates/parser/src/parse/mod.rs index 04d4474a..a0196037 100644 --- a/crates/parser/src/parse/mod.rs +++ b/crates/parser/src/parse/mod.rs @@ -994,7 +994,11 @@ mod tests { #[test] fn parenthesized_single_pattern_parses_as_grouping() { - let source = "{ match p { | (y) => return y; | ((), (x, z)) => return x; } }"; + let source = "\ +{ match (p) { + case (y) { return y; } + case ((), (x, z)) { return x; } +} }"; let body = parse_body_statements(source, (0..source.len()).into()); assert!(body.errors.is_empty(), "body errors: {:?}", body.errors); @@ -1016,10 +1020,10 @@ mod tests { #[test] fn qualified_constructor_patterns_parse() { let source = "\ -{ match mmx { -| Option.None => return x; -| Option.Some(Option.None) => return x; -| y => return y; +{ match (mmx) { +case Option.None { return x; } +case Option.Some(Option.None) { return x; } +case y { return y; } } }"; let body = parse_body_statements(source, (0..source.len()).into()); assert!(body.errors.is_empty(), "body errors: {:?}", body.errors); @@ -1062,7 +1066,7 @@ mod tests { #[test] fn import_with_alias_parses() { - let parsed = parse_supported_items("import math.bits as Bits;"); + let parsed = parse_supported_items("import * as Bits from math.bits;"); assert!(parsed.errors.is_empty(), "errors: {:?}", parsed.errors); match parsed.output.as_slice() { @@ -1091,7 +1095,7 @@ mod tests { #[test] fn import_with_selected_items_parses() { - let parsed = parse_supported_items("import math.words.{addWord, subWord};"); + let parsed = parse_supported_items("import {addWord, subWord} from math.words;"); assert!(parsed.errors.is_empty(), "errors: {:?}", parsed.errors); match parsed.output.as_slice() { @@ -1131,7 +1135,7 @@ mod tests { #[test] fn import_with_wildcard_and_hiding_parses() { - let parsed = parse_supported_items("import glob.{*} hiding {drop};"); + let parsed = parse_supported_items("import * from glob hiding {drop};"); assert!(parsed.errors.is_empty(), "errors: {:?}", parsed.errors); match parsed.output.as_slice() { @@ -1155,7 +1159,7 @@ mod tests { #[test] fn import_and_export_operator_names_parse() { - let parsed = parse_supported_items("import math.{pow, (^^)};\nexport { f, (^^) };"); + let parsed = parse_supported_items("import {pow, (^^)} from math;\nexport { f, (^^) };"); assert!(parsed.errors.is_empty(), "errors: {:?}", parsed.errors); assert!(matches!( @@ -1173,6 +1177,392 @@ mod tests { ); } + #[test] + fn canonical_function_headers_and_return_shapes_parse() { + let source = r#" +contract Box { + function one(value: U) public payable returns (Option) where U: Eq { + return Option.Some(value); + } + function pair() returns (word, bool) { return (0, true); } + function explicitUnit() returns () { return; } + function implicitUnit() { return; } +} +"#; + let parsed = parse_supported_items(source); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + + let [ + ParsedTopItem::Contract { + ty_params, items, .. + }, + ] = parsed.output.as_slice() + else { + panic!("unexpected parse output: {:#?}", parsed.output); + }; + assert!(matches!(ty_params.as_slice(), [("T", _)])); + + let [ + ParsedContractItem::Function(one), + ParsedContractItem::Function(pair), + ParsedContractItem::Function(explicit_unit), + ParsedContractItem::Function(implicit_unit), + ] = items.as_slice() + else { + panic!("unexpected contract items: {items:#?}"); + }; + + assert!(one.sig.public.is_some()); + assert!(one.sig.payable.is_some()); + assert!(matches!(one.sig.type_vars.as_slice(), [("U", _)])); + assert_eq!(one.sig.preds.len(), 1); + assert!(matches!( + &one.sig.ret, + Some(ParsedTy { + kind: ParsedTyKind::Named { name: ("Option", _), args, .. }, + .. + }) if args.len() == 1 + )); + assert!(matches!( + &pair.sig.ret, + Some(ParsedTy { + kind: ParsedTyKind::Tuple { elems }, + .. + }) if elems.len() == 2 + )); + assert!(matches!( + &explicit_unit.sig.ret, + Some(ParsedTy { + kind: ParsedTyKind::Tuple { elems }, + .. + }) if elems.is_empty() + )); + assert!(matches!( + &implicit_unit.sig.ret, + Some(ParsedTy { + kind: ParsedTyKind::Tuple { elems }, + .. + }) if elems.is_empty() + )); + } + + #[test] + fn canonical_composite_and_function_types_parse() { + let source = r#" +function useTypes( + callback: function(word) returns (bool), + fire: function(word), + table: mapping(address => memory>) +) returns (bool) { return true; } +"#; + let parsed = parse_supported_items(source); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + let [ParsedTopItem::Function { sig, .. }] = parsed.output.as_slice() else { + panic!("unexpected parse output: {:#?}", parsed.output); + }; + + let [ + ParsedFuncParam::Typed { ty: callback, .. }, + ParsedFuncParam::Typed { ty: fire, .. }, + ParsedFuncParam::Typed { ty: table, .. }, + ] = sig.params.as_slice() + else { + panic!("unexpected parameters: {:#?}", sig.params); + }; + assert!(matches!( + &callback.kind, + ParsedTyKind::Fn { params, ret, .. } + if params.len() == 1 + && matches!(ret.kind, ParsedTyKind::Named { name: ("bool", _), .. }) + )); + assert!(matches!( + &fire.kind, + ParsedTyKind::Fn { params, ret, .. } + if params.len() == 1 + && matches!(&ret.kind, ParsedTyKind::Tuple { elems } if elems.is_empty()) + )); + assert!(matches!( + &table.kind, + ParsedTyKind::Named { name: ("mapping", _), args, .. } + if args.len() == 2 + && matches!( + &args[1].kind, + ParsedTyKind::Named { name: ("memory", _), args, .. } + if args.len() == 1 + ) + )); + assert!(matches!( + &sig.ret, + Some(ParsedTy { + kind: ParsedTyKind::Named { + name: ("bool", _), + .. + }, + .. + }) + )); + } + + #[test] + fn generic_argument_and_where_lists_require_at_least_one_entry() { + for source in [ + "function value(x: Box) returns (T) where T: Eq { return x; }", + "function pair(x: Pair) where (T: Eq, U: Eq) {}", + ] { + let parsed = parse_supported_items(source); + assert!( + parsed.errors.is_empty(), + "canonical non-empty list failed to parse: {source}: {:#?}", + parsed.errors + ); + } + + // syntax-migration: preserve-literals-begin + for source in [ + "function emptyArgs(x: Box<>) {}", + "function emptyConstraintArgs(x: T) where T: Eq<> {}", + "function genericMapping(x: mapping) {}", + "function bareMapping(x: mapping) {}", + "function emptyWhere(x: T) where {}", + "function emptyParenWhere(x: T) where () {}", + ] { + let parsed = parse_supported_items(source); + assert!( + !parsed.errors.is_empty(), + "empty generic or constraint list unexpectedly parsed: {source}: {:#?}", + parsed.output + ); + } + // syntax-migration: preserve-literals-end + } + + #[test] + fn enum_trait_and_impl_surface_lowers_to_existing_nodes() { + let source = r#" +enum Option { None, Some(T), } +trait Eq { + function eq(left: T, right: T) returns (bool); +} +impl Eq> where T: Eq { + function eq(left: Option, right: Option) returns (bool) { return true; } +} +default impl ABIAttribs {} +"#; + let parsed = parse_supported_items(source); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + assert!(matches!( + parsed.output.as_slice(), + [ + ParsedTopItem::Adt { ty_params, ctors, .. }, + ParsedTopItem::Class { type_vars, methods, .. }, + ParsedTopItem::Instance { type_vars: impl_vars, preds, default_kw: None, .. }, + ParsedTopItem::Instance { default_kw: Some(_), .. }, + ] if ty_params.len() == 1 + && ctors.len() == 2 + && type_vars.len() == 1 + && methods.len() == 1 + && impl_vars.len() == 1 + && preds.len() == 1 + )); + } + + #[test] + fn case_default_match_and_while_lower_to_existing_statement_nodes() { + let source = r#"{ +while (keepGoing) { continue; } +match (left, right) { + case (Option.Some(a), Option.Some(b)) { return a; } + default { return 0; } +} +}"#; + let body = parse_body_statements(source, (0..source.len()).into()); + assert!(body.errors.is_empty(), "body errors: {:#?}", body.errors); + let [ + ParsedStmt { + kind: + ParsedStmtKind::For { + init, + post, + body: loop_body, + .. + }, + .. + }, + ParsedStmt { + kind: ParsedStmtKind::Match { scrutinees, arms }, + .. + }, + ] = body.output.as_slice() + else { + panic!("unexpected body: {:#?}", body.output); + }; + assert!(init.is_empty() && post.is_empty() && loop_body.len() == 1); + assert_eq!(scrutinees.len(), 2); + assert_eq!(arms.len(), 2); + assert_eq!(arms[0].pats.len(), 2); + assert!( + arms[1] + .pats + .iter() + .all(|pat| matches!(pat.kind, ParsedPatKind::Wildcard)) + ); + } + + #[test] + fn named_function_like_parameters_require_explicit_types() { + for source in [ + "function f(value) {}", + "function f(comptime value) {}", + "trait T { function f(value); }", + "impl T { function f(value) {} }", + "contract C { constructor(value) {} }", + ] { + let parsed = parse_supported_items(source); + assert!( + parsed.errors.iter().any(|error| { + error.message == "named function parameter requires an explicit type" + }), + "missing explicit-parameter-type error for `{source}`: {:#?}", + parsed.errors + ); + } + + let parsed = parse_supported_items( + "function f(value: word, comptime offset: word) returns (word) { return value; }", + ); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + + for source in [ + "function f(value: comptime) {}", + "function f(comptime value: comptime) {}", + ] { + let parsed = parse_supported_items(source); + assert!( + parsed.errors.iter().any(|error| error.message + == "`comptime` is not a parameter type; write `comptime name: T`"), + "missing canonical comptime-parameter-placement error for `{source}`: {:#?}", + parsed.errors + ); + } + } + + #[test] + fn lambda_parameters_allow_inference_but_comptime_still_requires_a_type() { + let source = "{ let inferred = lam (value) { return value; }; }"; + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + + let source = "{ let invalid = lam (comptime value) { return value; }; }"; + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!( + parsed + .errors + .iter() + .any(|error| { error.message == "`comptime` parameter requires an explicit type" }), + "missing comptime-parameter-type error: {:#?}", + parsed.errors + ); + + for source in [ + "{ let invalid = lam (value: comptime) { return value; }; }", + "{ let invalid = lam (comptime value: comptime) { return value; }; }", + ] { + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!( + parsed.errors.iter().any(|error| error.message + == "`comptime` is not a parameter type; write `comptime name: T`"), + "missing noncanonical comptime-parameter error for `{source}`: {:#?}", + parsed.errors + ); + } + } + + #[test] + fn if_statement_requires_a_parenthesized_condition() { + let source = "{ if (condition) { return 1; } else { return 0; } }"; + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + assert!(matches!( + parsed.output.as_slice(), + [ParsedStmt { + kind: ParsedStmtKind::If { .. }, + .. + }] + )); + + let source = "{ if condition { return 1; } }"; + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!( + !parsed.errors.is_empty(), + "unparenthesized legacy if statement unexpectedly parsed: {:#?}", + parsed.output + ); + } + + #[test] + fn only_a_root_tail_expression_may_omit_its_semicolon() { + let source = "{ first(); second() }"; + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!(parsed.errors.is_empty(), "errors: {:#?}", parsed.errors); + + for source in [ + "{ first() second(); }", + "{ if (condition) { branch() } }", + "{ { nested() } }", + "{ match (value) { case _ { arm() } } }", + ] { + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!( + parsed.errors.iter().any(|error| error + .message + .starts_with("expression statement requires trailing `;`")), + "unterminated non-tail expression unexpectedly parsed: {source}: {:#?}", + parsed.errors + ); + } + } + + #[test] + fn rejected_legacy_core_spellings_produce_parse_errors() { + // Every case below is intentionally written in a rejected legacy + // spelling. Keep this list as the explicit compatibility boundary. + // syntax-migration: preserve-literals-begin + for source in [ + "data Option(T) = None;", + "class Eq(T) {}", + "instance Eq: word {}", + "forall T. function id(x: T) -> T { return x; }", + "public function exposed() -> word { return 0; }", + "function arrowResult() -> word { return 0; }", + "function oldType(value: array(word)) {}", + "import old.module.{item};", + ] { + let parsed = parse_supported_items(source); + assert!( + !parsed.errors.is_empty(), + "legacy spelling unexpectedly parsed: {source}: {:#?}", + parsed.output + ); + } + + for source in [ + "{ return value: word; }", + "{ return value as word; }", + "{ return if true then 1 else 0; }", + "{ match value { | item => return item; } }", + "{ let value := 1; }", + "{ value := 1; }", + ] { + let parsed = parse_body_statements(source, (0..source.len()).into()); + assert!( + !parsed.errors.is_empty(), + "legacy body spelling unexpectedly parsed: {source}: {:#?}", + parsed.output + ); + } + // syntax-migration: preserve-literals-end + } + #[test] fn lexical_error_does_not_hide_independent_top_level_parse_error() { let parsed = parse_supported_items("§\nfunction ok() {}\nfunction broken( { }\n"); diff --git a/crates/parser/src/parse/recovery.rs b/crates/parser/src/parse/recovery.rs index e5172eed..81b1dfea 100644 --- a/crates/parser/src/parse/recovery.rs +++ b/crates/parser/src/parse/recovery.rs @@ -32,8 +32,7 @@ fn preview_span_source(source: &str, span: LexSpan, max_chars: usize) -> Option< } pub(super) fn top_level_recovery_message(source: &str, span: LexSpan) -> String { - let expected = - "`import`, `pragma`, `type`, `data`, `class`, `instance`, `contract`, or `function`"; + let expected = "`import`, `pragma`, `type`, `enum`, `trait`, `impl`, `contract`, or `function`"; match preview_span_source(source, span, 48) { Some(preview) => format!( "could not parse top-level item near `{preview}`; expected a declaration starting with {expected}" @@ -99,7 +98,7 @@ fn is_statement_start_token(token: &Token<'_>) -> bool { | Token::LBrace | Token::Break | Token::Continue - ) + ) || matches!(token, Token::Ident("while")) } pub(super) fn refine_body_parse_error<'src>( @@ -123,7 +122,7 @@ fn refine_let_parse_error<'src>( ) -> Option { let assignment_idx = tokens[let_idx + 1..] .iter() - .position(|(token, _)| matches!(token, Token::Eq | Token::ColonEq)) + .position(|(token, _)| matches!(token, Token::Eq)) .map(|idx| let_idx + 1 + idx)?; if let Some((Token::Semi, semi_span)) = tokens.get(assignment_idx + 1) { @@ -169,10 +168,10 @@ fn refine_match_parse_error<'src>( Some( ParsedError::new( LexSpan::from(lbrace_span.start..rbrace_span.end), - "match statement requires at least one arm", + "match requires at least one `case` or `default` arm", ) .with_label("empty match arm list") - .with_note("add a `| pattern =>` arm"), + .with_note("add a `case pattern { ... }` or `default { ... }` arm"), ) } diff --git a/crates/parser/src/parse/stmt.rs b/crates/parser/src/parse/stmt.rs index eaf76281..488d5888 100644 --- a/crates/parser/src/parse/stmt.rs +++ b/crates/parser/src/parse/stmt.rs @@ -45,6 +45,7 @@ where fn assign_stmt_kind<'src>( lhs: ParsedExpr<'src>, tail: Option>, + trailing_semi: bool, ) -> ParsedStmtKind<'src> { match tail { Some(ParsedAssignTail::Binary(op, rhs)) => { @@ -91,7 +92,10 @@ fn assign_stmt_kind<'src>( rhs, } } - None => ParsedStmtKind::Expr(lhs), + None => ParsedStmtKind::Expr { + expr: lhs, + trailing_semi, + }, } } @@ -116,12 +120,7 @@ where just(Token::Let) .ignore_then(ident_parser()) .then(just(Token::Colon).ignore_then(type_parser()).or_not()) - .then( - just(Token::Eq) - .or(just(Token::ColonEq)) - .ignore_then(parsed_expr_parser()) - .or_not(), - ) + .then(just(Token::Eq).ignore_then(parsed_expr_parser()).or_not()) .map_with(|((name, ty), init), e| ParsedStmt { span: e.span(), kind: ParsedStmtKind::Let { @@ -142,7 +141,10 @@ where .then(assign_tail_parser().or_not()) .map_with(|(lhs, tail), e| ParsedStmt { span: e.span(), - kind: assign_stmt_kind(lhs, tail), + // `for` header items are terminated by `,`, `;`, or `)` rather + // than by statement semicolons. They are never candidates for a + // function-body tail expression. + kind: assign_stmt_kind(lhs, tail, true), }) } @@ -152,31 +154,28 @@ where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { recursive(|stmt| { - let match_arm = just(Token::Pipe) - .ignore_then( - parsed_pat_parser() - .separated_by(just(Token::Comma)) - .at_least(1) - .collect::>(), - ) - .then_ignore(just(Token::FatArrow)) - .then(stmt.clone().repeated().collect::>()) - .map_with(|(pats, body), e| ParsedMatchArm { - span: e.span(), - pats, - body, - }) + let arm_body = stmt + .clone() + .repeated() + .collect::>() + .delimited_by(just(Token::LBrace), just(Token::RBrace)) + .boxed(); + + let case_arm = just(Token::Case) + .ignore_then(parsed_pat_parser()) + .then(arm_body.clone()) + .map_with(|(pat, body), e| (e.span(), pat, body)) + .boxed(); + + let default_arm = just(Token::Default) + .map_with(|_, e| e.span()) + .then(arm_body) .boxed(); let let_stmt = just(Token::Let) .ignore_then(ident_parser()) .then(just(Token::Colon).ignore_then(type_parser()).or_not()) - .then( - just(Token::Eq) - .or(just(Token::ColonEq)) - .ignore_then(parsed_expr_parser()) - .or_not(), - ) + .then(just(Token::Eq).ignore_then(parsed_expr_parser()).or_not()) .then_ignore(just(Token::Semi)) .map_with(|((name, ty), init), e| ParsedStmt { span: e.span(), @@ -203,20 +202,67 @@ where parsed_expr_parser() .separated_by(just(Token::Comma)) .at_least(1) - .collect::>(), + .allow_trailing() + .collect::>() + .delimited_by(just(Token::LParen), just(Token::RParen)), ) .then( - match_arm + case_arm .repeated() - .at_least(1) .collect::>() + .then(default_arm.or_not()) .delimited_by(just(Token::LBrace), just(Token::RBrace)), ) - .map_with(|(scrutinees, arms), e| ParsedStmt { - span: e.span(), - kind: ParsedStmtKind::Match { scrutinees, arms }, + .validate(|(scrutinees, (case_arms, default_arm)), e, emitter| { + if case_arms.is_empty() && default_arm.is_none() { + emitter.emit(Rich::custom( + e.span(), + "match requires at least one `case` or `default` arm", + )); + } + + let arity = scrutinees.len(); + let mut arms = + Vec::with_capacity(case_arms.len() + usize::from(default_arm.is_some())); + for (span, pat, body) in case_arms { + let pats = if arity > 1 { + match pat { + ParsedPat { + kind: ParsedPatKind::Tuple(pats), + .. + } => pats, + pat => vec![pat], + } + } else { + vec![pat] + }; + if pats.len() != arity { + emitter.emit(Rich::custom( + span, + format!( + "match has {arity} scrutinees but this case has {} patterns", + pats.len() + ), + )); + } + arms.push(ParsedMatchArm { span, pats, body }); + } + + if let Some((span, body)) = default_arm { + let pats = (0..arity) + .map(|_| ParsedPat { + span, + kind: ParsedPatKind::Wildcard, + }) + .collect(); + arms.push(ParsedMatchArm { span, pats, body }); + } + + ParsedStmt { + span: e.span(), + kind: ParsedStmtKind::Match { scrutinees, arms }, + } }) - .then_ignore(just(Token::Semi).or_not()) .boxed(); let for_item = parsed_for_let_parser() @@ -253,8 +299,31 @@ where }) .boxed(); + let while_stmt = while_kw_parser() + .ignore_then( + parsed_expr_parser().delimited_by(just(Token::LParen), just(Token::RParen)), + ) + .then( + stmt.clone() + .repeated() + .collect::>() + .delimited_by(just(Token::LBrace), just(Token::RBrace)), + ) + .map_with(|(cond, body), e| ParsedStmt { + span: e.span(), + kind: ParsedStmtKind::For { + init: Vec::new(), + cond, + post: Vec::new(), + body, + }, + }) + .boxed(); + let if_stmt = just(Token::If) - .ignore_then(parsed_expr_parser()) + .ignore_then( + parsed_expr_parser().delimited_by(just(Token::LParen), just(Token::RParen)), + ) .then( stmt.clone() .repeated() @@ -331,7 +400,7 @@ where } ParsedStmt { span: e.span(), - kind: assign_stmt_kind(lhs, tail), + kind: assign_stmt_kind(lhs, tail, semi.is_some()), } }) .boxed(); @@ -341,6 +410,7 @@ where return_stmt, match_stmt, for_stmt, + while_stmt, if_stmt, assembly_stmt, block_stmt, diff --git a/crates/parser/src/parse/types.rs b/crates/parser/src/parse/types.rs index 4478dfec..3f5b63c5 100644 --- a/crates/parser/src/parse/types.rs +++ b/crates/parser/src/parse/types.rs @@ -8,18 +8,19 @@ where I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, { recursive(|ty| { - let args = ty + let angle_args = ty .clone() .separated_by(just(Token::Comma)) + .at_least(1) .allow_trailing() .collect::>() - .delimited_by(just(Token::LParen), just(Token::RParen)) + .delimited_by(just(Token::Less), just(Token::Greater)) .map_with(|args, e| (args, e.span())) .or_not() .boxed(); let named_type = qualified_ident_parser() - .then(args) + .then(angle_args) .map_with(|(mut path, args), e| { let name = path.pop().expect("qualified path has at least one segment"); let (args, args_span) = args @@ -35,6 +36,38 @@ where }, } }) + .validate(|ty, _, emitter| { + if let ParsedTyKind::Named { + qualifiers, + name: ("mapping", _), + .. + } = &ty.kind + && qualifiers.is_empty() + { + emitter.emit(Rich::custom( + ty.span, + "the `mapping` type uses `mapping(Key => Value)`", + )); + } + ty + }) + .boxed(); + + let mapping_type = mapping_kw_parser() + .then_ignore(just(Token::LParen)) + .then(ty.clone()) + .then_ignore(just(Token::FatArrow)) + .then(ty.clone()) + .then_ignore(just(Token::RParen)) + .map_with(|((mapping, key), value), e| ParsedTy { + span: e.span(), + kind: ParsedTyKind::Named { + qualifiers: Vec::new(), + name: ("mapping", mapping), + args: vec![key, value], + args_span: Some(e.span()), + }, + }) .boxed(); let paren_types = ty @@ -47,7 +80,9 @@ where .boxed(); let comptime_type = comptime_kw_parser() + .then_ignore(just(Token::Less)) .then(ty.clone()) + .then_ignore(just(Token::Greater)) .map_with(|(kw, inner), e| ParsedTy { span: e.span(), kind: ParsedTyKind::Comptime { @@ -57,49 +92,74 @@ where }) .boxed(); - let tuple_type = paren_types - .map(|(elems, paren_span)| ParsedTy { - span: paren_span, - kind: ParsedTyKind::Tuple { elems }, + let function_params = ty + .clone() + .separated_by(just(Token::Comma)) + .allow_trailing() + .collect::>() + .delimited_by(just(Token::LParen), just(Token::RParen)) + .map_with(|params, e| (params, e.span())) + .boxed(); + let function_ret = ty + .clone() + .separated_by(just(Token::Comma)) + .allow_trailing() + .collect::>() + .delimited_by(just(Token::LParen), just(Token::RParen)) + .map_with(|elems, e| match <[_; 1]>::try_from(elems) { + Ok([elem]) => elem, + Err(elems) => ParsedTy { + span: e.span(), + kind: ParsedTyKind::Tuple { elems }, + }, }) .boxed(); - - let atom_type = recursive(|atom| { - let proxy_type = just(Token::At) - .map_with(|_, e| e.span()) - .then(atom) - .map_with(|(at, inner), e| ParsedTy { + let function_type = just(Token::Function) + .ignore_then(function_params) + .then(returns_kw_parser().ignore_then(function_ret).or_not()) + .map_with(|((params, params_span), ret), e| { + let ret = ret.unwrap_or_else(|| ParsedTy { span: e.span(), - kind: ParsedTyKind::Proxy { - at, - inner: Box::new(inner), - }, - }) - .boxed(); - - proxy_type.or(tuple_type).or(named_type) - }) - .boxed(); - - let atom_type = comptime_type.or(atom_type).boxed(); - - atom_type - .clone() - .then(just(Token::Arrow).ignore_then(ty.clone()).or_not()) - .map_with(|(domain, ret), e| match ret { - Some(ret) => ParsedTy { + kind: ParsedTyKind::Tuple { elems: Vec::new() }, + }); + ParsedTy { span: e.span(), - // Arrow types are right-associative over atom domains. - // A parenthesized tuple domain remains one unary domain, - // matching the Haskell reference parser. kind: ParsedTyKind::Fn { - params_span: domain.span, - params: vec![domain], + params, + params_span, ret: Box::new(ret), }, + } + }) + .boxed(); + + let tuple_type = paren_types + .map(|(elems, paren_span)| ParsedTy { + span: paren_span, + kind: ParsedTyKind::Tuple { elems }, + }) + .boxed(); + + let proxy_type = just(Token::At) + .map_with(|_, e| e.span()) + .then(ty.clone()) + .map_with(|(at, inner), e| ParsedTy { + span: e.span(), + kind: ParsedTyKind::Proxy { + at, + inner: Box::new(inner), }, - None => domain, }) + .boxed(); + + choice(( + function_type, + comptime_type, + mapping_type, + proxy_type, + tuple_type, + named_type, + )) }) .labelled("type") .as_context() @@ -118,9 +178,10 @@ where { let class_args = type_parser() .separated_by(just(Token::Comma)) + .at_least(1) .allow_trailing() .collect::>() - .delimited_by(just(Token::LParen), just(Token::RParen)) + .delimited_by(just(Token::Less), just(Token::Greater)) .map_with(|args, e| (args, e.span())) .or_not() .boxed(); @@ -152,6 +213,7 @@ where { let bare = pred_parser() .separated_by(just(Token::Comma)) + .at_least(1) .allow_trailing() .collect::>() .boxed(); @@ -159,100 +221,3 @@ where .delimited_by(just(Token::LParen), just(Token::RParen)) .or(bare) } - -#[derive(Debug, Clone)] -enum ParsedForallBinder<'src> { - Var(SpannedStr<'src>), - Bound { - var: SpannedStr<'src>, - pred: ParsedPred<'src>, - }, -} - -fn forall_binder_parser<'src, I>() -> impl Parser<'src, I, ParsedForallBinder<'src>, ParserErr<'src>> -where - I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, -{ - let class_args = type_parser() - .separated_by(just(Token::Comma)) - .allow_trailing() - .collect::>() - .delimited_by(just(Token::LParen), just(Token::RParen)) - .map_with(|args, e| (args, e.span())) - .or_not() - .boxed(); - - let bounded = ident_parser() - .then_ignore(just(Token::Colon)) - .then(ident_parser()) - .then(class_args) - .map(|((var, class), args)| { - let (args, args_span) = args - .map(|(args, span)| (args, Some(span))) - .unwrap_or_else(|| (Vec::new(), None)); - let ty = ParsedTy { - span: var.1, - kind: ParsedTyKind::Named { - qualifiers: Vec::new(), - name: var, - args: Vec::new(), - args_span: None, - }, - }; - let pred = ParsedPred { - ty, - class, - args, - args_span, - }; - ParsedForallBinder::Bound { var, pred } - }); - - let bare = ident_parser().map(ParsedForallBinder::Var); - - choice((bounded, bare)) -} - -pub(super) fn forall_clause_parser<'src, I>() --> impl Parser<'src, I, (Vec>, Vec>), ParserErr<'src>> -where - I: ValueInput<'src, Token = Token<'src>, Span = LexSpan>, -{ - let binder = forall_binder_parser().boxed(); - let binders = binder - .clone() - .then( - just(Token::Comma) - .or_not() - .ignore_then(binder) - .repeated() - .collect::>(), - ) - .map(|(first, mut rest)| { - let mut all = Vec::with_capacity(rest.len() + 1); - all.push(first); - all.append(&mut rest); - all - }); - - just(Token::Forall) - .ignore_then(binders) - .then_ignore(just(Token::Dot)) - .or_not() - .map(|binders| { - let mut type_vars = Vec::new(); - let mut preds = Vec::new(); - if let Some(binders) = binders { - for binder in binders { - match binder { - ParsedForallBinder::Var(var) => type_vars.push(var), - ParsedForallBinder::Bound { var, pred } => { - type_vars.push(var); - preds.push(pred); - } - } - } - } - (type_vars, preds) - }) -} diff --git a/crates/parser/src/parse/yul.rs b/crates/parser/src/parse/yul.rs index 682a75a5..4c885edf 100644 --- a/crates/parser/src/parse/yul.rs +++ b/crates/parser/src/parse/yul.rs @@ -12,6 +12,9 @@ where select! { Token::YulIdent(name) => name, Token::Underscore => "_", + // `fallback` is reserved by the Core surface, not by Yul. Keep + // the two identifier grammars independent inside assembly. + Token::Fallback => "fallback", } .map_with(|name, e| (name, e.span())), )) diff --git a/crates/parser/src/types.rs b/crates/parser/src/types.rs index baf6e3b1..24a352fc 100644 --- a/crates/parser/src/types.rs +++ b/crates/parser/src/types.rs @@ -93,21 +93,21 @@ pub(crate) struct ParseOutput { pub(crate) errors: Vec, } -/// One class named by a `derive` attribute. +/// One trait named by a `derive` attribute. #[derive(Debug, Clone)] pub(crate) struct ParsedDeriveTarget<'src> { - /// Span covering the complete possibly-qualified class path. + /// Span covering the complete possibly-qualified trait path. pub(crate) span: LexSpan, - /// Class path segments in source order. + /// Trait path segments in source order. pub(crate) path: Vec>, } -/// Parsed `#[derive(...)]` attribute attached to a data declaration. +/// Parsed `#[derive(...)]` attribute attached to an enum declaration. #[derive(Debug, Clone)] pub(crate) struct ParsedDeriveAttr<'src> { /// Span covering the complete attribute, from `#` through `]`. pub(crate) span: LexSpan, - /// Classes requested by the attribute, in source order. + /// Traits requested by the attribute, in source order. pub(crate) targets: Vec>, } @@ -164,13 +164,13 @@ pub(crate) enum ParsedTopItem<'src> { /// Aliased type. ty: ParsedTy<'src>, }, - /// Algebraic data type declaration. + /// Enum/algebraic data type declaration. Adt { /// Span covering the declaration. span: LexSpan, /// Consecutive comments directly preceding the declaration. leading_comments: Vec>, - /// Optional derive attribute preceding `data`. + /// Optional derive attribute preceding `enum`. derive_attr: Option>, /// Type name. name: SpannedStr<'src>, @@ -179,13 +179,13 @@ pub(crate) enum ParsedTopItem<'src> { /// Constructors. ctors: Vec>, }, - /// Class declaration. + /// Trait declaration, lowered to the existing class representation. Class { /// Span covering the declaration. span: LexSpan, /// Consecutive comments directly preceding the declaration. leading_comments: Vec>, - /// Type variables introduced by `forall`. + /// Type variables declared by the trait's generic parameter list. type_vars: Vec>, /// Superclass predicates. super_preds: Vec>, @@ -194,13 +194,13 @@ pub(crate) enum ParsedTopItem<'src> { /// Method signature declarations. methods: Vec>, }, - /// Instance declaration. + /// Impl declaration, lowered to the existing instance representation. Instance { /// Span covering the declaration. span: LexSpan, /// Consecutive comments directly preceding the declaration. leading_comments: Vec>, - /// Type variables introduced by `forall`. + /// Type variables declared by the impl's generic parameter list. type_vars: Vec>, /// Context predicates. preds: Vec>, @@ -431,7 +431,7 @@ pub(crate) enum ParsedFuncParam<'src> { pub(crate) struct ParsedFuncSig<'src> { /// Span covering the signature. pub(crate) span: LexSpan, - /// Type variables from `forall`. + /// Type variables from the angle-bracket generic parameter list. pub(crate) type_vars: Vec>, /// Qualifying predicates. pub(crate) preds: Vec>, @@ -445,7 +445,8 @@ pub(crate) struct ParsedFuncSig<'src> { pub(crate) params: Vec>, /// Span of the parameter list. pub(crate) params_span: LexSpan, - /// Optional return type. + /// Return type for an ordinary function, including explicit unit when + /// `returns` is omitted; absent only for constructor/fallback signatures. pub(crate) ret: Option>, } @@ -497,13 +498,13 @@ pub(crate) enum ParsedContractItem<'src> { /// Aliased type. ty: ParsedTy<'src>, }, - /// Contract-local ADT. + /// Contract-local enum/ADT. Adt { /// Span covering the declaration. span: LexSpan, /// Consecutive comments directly preceding the declaration. leading_comments: Vec>, - /// Optional derive attribute preceding `data`. + /// Optional derive attribute preceding `enum`. derive_attr: Option>, /// ADT name. name: SpannedStr<'src>, @@ -605,13 +606,6 @@ pub(crate) enum ParsedExprKind<'src> { /// Field name. field: SpannedStr<'src>, }, - /// Type annotation expression. - TypeAnnot { - /// Annotated expression. - expr: Box>, - /// Annotation type. - ty: ParsedTy<'src>, - }, /// Unary operator expression. UnaryOp { /// Operator and span. @@ -738,7 +732,12 @@ pub(crate) enum ParsedStmtKind<'src> { /// Return statement. Return(Option>), /// Expression statement. - Expr(ParsedExpr<'src>), + Expr { + /// Expression payload. + expr: ParsedExpr<'src>, + /// Whether the source expression was followed by `;`. + trailing_semi: bool, + }, /// Assignment. Assign { /// Assignment operator. diff --git a/crates/parser/tests/def_identity.rs b/crates/parser/tests/def_identity.rs index 7c4fccff..0c87da73 100644 --- a/crates/parser/tests/def_identity.rs +++ b/crates/parser/tests/def_identity.rs @@ -37,7 +37,7 @@ struct DefIdentity { } fn source_file(db: &TestDb, name: &str, src: &str) -> SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid url"); + let url = format!("memory:///{name}.sol").parse().expect("valid url"); SourceFile::new(db, url, Some(src.to_owned())) } @@ -122,9 +122,9 @@ fn instances_of_same_class_on_different_heads_have_distinct_def_ids() { let file = source_file( &db, "instance-heads", - "class self:StorageType {}\n\n\ - instance word:StorageType {\n function rep(x:word) -> word { return x; }\n}\n\n\ - instance uint:StorageType {\n function rep(x:uint) -> uint { return x; }\n}\n", + "trait StorageType {}\n\n\ + impl StorageType {\n function rep(x:word) returns (word) { return x; }\n}\n\n\ + impl StorageType {\n function rep(x:uint) returns (uint) { return x; }\n}\n", ); let instances = defs_by_name(&db, file, DefKind::Instance, "StorageType"); @@ -145,9 +145,9 @@ fn instances_with_same_subject_and_different_class_args_have_distinct_def_ids() let file = source_file( &db, "instance-class-args", - "class self:Carrier(arg) {}\n\n\ - instance word:Carrier(uint) {}\n\n\ - instance word:Carrier(bool) {}\n", + "trait Carrier {}\n\n\ + impl Carrier {}\n\n\ + impl Carrier {}\n", ); let instances = defs_by_name(&db, file, DefKind::Instance, "Carrier"); @@ -214,11 +214,11 @@ fn import_selector_fingerprints_are_structural_and_order_independent() { let file = source_file( &db, "imports-selector-fingerprints", - "import A.{x as y, (^^)} hiding {z, w};\n\ - import A.{(^^), x as y} hiding {w, z};\n\ - import A.{x};\n\ - import A.{x as y};\n\ - import A.{*};\n", + "import {x as y, (^^)} from A hiding {z, w};\n\ + import {(^^), x as y} from A hiding {w, z};\n\ + import {x} from A;\n\ + import {x as y} from A;\n\ + import * from A;\n", ); let mut fingerprints = all_defs(&db, file) @@ -243,7 +243,7 @@ fn import_selector_fingerprints_are_structural_and_order_independent() { #[test] fn inserting_preceding_lambda_keeps_existing_lambda_body_identities_stable() { let mut db = TestDb::default(); - let before_src = "function f(z: word) -> word { + let before_src = "function f(z: word) returns (word) { let n = lam (x: word) { return x; }; let m = lam (y: word) { return y; }; return m(n(z)); @@ -254,7 +254,7 @@ fn inserting_preceding_lambda_keeps_existing_lambda_body_identities_stable() { assert_eq!(before.len(), 2); file.set_content(&mut db).to(Some( - "function f(z: word) -> word { + "function f(z: word) returns (word) { let ignored = lam (q: word) { return q + 1; }; let n = lam (x: word) { return x; }; let m = lam (y: word) { return y; }; @@ -280,7 +280,7 @@ fn inserting_preceding_lambda_keeps_existing_lambda_body_identities_stable() { #[test] fn lambda_body_edit_keeps_lambda_body_identity_stable() { let mut db = TestDb::default(); - let before_src = "function f(z: word) -> word { + let before_src = "function f(z: word) returns (word) { let n = lam (x: word) { return x + 1; }; return n(z); }"; @@ -290,7 +290,7 @@ fn lambda_body_edit_keeps_lambda_body_identity_stable() { assert_eq!(before.len(), 1); file.set_content(&mut db).to(Some( - "function f(z: word) -> word { + "function f(z: word) returns (word) { let n = lam (x: word) { return x + 2; }; return n(z); }" @@ -355,9 +355,9 @@ fn well_formed_program_defs_have_zero_disambiguators() { let file = source_file( &db, "zero-disambiguators", - "class self:StorageType {}\n\n\ - instance word:StorageType {\n function rep(x:word) -> word { return x; }\n}\n\n\ - contract Counter {\n function main() -> word { return 0; }\n}\n\n\ + "trait StorageType {}\n\n\ + impl StorageType {\n function rep(x:word) returns (word) { return x; }\n}\n\n\ + contract Counter {\n function main() returns (word) { return 0; }\n}\n\n\ function top() {}\n", ); diff --git a/crates/parser/tests/diagnostics.rs b/crates/parser/tests/diagnostics.rs index f07c7f6c..5c98a4b4 100644 --- a/crates/parser/tests/diagnostics.rs +++ b/crates/parser/tests/diagnostics.rs @@ -33,7 +33,7 @@ impl solcore_parser::Db for TestDb {} #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/corpus/fail", - glob: "**/*.solc" + glob: "**/*.sol" )] fn parser_corpus_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_assertion(fixture, assert_fail_fixture); @@ -55,7 +55,7 @@ fn assert_fail_fixture(path: &str, content: &str) { return; } - if path.ends_with("multiple_emitted_errors.solc") { + if path.ends_with("multiple_emitted_errors.sol") { assert!( diagnostics.len() > 1, "expected more than one diagnostic for `{}`", @@ -69,7 +69,7 @@ fn assert_fail_fixture(path: &str, content: &str) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/ok", - glob: "**/*.solc" + glob: "**/*.sol" )] fn parser_ok_no_diagnostics(fixture: Fixture<&str>) { run_fixture_assertion(fixture, assert_ok_fixture); @@ -77,7 +77,7 @@ fn parser_ok_no_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/corpus/ok", - glob: "**/*.solc" + glob: "**/*.sol" )] fn parser_corpus_ok_no_diagnostics(fixture: Fixture<&str>) { run_fixture_assertion(fixture, assert_ok_fixture); @@ -122,7 +122,7 @@ fn fixture_source_file(db: &TestDb, path: &str, content: &str) -> SourceFile { let file_name = fixture_path .file_name() .and_then(|name| name.to_str()) - .unwrap_or("fixture.solc"); + .unwrap_or("fixture.sol"); let url = format!("memory:///{file_name}") .parse() .expect("valid fixture URL"); diff --git a/crates/parser/tests/incremental_spans.rs b/crates/parser/tests/incremental_spans.rs index b66b1f3f..fe2f4857 100644 --- a/crates/parser/tests/incremental_spans.rs +++ b/crates/parser/tests/incremental_spans.rs @@ -200,7 +200,7 @@ fn nested_item_defs<'db>( #[test] fn top_level_error_item_has_recovery_span() { let db = TestDb::default(); - let url = "memory:///recovery.solc".parse().expect("valid url"); + let url = "memory:///recovery.sol".parse().expect("valid url"); let src = "function first() {}\nunknown nonsense tokens\nfunction second() {}\n"; let file = SourceFile::new(&db, url, Some(src.to_owned())); From 684d4ee70f3c12380dd6030d9b6cc5dc9a8e85d7 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 046/110] Switch the compiler and fixtures to canonical syntax: parser Co-authored-by: Codex --- crates/parser/tests/incremental_spans.rs | 40 ++- crates/parser/tests/lowering_regressions.rs | 359 +++++++++++++++----- crates/parser/tests/nameres.rs | 153 +++++---- crates/parser/tests/properties.rs | 16 +- crates/parser/tests/reserved_words.rs | 83 +++++ 5 files changed, 471 insertions(+), 180 deletions(-) create mode 100644 crates/parser/tests/reserved_words.rs diff --git a/crates/parser/tests/incremental_spans.rs b/crates/parser/tests/incremental_spans.rs index fe2f4857..11912195 100644 --- a/crates/parser/tests/incremental_spans.rs +++ b/crates/parser/tests/incremental_spans.rs @@ -222,8 +222,8 @@ fn top_level_error_item_has_recovery_span() { #[test] fn relative_span_query_backdates_after_edit_above_def() { let mut db = TestDb::default(); - let url = "memory:///incr.solc".parse().expect("valid url"); - let src = "function id(x: word) -> word {\n return x;\n}\n"; + let url = "memory:///incr.sol".parse().expect("valid url"); + let src = "function id(x: word) returns (word) {\n return x;\n}\n"; let file = SourceFile::new(&db, url, Some(src.to_owned())); // Baseline: execute the semantic-style query once, then drop all `'db` @@ -268,11 +268,11 @@ fn relative_span_query_backdates_after_edit_above_def() { #[test] fn editing_leading_comment_invalidates_only_comment_consumers() { let mut db = TestDb::default(); - let url = "memory:///comment-incr.solc".parse().expect("valid url"); + let url = "memory:///comment-incr.sol".parse().expect("valid url"); let file = SourceFile::new( &db, url, - Some("// one\nfunction id(x: word) -> word { return x; }\n".to_owned()), + Some("// one\nfunction id(x: word) returns (word) { return x; }\n".to_owned()), ); let (before_identity, before_span) = { @@ -292,7 +292,7 @@ fn editing_leading_comment_invalidates_only_comment_consumers() { }; file.set_content(&mut db).to(Some( - "// two\nfunction id(x: word) -> word { return x; }\n".to_owned(), + "// two\nfunction id(x: word) returns (word) { return x; }\n".to_owned(), )); let function = first_function(&db, file); @@ -317,15 +317,16 @@ fn editing_leading_comment_invalidates_only_comment_consumers() { #[test] fn editing_nested_item_comments_preserves_semantic_fields() { let mut db = TestDb::default(); - let url = "memory:///nested-comment-incr.solc" + let url = "memory:///nested-comment-incr.sol" .parse() .expect("valid url"); - let before_src = "data Choice = + let before_src = "enum Choice { // alpha - First; -class a:Documented { + First +} +trait Documented { // alpha - function describe(x: a) -> word; + function describe(x: a) returns (word); } contract C { // alpha @@ -364,12 +365,13 @@ contract C { // Keep the payload byte length unchanged so every nested declaration keeps // the same owner-relative span. Only the parallel comment fields change. file.set_content(&mut db).to(Some( - "data Choice = + "enum Choice { // bravo - First; -class a:Documented { + First +} +trait Documented { // bravo - function describe(x: a) -> word; + function describe(x: a) returns (word); } contract C { // bravo @@ -401,8 +403,10 @@ contract C { #[test] fn lambda_body_relative_span_backdates_after_cosmetic_signature_edit() { let mut db = TestDb::default(); - let url = "memory:///lambda-incr.solc".parse().expect("valid url"); - let before_src = "function make(z: word) -> word { + let url = "memory:///lambda-incr.sol".parse().expect("valid url"); + // `->` remains the canonical result annotation for lambdas; only named + // function declarations moved to `returns (...)`. + let before_src = "function make(z: word) returns (word) { let n = lam (x: word) -> word { return x; }; @@ -421,7 +425,7 @@ fn lambda_body_relative_span_backdates_after_cosmetic_signature_edit() { }; file.set_content(&mut db).to(Some( - "function make(z: word) -> word { + "function make(z: word) returns (word) { let n = lam ( x /* same binder */ : /* same parameter type */ word ) -> /* same return type */ word { @@ -445,7 +449,7 @@ fn lambda_body_relative_span_backdates_after_cosmetic_signature_edit() { assert_eq!(after_cosmetic_fact, before_fact); file.set_content(&mut db).to(Some( - "function make(z: word) -> word { + "function make(z: word) returns (word) { let n = lam (x: uint) -> word { return x; }; diff --git a/crates/parser/tests/lowering_regressions.rs b/crates/parser/tests/lowering_regressions.rs index b0fb9929..4346d94b 100644 --- a/crates/parser/tests/lowering_regressions.rs +++ b/crates/parser/tests/lowering_regressions.rs @@ -34,7 +34,7 @@ impl hir::Db for TestDb { impl solcore_parser::Db for TestDb {} fn source_file(db: &TestDb, name: &str, src: &str) -> SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid url"); + let url = format!("memory:///{name}.sol").parse().expect("valid url"); SourceFile::new(db, url, Some(src.to_owned())) } @@ -119,6 +119,8 @@ fn block_comments_do_not_swallow_following_items_and_unterminated_comments_diagn #[test] fn function_hir_retains_only_directly_leading_source_comments() { let db = TestDb::default(); + // The arrow-like text below is comment payload under test, not a legacy + // function result annotation. let (_, module) = parse_module( &db, "function-comments", @@ -127,7 +129,7 @@ contract C { // ordinary documentation // #[(0, 1) -> 1] /* block /* nested */ documentation */ - public function add(x: word, y: word) -> word { return x; } + function add(x: word, y: word) public returns (word) { return x; } function body_comment() { // this belongs to the body @@ -192,20 +194,21 @@ export dependency; pragma feature Example; // top alias type Alias = word; -// top data -data TopData = // first constructor after equals +// top enum +enum TopData { // first constructor after opening brace First // second constructor before separator - | Second; -// top class -class a:Documented { - // class method - function describe(x: a) -> word; + , Second } -// top instance -instance word:Documented { - // instance method - function describe(x: word) -> word { return x; } +// top trait +trait Documented { + // trait method + function describe(x: a) returns (word); +} +// top impl +impl Documented { + // impl method + function describe(x: word) returns (word) { return x; } } // top contract contract C { @@ -213,18 +216,19 @@ contract C { value: word; // contract alias type LocalAlias = word; - // contract data - data LocalData = + // contract enum + enum LocalData { // local first constructor LocalFirst - | // local second constructor after separator - LocalSecond; + , // local second constructor after separator + LocalSecond + } // contract constructor constructor() {} // contract fallback - fallback() -> () {} + fallback() {} // contract function - function get() -> word { return value; } + function get() returns (word) { return value; } } // top function function top() {} @@ -241,9 +245,9 @@ function top() {} " top export", " top pragma", " top alias", - " top data", - " top class", - " top instance", + " top enum", + " top trait", + " top impl", " top contract", " top function", ]; @@ -263,7 +267,7 @@ function top() {} assert_eq!(top_adt.ctors_with_comments(&db).len(), 2); assert_comment_texts( top_adt.ctor_leading_comments(&db, 0).expect("first ctor"), - &[" first constructor after equals"], + &[" first constructor after opening brace"], ); assert_comment_texts( top_adt.ctor_leading_comments(&db, 1).expect("second ctor"), @@ -281,7 +285,7 @@ function top() {} assert_eq!(class.methods_with_comments(&db).len(), 1); assert_comment_texts( class.method_leading_comments(&db, 0).expect("class method"), - &[" class method"], + &[" trait method"], ); let instance = module @@ -294,7 +298,7 @@ function top() {} .expect("instance"); assert_comment_texts( instance.methods(&db)[0].leading_comments(&db), - &[" instance method"], + &[" impl method"], ); let contract = module @@ -315,7 +319,7 @@ function top() {} let expected_contract_item_comments = [ " contract alias", - " contract data", + " contract enum", " contract constructor", " contract fallback", " contract function", @@ -363,13 +367,13 @@ fn item_comments_do_not_cross_blank_lines_trailing_code_or_bodies() { "item-comment-boundaries", r#" type Owner = word; // trailing top-level comment -data AfterTrailing; +enum AfterTrailing {} // separated top-level comment -class a:Boundary { +trait Boundary { // separated method comment - function method(x: a) -> word; + function method(x: a) returns (word); } contract C { first: word; // trailing field comment @@ -377,12 +381,13 @@ contract C { // separated field comment second: word; - data Nested = First // trailing constructor comment - | Second - // separated from the constructor name by a blank line after `|` - | + enum Nested { First // trailing constructor comment + , Second + // separated from the constructor name by a blank line after `,` + , - Third; + Third + } function body_owner() { // body-only comment } @@ -507,11 +512,11 @@ fn equivalent_type_and_predicate_refs_share_semantic_shapes_without_sharing_occu let (_, module) = parse_module( &db, "type-ref-shapes", - "class self:C {} + "trait C {} function a(x: word) {} function b(y: word) {} - forall t . t:C => function c(x: t) {} - forall t . t:C => function d(x: t) {}", + function c(x: t) where t:C {} + function d(x: t) where t:C {}", ); let a = top_function(&db, module, "a"); @@ -536,13 +541,15 @@ fn equivalent_type_and_predicate_refs_share_semantic_shapes_without_sharing_occu } #[test] -fn implicit_return_applies_to_function_definitions_but_not_lambdas() { +fn implicit_return_applies_only_to_named_function_tail_expressions() { let db = TestDb::default(); let (_, module) = parse_module( &db, "implicit-return", - "function id(x: word) -> word { x } - function make() { return lam (x: word) { x }; }", + "function id(x: word) returns (word) { x } + function sequence(x: word) returns (word) { let copy = x; copy } + function discarded(x: word) { x; } + function make() returns (function(word)) { return lam (x: word) { return x; }; }", ); let id = top_function(&db, module, "id"); @@ -550,6 +557,22 @@ fn implicit_return_applies_to_function_definitions_but_not_lambdas() { let id_stmt = id_body.stmts(&db).get(id_body.top_level_stmts(&db)[0]); assert!(matches!(&id_stmt.kind, StmtKind::Return(_))); + let sequence = top_function(&db, module, "sequence"); + let sequence_body = sequence.body(&db).expect("body"); + let sequence_stmts = sequence_body.top_level_stmts(&db); + assert_eq!(sequence_stmts.len(), 2); + assert!(matches!( + &sequence_body.stmts(&db).get(sequence_stmts[1]).kind, + StmtKind::Return(_) + )); + + let discarded = top_function(&db, module, "discarded"); + let discarded_body = discarded.body(&db).expect("body"); + let discarded_stmt = discarded_body + .stmts(&db) + .get(discarded_body.top_level_stmts(&db)[0]); + assert!(matches!(&discarded_stmt.kind, StmtKind::Expr(_))); + let make = top_function(&db, module, "make"); let make_body = make.body(&db).expect("body"); let lambda_body = make_body @@ -563,7 +586,147 @@ fn implicit_return_applies_to_function_definitions_but_not_lambdas() { let lambda_stmt = lambda_body .stmts(&db) .get(lambda_body.top_level_stmts(&db)[0]); - assert!(matches!(&lambda_stmt.kind, StmtKind::Expr(_))); + assert!(matches!(&lambda_stmt.kind, StmtKind::Return(_))); + + let (file, _) = parse_module( + &db, + "lambda-tail-expression", + "function invalid() returns (function(word)) { return lam (x: word) { x }; }", + ); + let diagnostics = diagnostics(&db, file); + assert!( + diagnostics.iter().any(|diagnostic| diagnostic + .message + .contains("expression statement requires trailing `;`")), + "missing lambda tail-expression diagnostic: {diagnostics:#?}" + ); +} + +#[test] +fn constructor_and_fallback_tail_expressions_require_semicolons() { + let db = TestDb::default(); + let (file, _) = parse_module( + &db, + "entry-tail-expression", + "contract C { + constructor() { (); } + fallback() { () } + }", + ); + let diagnostics = diagnostics(&db, file); + assert!( + diagnostics.iter().any(|diagnostic| diagnostic + .message + .contains("expression statement requires trailing `;`")), + "missing fallback tail-expression diagnostic: {diagnostics:#?}" + ); +} + +#[test] +fn named_parameters_are_typed_while_lambda_parameters_may_be_inferred() { + let db = TestDb::default(); + let (file, module) = parse_module( + &db, + "parameter-annotations", + "function apply(value: word) returns (word) { + let identity = lam (inferred) { return inferred; }; + return identity(value); + }", + ); + assert!(diagnostics(&db, file).is_empty()); + + let apply = top_function(&db, module, "apply"); + assert!(matches!( + apply.sig(&db).params.atom().as_slice(), + [FuncParam::Typed { .. }] + )); + let body = apply.body(&db).expect("body"); + let lambda_params = body + .exprs(&db) + .iter() + .find_map(|(_, expr)| match &expr.kind { + ExprKind::Lambda { params, .. } => Some(params.atom()), + _ => None, + }) + .expect("lambda expression"); + assert!(matches!( + lambda_params.as_slice(), + [FuncParam::Untyped { comptime: None, .. }] + )); + + // These two sources intentionally omit the annotation to assert the + // canonical named-parameter rejection rule. + for (name, source) in [ + ("untyped-named-parameter", "function invalid(value) {}"), + ( + "untyped-comptime-parameter", + "function invalid(comptime value) {}", + ), + ] { + let file = source_file(&db, name, source); + assert!(diagnostics(&db, file).iter().any(|diagnostic| { + diagnostic.message == "named function parameter requires an explicit type" + })); + } +} + +#[test] +fn omitted_named_return_is_explicit_unit_even_when_the_body_returns_a_value() { + let db = TestDb::default(); + let (file, module) = parse_module( + &db, + "omitted-return-is-unit", + "function noValue() {} + function valueInBody() { return 1; } + trait UnitMethod { function unit(value: T); }", + ); + assert!(diagnostics(&db, file).is_empty()); + + for name in ["noValue", "valueInBody"] { + let ret = top_function(&db, module, name) + .sig(&db) + .ret + .expect("omitted `returns` lowers to an explicit unit type"); + assert!(matches!(ret.kind(&db), TypeRefKind::Tuple { elems } if elems.atom().is_empty())); + } + + let trait_method = module + .items(&db) + .iter() + .find_map(|item| match item { + Item::ClassDef(class) => class.methods(&db).first().cloned(), + _ => None, + }) + .expect("trait method"); + let ret = trait_method + .ret + .expect("trait method omission lowers to unit"); + assert!(matches!(ret.kind(&db), TypeRefKind::Tuple { elems } if elems.atom().is_empty())); +} + +#[test] +fn core_bindings_and_assignments_reject_yul_colon_equals() { + let db = TestDb::default(); + // These are intentional legacy-rejection probes. `:=` remains valid only + // within an `assembly` block; canonical Core uses `=`. + // syntax-migration: preserve-literals-begin + for (name, source) in [ + ( + "colon-equals-binding", + "function invalid() { let value := 1; }", + ), + ( + "colon-equals-assignment", + "function invalid() { value := 1; }", + ), + ] { + let file = source_file(&db, name, source); + assert!( + !diagnostics(&db, file).is_empty(), + "Core `:=` unexpectedly accepted in {name}" + ); + } + // syntax-migration: preserve-literals-end } #[test] @@ -630,15 +793,15 @@ function good() {}"; } #[test] -fn arrow_types_preserve_source_arity_and_explicit_tuple_domains() { +fn function_types_preserve_source_arity_and_explicit_tuple_domains() { let db = TestDb::default(); let (_, module) = parse_module( &db, - "arrow-types", - "type F = word -> word -> bool; - type G = (word, bool) -> uint; - type H = ((word, bool)) -> uint; - type I = () -> uint;", + "function-types", + "type F = function(word) returns (function(word) returns (bool)); + type G = function(word, bool) returns (uint); + type H = function((word, bool)) returns (uint); + type I = function() returns (uint);", ); let aliases = module .items(&db) @@ -651,14 +814,14 @@ fn arrow_types_preserve_source_arity_and_explicit_tuple_domains() { let f = aliases[0].ty(&db); let TypeRefKind::Fn { params, ret } = f.kind(&db) else { - panic!("F should be an arrow type"); + panic!("F should be a function type"); }; assert_eq!(params.atom().len(), 1); assert!(matches!(ret.kind(&db), TypeRefKind::Fn { .. })); let g = aliases[1].ty(&db); let TypeRefKind::Fn { params, .. } = g.kind(&db) else { - panic!("G should be an arrow type"); + panic!("G should be a function type"); }; assert_eq!(params.atom().len(), 2); assert!( @@ -670,7 +833,7 @@ fn arrow_types_preserve_source_arity_and_explicit_tuple_domains() { let h = aliases[2].ty(&db); let TypeRefKind::Fn { params, .. } = h.kind(&db) else { - panic!("H should be an arrow type"); + panic!("H should be a function type"); }; assert_eq!(params.atom().len(), 1); assert!(matches!( @@ -680,7 +843,7 @@ fn arrow_types_preserve_source_arity_and_explicit_tuple_domains() { let i = aliases[3].ty(&db); let TypeRefKind::Fn { params, .. } = i.kind(&db) else { - panic!("I should be an arrow type"); + panic!("I should be a function type"); }; assert!(params.atom().is_empty()); } @@ -688,9 +851,9 @@ fn arrow_types_preserve_source_arity_and_explicit_tuple_domains() { #[test] fn type_and_predicate_argument_list_spans_are_precise() { let db = TestDb::default(); - let src = "class self:C(arg) {} -type T = Map(word, bool); -forall t . t:C(word) => function f(x: t) {}"; + let src = "trait C {} +type T = Map; +function f(x: t) where t:C {}"; let (_, module) = parse_module(&db, "precise-type-spans", src); let alias = module @@ -705,21 +868,21 @@ forall t . t:C(word) => function f(x: t) {}"; panic!("alias target should be named"); }; let args_abs = args.span(&db).resolve_to_absolute(&db); - let expected_args_start = src.find("(word, bool)").expect("type args") as u32; + let expected_args_start = src.find("").expect("type args") as u32; assert_eq!(args_abs.start().as_u32(), expected_args_start); assert_eq!( args_abs.end().as_u32(), - expected_args_start + "(word, bool)".len() as u32 + expected_args_start + "".len() as u32 ); let function = top_function(&db, module, "f"); let pred = function.sig(&db).preds[0].kind(&db); let pred_args_abs = pred.args.span(&db).resolve_to_absolute(&db); - let expected_pred_start = src.find("(word) =>").expect("predicate args") as u32; + let expected_pred_start = src.find("").expect("predicate args") as u32; assert_eq!(pred_args_abs.start().as_u32(), expected_pred_start); assert_eq!( pred_args_abs.end().as_u32(), - expected_pred_start + "(word)".len() as u32 + expected_pred_start + "".len() as u32 ); } @@ -729,7 +892,7 @@ fn ternary_expression_lowers_to_conditional_expression() { let (_, module) = parse_module( &db, "ternary", - "function f(x: bool) -> word { return x ? 1 : 0; }", + "function f(x: bool) returns (word) { return x ? 1 : 0; }", ); let function = top_function(&db, module, "f"); let body = function.body(&db).expect("body"); @@ -743,6 +906,46 @@ fn ternary_expression_lowers_to_conditional_expression() { )); } +#[test] +fn ternary_expression_is_right_associative_and_allows_a_nested_then_arm() { + let db = TestDb::default(); + let (file, module) = parse_module( + &db, + "nested-ternary", + "function right(x: bool, y: bool) returns (word) { + return x ? 1 : y ? 2 : 3; + } + function nestedThen(x: bool, y: bool) returns (word) { + return x ? y ? 1 : 2 : 3; + }", + ); + assert!(diagnostics(&db, file).is_empty()); + + let conditional_parts = |name| { + let function = top_function(&db, module, name); + let body = function.body(&db).expect("body"); + let stmt = body.stmts(&db).get(body.top_level_stmts(&db)[0]); + let StmtKind::Return(Some(expr_id)) = &stmt.kind else { + panic!("expected return with expression"); + }; + let ExprKind::If { + then_expr, + else_expr, + .. + } = &body.exprs(&db).get(*expr_id).kind + else { + panic!("expected outer conditional expression"); + }; + ( + matches!(&body.exprs(&db).get(*then_expr).kind, ExprKind::If { .. }), + matches!(&body.exprs(&db).get(*else_expr).kind, ExprKind::If { .. }), + ) + }; + + assert_eq!(conditional_parts("right"), (false, true)); + assert_eq!(conditional_parts("nestedThen"), (true, false)); +} + #[test] fn array_literals_lower_with_empty_nested_and_postfix_index_forms() { let db = TestDb::default(); @@ -750,7 +953,7 @@ fn array_literals_lower_with_empty_nested_and_postfix_index_forms() { &db, "array-literals", r#" -function f(a: word, b: word) -> word { +function f(a: word, b: word) returns (word) { let empty = []; let nested = [[a], [b]]; return [a, b][0]; @@ -852,8 +1055,8 @@ fn compound_assignments_lower_through_binary_operator_calls() { #[test] fn derive_attributes_lower_qualified_targets_and_precise_spans() { let db = TestDb::default(); - let src = "#[derive(Eq, core.Show)] data Top(a) = Top(a);\n\ -contract C { #[derive(pkg.codec.Encode)] data Local; }"; + let src = "#[derive(Eq, core.Show)] enum Top { Top(a) }\n\ +contract C { #[derive(pkg.codec.Encode)] enum Local {} }"; let (file, module) = parse_module(&db, "derive-attributes", src); let diagnostics = diagnostics(&db, file); assert!( @@ -926,16 +1129,17 @@ contract C { #[derive(pkg.codec.Encode)] data Local; }"; #[test] fn invalid_derive_attributes_diagnose_and_keep_following_declarations() { let db = TestDb::default(); + // syntax-migration: preserve-next-literal let src = r#" -#[derive()] data Empty; -#[derive(Eq,)] data Malformed; +#[derive()] enum Empty {} +#[derive(Eq,)] enum Malformed {} #[derive(Eq)] function kept() {} -data After; +enum After {} contract C { #[derive(Eq)] field: word; #[derive(Eq)] function nested() {} - #[derive()] data EmptyLocal; - data AfterLocal; + #[derive()] enum EmptyLocal {} + enum AfterLocal {} } "#; let (file, module) = parse_module(&db, "invalid-derive-attributes", src); @@ -948,19 +1152,19 @@ contract C { messages .iter() .filter(|message| { - message.as_str() == "derive attribute requires at least one class path" + message.as_str() == "derive attribute requires at least one trait path" }) .count(), 2 ); assert!(messages.iter().any(|message| { - message == "malformed derive attribute; expected `#[derive(Class, ...)]`" + message == "malformed derive attribute; expected `#[derive(Trait, ...)]`" })); assert_eq!( messages .iter() .filter(|message| { - message.as_str() == "derive attribute is only allowed on data declarations" + message.as_str() == "derive attribute is only allowed on enum declarations" }) .count(), 3 @@ -998,7 +1202,7 @@ contract C { #[test] fn unclosed_derive_attribute_recovers_at_the_next_declaration() { let db = TestDb::default(); - let src = "#[derive(Eq)\ndata Recovered;\nfunction after() {}"; + let src = "#[derive(Eq)\nenum Recovered {}\nfunction after() {}"; let (file, module) = parse_module(&db, "unclosed-derive-attribute", src); assert!(!diagnostics(&db, file).is_empty()); assert_eq!( @@ -1017,10 +1221,10 @@ fn recovery_before_derive_preserves_top_level_and_contract_local_attributes() { let db = TestDb::default(); let src = r#" @ stray -#[derive(Eq)] data Top; +#[derive(Eq)] enum Top {} contract C { @ stray - #[derive(Ord)] data Local; + #[derive(Ord)] enum Local {} } "#; let (file, module) = parse_module(&db, "recovery-before-derive", src); @@ -1071,7 +1275,7 @@ contract C { #[test] fn derive_remains_an_ordinary_identifier_outside_attributes() { let db = TestDb::default(); - let src = "data derive; function derive() -> derive { return derive; }"; + let src = "enum derive {} function derive() returns (derive) { return derive; }"; let (file, module) = parse_module(&db, "derive-soft-keyword", src); assert!(diagnostics(&db, file).is_empty()); assert!(module.items(&db).iter().any(|item| { @@ -1083,11 +1287,12 @@ fn derive_remains_an_ordinary_identifier_outside_attributes() { #[test] fn unclosed_derive_does_not_consume_later_declarations_or_contract_fields() { let db = TestDb::default(); + // syntax-migration: preserve-next-literal let src = r#" #[derive(Eq) function kept() {} ] -data After; +enum After {} contract C { #[derive(Eq) slot: word; @@ -1116,7 +1321,7 @@ contract C { #[test] fn derive_targets_reject_reserved_identifiers() { let db = TestDb::default(); - let src = "#[derive(fallback)] data Kept;"; + let src = "#[derive(fallback)] enum Kept {}"; let (file, module) = parse_module(&db, "derive-reserved-target", src); assert!(!diagnostics(&db, file).is_empty()); module @@ -1126,5 +1331,5 @@ fn derive_targets_reject_reserved_identifiers() { Item::AdtDef(adt) => Some(*adt), _ => None, }) - .expect("data declaration survives malformed attribute"); + .expect("enum declaration survives malformed attribute"); } diff --git a/crates/parser/tests/nameres.rs b/crates/parser/tests/nameres.rs index 6ef712a0..bf4d6a5f 100644 --- a/crates/parser/tests/nameres.rs +++ b/crates/parser/tests/nameres.rs @@ -36,7 +36,7 @@ impl hir::Db for TestDb { impl solcore_parser::Db for TestDb {} fn source_file(db: &TestDb, name: &str, src: &str) -> SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid url"); + let url = format!("memory:///{name}.sol").parse().expect("valid url"); SourceFile::new(db, url, Some(src.to_owned())) } @@ -216,9 +216,9 @@ fn derive_targets_resolve_in_source_order_for_top_level_and_contract_adts() { let db = TestDb::default(); let module = parse_module( &db, - "class a:Eq {}\n\ - #[derive(Eq, Eq)] data Top;\n\ - contract C { #[derive(Eq)] data Local; }", + "trait Eq {}\n\ + #[derive(Eq, Eq)] enum Top {}\n\ + contract C { #[derive(Eq)] enum Local {} }", ); let resolution = resolve_module(&db, module); assert!(resolution.diagnostics.is_empty()); @@ -249,7 +249,7 @@ fn derive_targets_report_unknown_and_wrong_kind_names() { let db = TestDb::default(); let module = parse_module( &db, - "data NotAClass; #[derive(Missing, NotAClass)] data Target;", + "enum NotAClass {} #[derive(Missing, NotAClass)] enum Target {}", ); let resolution = resolve_module(&db, module); let undefined = resolution @@ -273,7 +273,7 @@ fn derive_targets_report_unknown_and_wrong_kind_names() { #[test] fn qualified_derive_target_uses_the_exact_imported_class_path() { let db = TestDb::default(); - let module = parse_module(&db, "class a:Eq {} #[derive(pkg.Eq)] data Target;"); + let module = parse_module(&db, "trait Eq {} #[derive(pkg.Eq)] enum Target {}"); let class = module .items(&db) .iter() @@ -301,38 +301,39 @@ fn parse_recovery_suppression_policy_silences_name_lookup_cascades() { let cases = [ ( "body_expr_error", - "function f() -> word { + "function f() returns (word) { let x = ; return missing; }", ), ( "lost_function_signature", - "lost(x: word) -> word { return 0; } - function caller() -> word { return lost(0); }", + // syntax-migration: preserve-next-literal + "lost(x: word) returns (word) { return 0; } + function caller() returns (word) { return lost(0); }", ), ( "broken_import", "impoort util; - function caller() -> word { return missing; }", + function caller() returns (word) { return missing; }", ), ( "broken_type_annotation", "typeish Alias = word; - function caller(x: Alias) -> word { return 0; }", + function caller(x: Alias) returns (word) { return 0; }", ), ( "top_level_item_error", "function first() {} unknown nonsense tokens function second() {} - function caller() -> word { return missing; }", + function caller() returns (word) { return missing; }", ), ( "broken_contract_member", "contract C { broken : - function get() -> word { return broken; } + function get() returns (word) { return broken; } }", ), ]; @@ -377,18 +378,18 @@ fn undefined_name_kind_distinguishes_bare_terms_from_path_lookups() { let (file, module) = parse_and_module( &db, "undefined_name_kinds", - "data Local = Present; - function bare() -> word { return missing; } - function qualified() -> word { return math.value(); } - function ctorExpr() -> word { return Option.Some(0); } - function ctorPat(x: word) -> word { - match x { - | Option.Some(y) => return y; - | _ => return 0; + "enum Local { Present } + function bare() returns (word) { return missing; } + function qualified() returns (word) { return math.value(); } + function ctorExpr() returns (word) { return Option.Some(0); } + function ctorPat(x: word) returns (word) { + match (x) { + case Option.Some(y) { return y; } + case _ { return 0; } } } - function valueMember(x: word) -> word { return x.absent; } - function member() -> word { return Local.absent; }", + function valueMember(x: word) returns (word) { return x.absent; } + function member() returns (word) { return Local.absent; }", ); assert!(parse_diagnostics(&db, file).is_empty()); @@ -437,8 +438,8 @@ fn missing_resolved_module_member_has_qualified_lookup_context() { let (file, module) = parse_and_module( &db, "missing_module_member", - "data Local = Present; - function missing() -> word { + "enum Local { Present } + function missing() returns (word) { let fromModule = math.value(); return Local.absent; }", @@ -485,11 +486,11 @@ fn missing_constructor_on_resolved_type_is_not_an_import_context() { let (file, module) = parse_and_module( &db, "missing_local_constructor", - "data Option = None; - function missing(value: Option) -> word { - match value { - | Option.Some => return 1; - | _ => return 0; + "enum Option { None } + function missing(value: Option) returns (word) { + match (value) { + case Option.Some { return 1; } + case _ { return 0; } } }", ); @@ -563,12 +564,12 @@ fn field_ufcs_resolves_a_unique_local_class_method() { let db = TestDb::default(); let module = parse_module( &db, - "forall self . class self:Combiner { - function combine(x: self, y: word) -> word; + "trait Combiner { + function combine(x: self, y: word) returns (word); } contract C { value: word; - function viaUfcs(y: word) -> word { return value.combine(y); } + function viaUfcs(y: word) returns (word) { return value.combine(y); } }", ); let resolution = resolve_module(&db, module); @@ -602,8 +603,8 @@ fn field_ufcs_resolves_a_unique_imported_class_method() { let db = TestDb::default(); let provider = parse_module( &db, - "forall self . class self:RemoteOps { - function touch(x: self) -> word; + "trait RemoteOps { + function touch(x: self) returns (word); }", ); let class = top_class_id(&db, provider, "RemoteOps"); @@ -611,7 +612,7 @@ fn field_ufcs_resolves_a_unique_imported_class_method() { &db, "contract C { value: word; - function viaImport() -> word { return value.touch(); } + function viaImport() returns (word) { return value.touch(); } }", ); let imports = ClassMethodImports { @@ -654,21 +655,21 @@ fn ufcs_reports_undefined_name_when_visible_methods_conflict() { let db = TestDb::default(); let provider = parse_module( &db, - "forall self . class self:RemoteOps { - function collide(x: self) -> word; + "trait RemoteOps { + function collide(x: self) returns (word); }", ); let remote_class = top_class_id(&db, provider, "RemoteOps"); let module = parse_module( &db, - "forall self . class self:LocalOps { - function collide(x: self) -> word; + "trait LocalOps { + function collide(x: self) returns (word); } contract C { value: word; - function ambiguous() -> word { return value.collide(); } - function ambiguousParameter(value: word) -> word { return value.collide(); } - function missing() -> word { return value.absent(); } + function ambiguous() returns (word) { return value.collide(); } + function ambiguousParameter(value: word) returns (word) { return value.collide(); } + function missing() returns (word) { return value.absent(); } }", ); let imports = ClassMethodImports { @@ -720,8 +721,7 @@ fn ufcs_reports_undefined_name_when_visible_methods_conflict() { .expect("parameter body map"); assert!(ident_resolutions(&db, parameter_body, parameter_map) .into_iter() - .any(|(name, resolution)| name == "value" - && matches!(resolution, Resolution::Param(_)))); + .any(|(name, resolution)| name == "value" && matches!(resolution, Resolution::Param(_)))); assert!( field_resolutions(&db, parameter_body, parameter_map) .into_iter() @@ -747,26 +747,26 @@ fn value_ufcs_resolves_parameters_and_locals_while_preserving_qualified_calls() let db = TestDb::default(); let module = parse_module( &db, - "forall self . class self:Combiner { - function combine(x: self, y: word) -> word; + "trait Combiner { + function combine(x: self, y: word) returns (word); } contract C { value: word; Combiner: word; - function qualified(y: word) -> word { + function qualified(y: word) returns (word) { return Combiner.combine(value, y); } - function sameNameQualifier(y: word) -> word { + function sameNameQualifier(y: word) returns (word) { return Combiner.combine(Combiner, y); } - function parameter(value: word, y: word) -> word { + function parameter(value: word, y: word) returns (word) { return value.combine(y); } - function local(value: word, y: word) -> word { + function local(value: word, y: word) returns (word) { let receiver = value; return receiver.combine(y); } - function arbitrary(y: word) -> word { + function arbitrary(y: word) returns (word) { return (value + y).combine(y); } }", @@ -844,8 +844,7 @@ fn value_ufcs_resolves_parameters_and_locals_while_preserving_qualified_calls() .expect("parameter body map"); assert!(ident_resolutions(&db, parameter_body, parameter_map) .into_iter() - .any(|(name, resolution)| name == "value" - && matches!(resolution, Resolution::Param(_)))); + .any(|(name, resolution)| name == "value" && matches!(resolution, Resolution::Param(_)))); assert!( field_resolutions(&db, parameter_body, parameter_map) .into_iter() @@ -892,7 +891,7 @@ fn let_initializer_resolves_before_binder_and_then_shadows() { let db = TestDb::default(); let module = parse_module( &db, - "function f(x: word) -> word { + "function f(x: word) returns (word) { let x = x; return x; }", @@ -917,7 +916,7 @@ fn explicit_blocks_scope_locals_but_for_body_lets_leak() { let db = TestDb::default(); let module = parse_module( &db, - "function f(x: word) -> word { + "function f(x: word) returns (word) { { let x = x; } @@ -947,11 +946,11 @@ fn contract_fields_beat_top_level_functions_and_params_shadow_fields() { let db = TestDb::default(); let module = parse_module( &db, - "function balance() -> word { return 0; } + "function balance() returns (word) { return 0; } contract C { balance: word; - function f() -> word { return balance; } - function g(balance: word) -> word { return balance; } + function f() returns (word) { return balance; } + function g(balance: word) returns (word) { return balance; } }", ); assert!(diagnostic_codes(&db, module).is_empty()); @@ -976,9 +975,9 @@ fn unqualified_call_callee_prefers_contract_function_over_same_name_field() { &db, "contract C { balance: word; - function balance() -> word { return 7; } - function call() -> word { return balance(); } - function bare() -> word { return balance; } + function balance() returns (word) { return 7; } + function call() returns (word) { return balance(); } + function bare() returns (word) { return balance; } }", ); assert!(diagnostic_codes(&db, module).is_empty()); @@ -1015,13 +1014,13 @@ fn qualified_ctor_class_method_and_dot_ctor_resolve_as_expected() { let db = TestDb::default(); let module = parse_module( &db, - "data Option = None | Some(word); - data Foo = Foo(word); - forall self . class self:Show { function show(x: self) -> word; } - function good(x: word) -> Option { return Option.Some(x); } - function classCall(x: word) -> word { return Show.show(x); } - function dot(x: word) -> Option { return .Some(x); } - function sameName(x: word) -> Foo { return Foo(x); }", + "enum Option { None, Some(word) } + enum Foo { Foo(word) } + trait Show { function show(x: self) returns (word); } + function good(x: word) returns (Option) { return Option.Some(x); } + function classCall(x: word) returns (word) { return Show.show(x); } + function dot(x: word) returns (Option) { return .Some(x); } + function sameName(x: word) returns (Foo) { return Foo(x); }", ); let codes = diagnostic_codes(&db, module); assert!(codes.is_empty()); @@ -1055,20 +1054,20 @@ fn self_qualified_contract_methods_do_not_shadow_same_named_local_adt_constructo &db, r#" contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function some(x : word) -> Option(word) { + function some(x: word) returns (Option) { return Option.Some(x); } - function none() -> Option(word) { + function none() returns (Option) { return Option.None; } - function read(o : Option(word)) -> word { - match o { - | Option.Some(x) => return x; - | Option.None => return 0; + function read(o: Option) returns (word) { + match (o) { + case Option.Some(x) { return x; } + case Option.None { return 0; } } } } @@ -1108,7 +1107,7 @@ fn definite_same_name_constructor_beats_unknown_wildcard_import() { let db = TestDb::default(); let module = parse_module( &db, - "data Unit = Unit; function make() -> Unit { return Unit; }", + "enum Unit { Unit } function make() returns (Unit) { return Unit; }", ); let function = top_function(&db, module, "make"); let body = function.body(&db).expect("body"); diff --git a/crates/parser/tests/properties.rs b/crates/parser/tests/properties.rs index e71e1c95..fb58a3e0 100644 --- a/crates/parser/tests/properties.rs +++ b/crates/parser/tests/properties.rs @@ -25,15 +25,15 @@ impl hir::Db for TestDb { impl solcore_parser::Db for TestDb {} const CORPUS_SEEDS: &[&str] = &[ - include_str!("fixtures/ok/no_diagnostics.solc"), - include_str!("fixtures/ok/contract_modifiers_constructor_fallback.solc"), - include_str!("fixtures/ok/match_arm_block.solc"), - include_str!("fixtures/corpus/fail/test/diagnostics/parse-error.solc"), + include_str!("fixtures/ok/no_diagnostics.sol"), + include_str!("fixtures/ok/contract_modifiers_constructor_fallback.sol"), + include_str!("fixtures/ok/match_arm_block.sol"), + include_str!("fixtures/corpus/fail/test/diagnostics/parse-error.sol"), ]; fn parse_without_large_test_stack(source: String) -> Vec { let db = TestDb::default(); - let url = "memory:///property.solc".parse().expect("valid test URL"); + let url = "memory:///property.sol".parse().expect("valid test URL"); let file = SourceFile::new(&db, url, Some(source)); let _ = parse_file_to_hir(&db, file).module(&db); parse_diagnostics(&db, file) @@ -71,10 +71,10 @@ proptest! { } #[test] -fn right_nested_else_if_chain_uses_the_default_stack() { +fn right_nested_ternary_chain_uses_the_default_stack() { let depth = 96; - let mut source = "function main() -> word { return ".to_owned(); - source.push_str(&"if true then 0 else ".repeat(depth)); + let mut source = "function main() returns (word) { return ".to_owned(); + source.push_str(&"true ? 0 : ".repeat(depth)); source.push_str("0; }"); let diagnostics = parse_without_large_test_stack(source); assert!( diff --git a/crates/parser/tests/reserved_words.rs b/crates/parser/tests/reserved_words.rs new file mode 100644 index 00000000..19676530 --- /dev/null +++ b/crates/parser/tests/reserved_words.rs @@ -0,0 +1,83 @@ +use hir::{diag::AnyDiagnostic, input::SourceFile}; +use solcore_parser::{parse_diagnostics, parse_file_to_hir}; + +#[salsa::db] +#[derive(Default, Clone)] +struct TestDb { + storage: salsa::Storage, +} + +#[salsa::db] +impl salsa::Database for TestDb {} + +#[salsa::db] +impl hir::Db for TestDb { + fn def_location_table<'db>( + &'db self, + file: SourceFile, + ) -> &'db hir::anchor::DefLocationTable<'db> { + parse_file_to_hir(self, file).def_locations(self) + } +} + +#[salsa::db] +impl solcore_parser::Db for TestDb {} + +fn source_file(db: &TestDb, name: &str, source: &str) -> SourceFile { + let url = format!("memory:///{name}.sol").parse().expect("valid URL"); + SourceFile::new(db, url, Some(source.to_owned())) +} + +fn diagnostics(db: &TestDb, file: SourceFile) -> Vec { + parse_diagnostics(db, file).to_vec() +} + +#[test] +fn booleans_remain_valid_values_and_patterns_and_fallback_remains_an_entry_point() { + let db = TestDb::default(); + let file = source_file( + &db, + "reserved-positive", + r#" +function flip(value: bool) returns (bool) { + match (value) { + case true { return false; } + case false { return true; } + } +} + +contract C { + fallback() payable {} +} +"#, + ); + + assert!(diagnostics(&db, file).is_empty()); +} + +#[test] +fn reserved_values_and_entry_point_name_are_rejected_as_identifiers() { + let cases = [ + ("function-true", "function true() {}"), + ("function-false", "function false() {}"), + ( + "ordinary-function-fallback", + "contract C { function fallback() {} }", + ), + ("let-true", "function f() { let true = false; }"), + ("field-false", "contract C { false: word; }"), + ("parameter-fallback", "function f(fallback: word) {}"), + ("type-true", "function f(value: true) {}"), + ("import-false", "import {false} from std;"), + ("enum-fallback", "enum fallback { Value }"), + ]; + + for (name, source) in cases { + let db = TestDb::default(); + let file = source_file(&db, name, source); + assert!( + !diagnostics(&db, file).is_empty(), + "reserved identifier case `{name}` parsed without diagnostics" + ); + } +} From 38989bf918cb1674b7c1293ee6da976ad61e4098 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 047/110] Switch the compiler and fixtures to canonical syntax: parser corpus README.md Co-authored-by: Codex --- crates/parser/tests/fixtures/corpus/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/README.md b/crates/parser/tests/fixtures/corpus/README.md index 539b2efa..a82c0765 100644 --- a/crates/parser/tests/fixtures/corpus/README.md +++ b/crates/parser/tests/fixtures/corpus/README.md @@ -1,13 +1,14 @@ # Solcore 2f372bde frontend corpus -This corpus vendors every `.solc` source under `test/examples/` from +This corpus ports every source under `test/examples/` from [`argotorg/solcore@2f372bde`](https://github.com/argotorg/solcore/tree/2f372bde2801612814015a22319d0bc51486cbf0/test/examples). -The 499 example paths and their contents are byte-identical to that snapshot. +The 499 examples keep the snapshot's module layout and semantics while using +the canonical `.sol` syntax. Sources accepted by the reference frontend live under `ok/test/examples/`; reference failures and timeouts live under `fail/test/examples/`. -The standard-library sources in `ok/std/` are the matching 2f372bde snapshot. -They are also byte-identical to [`std/`](../../../../../std/); see +The standard-library sources in `ok/std/` are the syntax-migrated 2f372bde +snapshot. They are byte-identical to [`std/`](../../../../../std/); see [`std/README.md`](../../../../../std/README.md) for the synchronization policy. The `test/imports/` and `known-diagnostic-gaps/` trees are Rust-specific regressions and are not part of the reference example snapshot. @@ -26,10 +27,11 @@ sol-core --file <2f372bde>/test/examples/ \ --color never --unicode never --diagnostic-format short ``` -The snapshot contains 337 passes, 160 failures, and two timeouts. `code` is the +The original snapshot contains 337 passes, 160 failures, and two timeouts. +Ledger paths map to the migrated `.sol` files by module stem. `code` is the first structured `SCnnnn` diagnostic emitted for a failure; `-` means that no structured code applies. The two timeout rows are -`cases/tabled-cycle-fail.solc` and `cases/tabled-left-recursive-fail.solc`. +`cases/tabled-cycle-fail.sol` and `cases/tabled-left-recursive-fail.sol`. These verdicts describe the legacy frontend with specialization and generated dispatch disabled, not the full compiler or the tabled resolver. From f5229b0b8da02d7f7a5412fced28f1a7abfe087d Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 048/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test diagnostics Co-authored-by: Codex --- .../fixtures/corpus/fail/test/diagnostics/parse-error.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.snap b/crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.snap index 9da95013..331e3a22 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.snap @@ -1,10 +1,10 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/diagnostics/parse-error.sol --- error[SC0001]: parse error: unexpected end of input - --> /parse-error.solc:1:38 + --> /parse-error.sol:1:38 | 1 | function main( -> word { return 0; } | ^ unexpected token From 83c2ebe9e6693b48d00e0410dfc52752d0ef1c1a Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 049/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples Co-authored-by: Codex --- .../corpus/fail/test/examples/Convertible.sol | 117 ++++++++++-------- .../fail/test/examples/cases/BadInstance.sol | 24 ++-- .../fail/test/examples/cases/DupFun.sol | 6 +- .../corpus/fail/test/examples/cases/Enum.sol | 28 +++-- .../corpus/fail/test/examples/cases/Eq.sol | 28 +++-- .../fail/test/examples/cases/Filter.sol | 71 ++++++----- .../fail/test/examples/cases/GetSet.sol | 4 +- .../fail/test/examples/cases/GoodInstance.sol | 46 ++++--- .../test/examples/cases/IncompleteInstDef.sol | 14 +-- .../fail/test/examples/cases/Invokable.sol | 12 +- .../fail/test/examples/cases/KindTest.sol | 6 +- .../fail/test/examples/cases/PairMatch1.sol | 4 +- .../fail/test/examples/cases/PairMatch2.sol | 10 +- .../corpus/fail/test/examples/cases/Ref.sol | 21 ++-- .../fail/test/examples/cases/SillyReturn.sol | 18 +-- .../fail/test/examples/cases/SimpleInvoke.sol | 14 +-- .../test/examples/cases/StructMembers.snap | 45 +++++-- .../test/examples/cases/StructMembers.sol | 109 ++++++++-------- .../fail/test/examples/cases/add-moritz.sol | 103 +++++++++------ .../cases/array-elem-no-storagecopy.sol | 8 +- .../examples/cases/array-push-no-canstore.sol | 8 +- .../examples/cases/arraylit-bad-target.sol | 4 +- .../examples/cases/arraylit-mixed-types.sol | 6 +- .../examples/cases/asm-assign-no-return.sol | 2 +- .../examples/cases/asm-assign-non-word.sol | 4 +- .../test/examples/cases/asm-let-no-return.sol | 2 +- .../test/examples/cases/bound-minimal.sol | 8 +- .../test/examples/cases/bound-only-test.sol | 8 +- .../examples/cases/bug-spec-generic-let.sol | 49 +++++--- .../test/examples/cases/catenable-err.snap | 14 +-- .../test/examples/cases/catenable-err.sol | 2 +- .../examples/cases/class-return-type-miss.sol | 6 +- .../cases/class-type-name-collision.sol | 7 +- .../corpus/fail/test/examples/cases/comp.sol | 2 +- .../fail/test/examples/cases/complexproxy.sol | 29 +++-- .../test/examples/cases/compose_desugared.sol | 42 +++---- .../fail/test/examples/cases/const-array.sol | 20 +-- 37 files changed, 501 insertions(+), 400 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.sol index cccfa06c..21dc4694 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/Convertible.sol @@ -1,70 +1,77 @@ -data Pair(a,b) = Pair(a,b); -data Proxy(a) = Proxy; -data Unit = Unit; +enum Pair { Pair(a, b) } +enum Proxy { Proxy } +enum Unit { Unit } -class a:Typedef(r) { - function abs(x:r) -> a; - function rep(x:a) -> r; +trait Typedef { + function abs(x: r) returns (a) ; + function rep(x: a) returns (r) ; } -data uint16 = uint16(word); +enum uint16 { uint16(word) } -instance uint16:Typedef(word) { - function abs(r:word) { return uint16(r);} - function rep(x: uint16) -> word { - match x { - | uint16(val) => return val; - }; +impl Typedef { + function abs(r:word) returns (uint16) { return uint16(r);} + function rep(x: uint16) returns (word) { + match (x) { +case uint16(val) { +return val; +} +} } } -data uint8 = uint8(word); +enum uint8 { uint8(word) } -instance uint8:Typedef(word) { - function abs(r:word) { return uint8(r);} - function rep(x: uint8) -> word { - match x { - | uint8(val) => return val; - }; +impl Typedef { + function abs(r:word) returns (uint8) { return uint8(r);} + function rep(x: uint8) returns (word) { + match (x) { +case uint8(val) { +return val; +} +} } } -data uint256 = uint256(word); +enum uint256 { uint256(word) } -instance uint256:Typedef(word) { - function abs(r:word) { return uint256(r);} - function rep(x: uint256) -> word { - match x { - | uint256(val) => return val; - }; +impl Typedef { + function abs(r:word) returns (uint256) { return uint256(r);} + function rep(x: uint256) returns (word) { + match (x) { +case uint256(val) { +return val; +} +} } } -function foo(x:word) -> uint16 { +function foo(x: word) returns (uint16) { let result : uint16 = Typedef.abs(x); return result; } -class self:Convertible(r) -{ - function convert(x:self) -> r; +trait Convertible { + function convert(x: self) returns (r) ; } -instance Pair(uint8,Proxy(uint16)):Convertible(uint16) { - function convert(p:Pair(uint8,Proxy(uint16))) -> uint16 { - match p { - | Pair(x, _) => return Typedef.abs(Typedef.rep(x)); - }; +impl Convertible>, uint16> { + function convert(p: Pair>) returns (uint16) { + match (p) { +case Pair(x, _) { +return Typedef.abs(Typedef.rep(x)); +} +} } } -function uint8to16(x : uint8) -> uint16 { - let proxy : Proxy(uint16) = Proxy; +function uint8to16(x: uint8) returns (uint16) { + let proxy : Proxy = Proxy; let result : uint16 = Convertible.convert(Pair(x,proxy)); return result; } @@ -77,31 +84,35 @@ forall Pair(a,Proxy(b)):Convertible(b). function convert(x:a) -> b { } */ -forall a, b. function convert(x:a) -> b { - let proxy : Proxy(b) = Proxy; +function convert(x: a) returns (b) { + let proxy : Proxy = Proxy; let result : b = Convertible.convert(Pair(x,proxy)); return result; } -function bar(x:Unit) -> word { +function bar(x: Unit) returns (word) { let result: word = convert(x); return result; } -instance Pair(uint8,Proxy(uint256)):Convertible(uint256) { - function convert(p:Pair(uint8,Proxy(uint256))) -> uint256 { - match p { - | Pair(x, _) => return Typedef.abs(Typedef.rep(x)); - }; +impl Convertible>, uint256> { + function convert(p: Pair>) returns (uint256) { + match (p) { +case Pair(x, _) { +return Typedef.abs(Typedef.rep(x)); +} +} } } -instance Pair(uint16,Proxy(uint256)):Convertible(uint256) { - function convert(p:Pair(uint16,Proxy(uint256))) -> uint256 { - match p { - | Pair(x, _) => return Typedef.abs(Typedef.rep(x)); - }; +impl Convertible>, uint256> { + function convert(p: Pair>) returns (uint256) { + match (p) { +case Pair(x, _) { +return Typedef.abs(Typedef.rep(x)); +} +} } } @@ -109,10 +120,10 @@ instance Pair(uint16,Proxy(uint256)):Convertible(uint256) { contract Bar { -public function main() -> word { +function main() public returns (word) { let x = Unit; let y : word = convert(x); return y; } -} \ No newline at end of file +} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.sol index 0906c230..a8cfeec8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/BadInstance.sol @@ -1,17 +1,21 @@ -class a:Enum { - function fromEnum(x:a) -> word; +trait Enum { + function fromEnum(x: a) returns (word) ; } -data Color = R | G | B; +enum Color { R, G, B } -data Bool = False | True; +enum Bool { False, True } -instance Bool : Enum { - function fromEnum(b : Bool) -> word { - match b { - | Color.R => return 0; - | Color.G => return 1; - } +impl Enum { + function fromEnum(b: Bool) returns (word) { + match (b) { +case Color.R { +return 0; +} +case Color.G { +return 1; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.sol index fbfc9dce..1159c19c 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/DupFun.sol @@ -1,11 +1,11 @@ -function f(x : word) -> word { +function f(x: word) returns (word) { return x; } -function f(x : word) -> word { +function f(x: word) returns (word) { return 10; } -function g(x : word) -> word { +function g(x: word) returns (word) { return f(x); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.sol index 6b977e4a..4548940f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Enum.sol @@ -1,21 +1,27 @@ -class a: Enum { - function fromEnum(x : a) -> word; +trait Enum { + function fromEnum(x: a) returns (word) ; } -data Food = Curry | Beans | Other; +enum Food { Curry, Beans, Other } -instance Food : Enum { - function fromEnum(x : Food) -> word { - match x { - | Food.Curry => return 1; - | Food.Beans => return 2; - | Food.Other => return 3; - } +impl Enum { + function fromEnum(x: Food) returns (word) { + match (x) { +case Food.Curry { +return 1; +} +case Food.Beans { +return 2; +} +case Food.Other { +return 3; +} +} } } contract Food { - public function main() -> word { + function main() public returns (word) { return Enum.fromEnum(Food.Beans); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.sol index a36b462d..ec5118b4 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Eq.sol @@ -1,20 +1,22 @@ -data Bool = True | False; +enum Bool { True, False } -class a : Eq { - function eq (x : a, y : a) -> Bool; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } -forall a . a : Eq => class a : Ord { - function lt (x : a, y : a) -> Bool ; +trait Ord where a: Eq { + function lt(x: a, y: a) returns (Bool) ; } -instance word : Eq { - function eq (x,y) { - match primEqWord(x,y) { - | 0 => - return Bool.False; - | _ => - return Bool.True ; - } +impl Eq { + function eq (x: word, y: word) returns (Bool) { + match (primEqWord(x,y)) { +case 0 { +return Bool.False; +} +default { +return Bool.True ; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.sol index fd0d0d59..aa8037ca 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Filter.sol @@ -1,51 +1,66 @@ -data List(a) = Nil | Cons(a,List(a)); -data Bool = False | True; +enum List { Nil, Cons(a, List) } +enum Bool { False, True } -function and(x : Bool, y : Bool) -> Bool { - match x, y { - | Bool.False, _ => return Bool.False; - | Bool.True, z => return z; - } +function and(x: Bool, y: Bool) returns (Bool) { + match (x, y) { +case (Bool.False, _) { +return Bool.False; +} +case (Bool.True, z) { +return z; +} +} } -class a : Eq { - function eq (x : a, y : a) -> Bool ; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } -instance Word : Eq { - function eq (x : Word, y : Word) -> Bool { - match primEqWord(x,y) { - | 0 => return Bool.False ; - | _ => return Bool.True ; - } +impl Eq { + function eq(x: Word, y: Word) returns (Bool) { + match (primEqWord(x,y)) { +case 0 { +return Bool.False ; +} +default { +return Bool.True ; +} +} } } -function filter (f : (Word) -> Bool, xs : List(Word)) -> List(Word) { - match xs { - | List.Nil => return List.Nil ; - | List.Cons(y,ys) => - match f(y) { - | Bool.False => return filter(f,ys); - | Bool.True => return List.Cons(y,filter(f,ys)); - } - } +function filter(f: function(Word) returns (Bool), xs: List) returns (List) { + match (xs) { +case List.Nil { +return List.Nil ; +} +case List.Cons(y,ys) { +match (f(y)) { +case Bool.False { +return filter(f,ys); +} +case Bool.True { +return List.Cons(y,filter(f,ys)); +} +} +} +} } -function list1 () -> List(Word) { +function list1() returns (List) { return List.Cons(1, List.Cons(2, List.Cons(3, List.Nil))); } -function foo0(y : Word) -> List(Word) { +function foo0(y: Word) returns (List) { return filter((lam (x){ return eq(x,y); }), list1()); } -function foo1() -> List(Word) { +function foo1() returns (List) { return filter((lam (x){ return eq(x,1); }), list1()); } -function foo2(p : (Word) -> Bool, q : (Word) -> Bool) -> List(Word) { +function foo2(p: function(Word) returns (Bool), q: function(Word) returns (Bool)) returns (List) { return filter(lam (x) { return and(p(x), q(x)) ; } , list1()); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.sol index b8da1585..9ffbc80f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GetSet.sol @@ -1,11 +1,11 @@ contract GetSet { value : Word ; - public function setValue (x) { + function setValue(x: Word) public { value = x ; } - public function getValue () { + function getValue() public returns (Word) { return value ; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.sol index 14cf8a79..6e2a03b7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/GoodInstance.sol @@ -1,31 +1,41 @@ -class a:Enum { - function fromEnum(x:a) -> Word; +trait Enum { + function fromEnum(x: a) returns (Word) ; } - data Color = R | G | B; + enum Color { R, G, B } -instance Color : Enum { - function fromEnum(c : Color) -> Word { - match c { - | Color.R => return 1; - | Color.G => return 2; - | Color.B => return 3; - } +impl Enum { + function fromEnum(c: Color) returns (Word) { + match (c) { +case Color.R { +return 1; +} +case Color.G { +return 2; +} +case Color.B { +return 3; +} +} } } -data Bool = False | True; +enum Bool { False, True } -instance Bool : Enum { - function fromEnum(b : Bool) -> Word { - match b { - | Bool.False => return 0; - | Bool.True => return 1; - } +impl Enum { + function fromEnum(b: Bool) returns (Word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } } contract GoodInstance { - public function main() -> Word { return fromEnum(Bool.True);} + function main() public returns (Word) { return fromEnum(Bool.True);} } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.sol index 4d86d53e..8db8de8c 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/IncompleteInstDef.sol @@ -1,14 +1,14 @@ -forall a b . class a : Foo(b) { - function foo (x : a, y : b) -> b ; - function faa (y : a) -> a ; +trait Foo { + function foo(x: a, y: b) returns (b) ; + function faa(y: a) returns (a) ; } -data Bool = False | True; +enum Bool { False, True } -data Maybe(a) = Nothing | Just(a); +enum Maybe { Nothing, Just(a) } // missing the definition of Foo.foo -instance Bool : Foo(Bool) { - function faa(y : Bool) -> Bool { +impl Foo { + function faa(y: Bool) returns (Bool) { return y ; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.sol index 35e52735..78e60dc7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Invokable.sol @@ -1,16 +1,16 @@ -class self : invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait invokable { + function invoke(s: self, a: args) returns (ret) ; } - forall a . function id(x : a) -> a { + function id(x: a) returns (a) { return x ; } - data IdToken(a) = IdToken; + enum IdToken { IdToken } -instance IdToken(a) : invokable(a,a) { - function invoke(token: IdToken(a), a) -> a { +impl invokable, a, a> { + function invoke(token: IdToken, a: a) returns (a) { return id(a); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.sol index 9a4399f5..69772cf5 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/KindTest.sol @@ -1,5 +1,5 @@ -data M = M; -function foo(x: M(Word)) {} +enum M { M } +function foo(x: M) {} -data P(a) = P; +enum P { P } function foo2(x: P) {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.sol index 3f2a4636..155603d8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch1.sol @@ -1,6 +1,6 @@ -data Pair(a, b) = Pair(a, b); +enum Pair { Pair(a, b) } -forall a . function foo(p: a) -> word { +function foo(p: a) returns (word) { let x: word = p; return x; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.sol index 98395bb4..7ddf8097 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/PairMatch2.sol @@ -1,8 +1,10 @@ -forall a . function snd(p: (a, word)) -> a { - match p { - | (_, w) => return w; - } +function snd(p: (a, word)) returns (a) { + match (p) { +case (_, w) { +return w; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.sol index afce6aa5..0ca14d36 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/Ref.sol @@ -1,16 +1,17 @@ -class ref : Ref(deref) { - function load (r : ref) -> deref; - function store (r : ref, d : deref) -> unit; +trait Ref { + function load(r: ref) returns (deref) ; + function store(r: ref, d: deref) returns (unit) ; } -data Memory(a) = new(a); +enum Memory { new(a) } -instance Memory(a) : Ref(a) { - function load (r) { - match r { - | Memory.new(x) => return x; - } +impl Ref, a> { + function load (r: Memory) returns (a) { + match (r) { +case Memory.new(x) { +return x; +} +} } } - diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.sol index 25dddd32..36fe79f3 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SillyReturn.sol @@ -1,9 +1,13 @@ -data Nat = Zero | Succ(Nat); -data Bool = True | False; +enum Nat { Zero, Succ(Nat) } +enum Bool { True, False } -function even (n) -> Bool { - match n { - | Nat.Zero => return 1; return Bool.True; - | Nat.Succ(m) => return 0; return Bool.False; - } +function even(n: word) returns (Bool) { + match (n) { +case Nat.Zero { +return 1; return Bool.True; +} +case Nat.Succ(m) { +return 0; return Bool.False; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.sol index 09f5ce97..55c4f74d 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/SimpleInvoke.sol @@ -1,17 +1,17 @@ -function lambdaimpl1 (x) { +function lambdaimpl1 (x: a) returns (a) { return x; } -data LambdaTy0(a) = LambdaTy0; -class self : invokable (args, ret) { - function invoke (self : self, args : args) -> ret; +enum LambdaTy0 { LambdaTy0 } +trait invokable { + function invoke(self: self, args: args) returns (ret) ; } -instance LambdaTy0(a) : invokable (a, a) { - forall a . function invoke (self : LambdaTy0(a), args : a) -> a { +impl invokable, a, a> { + function invoke(self: LambdaTy0, args: a) returns (a) { return lambdaimpl1(args); } } contract SimpleLambda { - public function f () { + function f() public returns (word) { let n = LambdaTy0 ; return invokable.invoke(n, 0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.snap index 56ead403..e49bccf3 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.snap @@ -1,15 +1,36 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.solc ---- -error[SC0001]: parse error: unexpected `data` - --> /StructMembers.solc:7:1 - | -6 | data Uint256 = Uint256(Word) -7 | data Bool = True | False - | ^^^^ unexpected token -8 | data Bytes32 = Bytes32(Word) - | - = note: expecting `;`, or `|` - = note: while parsing data declaration +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol +--- +error[SC0001]: parse error: unexpected `;` + --> /StructMembers.sol:77:40 + | +76 | let szb = memorySize(pb); +77 | assembly { sz := add(sz, szb) }; // TODO: bounds check? + | ^ unexpected token +78 | return sz; + | + = note: expecting end of input, or statement +--- + +error[SC0001]: parse error: unexpected `;` + --> /StructMembers.sol:91:37 + | +90 | let v; +91 | assembly { v := mload(off) }; + | ^ unexpected token +92 | return Uint256(v); + | + = note: expecting end of input, or statement +--- + +error[SC0001]: parse error: unexpected `;` + --> /StructMembers.sol:121:45 + | +120 | +121 | assembly { ptr := add(ptr, offset) }; + | ^ unexpected token +122 | + | + = note: expecting end of input, or statement diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol index 89508d44..818e4941 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/StructMembers.sol @@ -1,24 +1,24 @@ /// Other used stdlib classes and types: -class self:Ref(deref) { - function load(x:self) -> deref; +trait Ref { + function load(x: self) returns (deref) ; } -data Uint256 = Uint256(Word) -data Bool = True | False -data Bytes32 = Bytes32(Word) -data Unit = Unit +enum Uint256 { Uint256(Word) } +enum Bool { True, False } +enum Bytes32 { Bytes32(Word) } +enum Unit { Unit } -data Proxy(t) = Proxy -data Memory(x) = Memory(Word) +enum Proxy { Proxy } +enum Memory { Memory(Word) } /// Specific new stdlib classes and types: -class self:StructMember(preceding, memberTy) {} -data StructMember(structType, fieldType) = StructMember +trait StructMember {} +enum StructMember { StructMember } // "dead" is only here to compensate for non-relaxed coverage condition and // incorrectly implemented Paterson condition -data MemberAccess(ty, field, dead) = MemberAccess(ty) +enum MemberAccess { MemberAccess(ty) } /// Usage Example / Proof of Concept: @@ -31,16 +31,16 @@ data MemberAccess(ty, field, dead) = MemberAccess(ty) } */ -data S = S(Pair(Uint256, Pair(Bool, Bytes32))) +enum S { S(Pair>) } -data Field_x = FieldX // Selector type for "x" -data Field_y = FieldY // Selector type for "y" -data Field_z = FieldZ // Selector type for "z" +enum Field_x { FieldX } // Selector type for "x" +enum Field_y { FieldY } // Selector type for "y" +enum Field_z { FieldZ } // Selector type for "z" // StructMember instances for field selectors: -instance StructMember(S, Field_x):StructMember(Unit, Uint256) {} -instance StructMember(S, Field_y):StructMember(Uint256, Bool) {} -instance StructMember(S, Field_z):StructMember(Pair(Uint256, Bool), Bytes32) {} +impl StructMember, Unit, Uint256> {} +impl StructMember, Uint256, Bool> {} +impl StructMember, Pair, Bytes32> {} /* Further compiler-internal builtin instances for use on stack (at least the stackref versions cannot be expressed in-language, * but none of these rely on any layout other than the compiler-builtin stack layout, so we can handle these purely internally @@ -57,22 +57,21 @@ instance StructMember(S, Field_z):StructMember(Pair(Uint256, Bool), Bytes32) {} /// Size of a type in memory -class self:MemorySize { - function memorySize(x:Proxy(self)) -> Word; +trait MemorySize { + function memorySize(x: Proxy) returns (Word) ; } /// Size of the struct member types in memory: -instance Unit:MemorySize { function memorySize(x : Proxy(Unit)) -> Word { return 0; } } -instance Uint256:MemorySize { function memorySize(x : Proxy(Uint256)) -> Word { return 32; } } -instance Bool:MemorySize { function memorySize(x : Proxy(Bool)) -> Word { return 32; } } -instance Bytes32:MemorySize { function memorySize(x : Proxy(Bytes32)) -> Word { return 32; } } +impl MemorySize { function memorySize(x: Proxy) returns (Word) { return 0; } } +impl MemorySize { function memorySize(x: Proxy) returns (Word) { return 32; } } +impl MemorySize { function memorySize(x: Proxy) returns (Word) { return 32; } } +impl MemorySize { function memorySize(x: Proxy) returns (Word) { return 32; } } /// Memory size of pairs -instance Pair(a,b):MemorySize { - function memorySize(x : Proxy((a,b))) -> Word - { - let pa:Proxy(a); - let pb:Proxy(b); +impl MemorySize> { + function memorySize(x: Proxy<(a, b)>) returns (Word) { + let pa:Proxy; + let pb:Proxy; let sz = memorySize(pa); let szb = memorySize(pb); assembly { sz := add(sz, szb) }; // TODO: bounds check? @@ -82,57 +81,53 @@ instance Pair(a,b):MemorySize { } /// Fragments of a generic memory implementation: -class self:MemoryType { - function loadFromMemory(p:Proxy(self), off:Word) -> self; +trait MemoryType { + function loadFromMemory(p: Proxy, off: Word) returns (self) ; } -instance Uint256:MemoryType { - function loadFromMemory(p:Proxy(Uint256), off:Word) -> Uint256 { +impl MemoryType { + function loadFromMemory(p: Proxy, off: Word) returns (Uint256) { let v; assembly { v := mload(off) }; return Uint256(v); } } -instance (a:MemoryType) => Memory(a):Ref(a) { - function load(x : Memory(a)) -> a { - let p:Proxy(a); - match x { | Memory(off) => return loadFromMemory(p, off); }; +impl Ref, a> { + function load(x: Memory) returns (a) { + let p:Proxy; + match (x) { +case Memory(off) { +return loadFromMemory(p, off); +} +} } } /// Crucial instance: member access to struct fields in memory: -instance ( - StructMember(structType, fieldType):StructMember(precedingTuple, ty), - precedingTuple:MemorySize, - Memory(ty):Ref(ty) -) => MemberAccess(Memory(structType), fieldType, - // Needs ridiculous amounts of constructor applications due to incorrect implementation of the Paterson Condition - // Needs to mention "ty" due to non-relaxed Coverage Condition - Memory(ty) -):Ref(ty) -{ - function load(x : MemberAccess(Memory(structType), fieldType, Memory(ty))) -> ty { +impl Ref, fieldType, Memory>, ty> { + function load(x: MemberAccess, fieldType, Memory>) returns (ty) { let ptr:Word; - match x { | MemberAccess(Memory(y)) => ptr = y; }; + match (x) { +case MemberAccess(Memory(y)) { +ptr = y; +} +} - let p:Proxy(precedingTuple); + let p:Proxy; let offset = memorySize(p); assembly { ptr := add(ptr, offset) }; - let tyPtr:Memory(ty) = Memory(ptr); + let tyPtr:Memory = Memory(ptr); return load(tyPtr); } } -function test() -> () -{ - let x:Memory(S); - let memberAccess:MemberAccess(Memory(S), Field_x, - Memory(Uint256) // will become unnecessary - ); +function test() { + let x:Memory; + let memberAccess:MemberAccess, Field_x, Memory>; memberAccess = MemberAccess(x); let result = load(memberAccess); /* diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.sol index d3654ec8..455ac54f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/add-moritz.sol @@ -1,4 +1,4 @@ -function add(x : word, y : word) { +function add(x : word, y : word) returns (word) { let res: word; assembly { res := add(x, y) @@ -6,65 +6,86 @@ function add(x : word, y : word) { return res; } -class self:Typedef(underlyingType) { - function rep(x:self) -> underlyingType; - function abs(x:underlyingType) -> self; +trait Typedef { + function rep(x: self) returns (underlyingType) ; + function abs(x: underlyingType) returns (self) ; } -forall a.class a : Add { - function add(x:a, y:a) -> a; +trait Add { + function add(x: a, y: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Typedef(word) { - function rep(x : B) -> word { - match x { - | B.F => return 0; - | B.T => return 1; - } +impl Typedef { + function rep(x: B) returns (word) { + match (x) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } - function abs(x : word) -> B { - match x { - | 0 => return B.F; - | 1 => return B.T; - } + function abs(x: word) returns (B) { + match (x) { +case 0 { +return B.F; +} +case 1 { +return B.T; +} +} } } -instance B : Add { - function add(x : B, y : B) -> B { - match x { - | B.F => - match y { - | B.F => return B.F; - | B.T => return B.T; - } - - | B.T => - match y { - | B.F => return B.T; - | B.T => return B.F; - } - } +impl Add { + function add(x: B, y: B) returns (B) { + match (x) { +case B.F { +match (y) { +case B.F { +return B.F; +} +case B.T { +return B.T; +} +} +} +case B.T { +match (y) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} +} +} } } -function fun(a : (B, B), b : (B, B)) -> (B, B) { // -> c - match a, b { - | (a1, a2), (b1, b2) => return (Add.add(a1, b1), fun(a2, b2)); - } +function fun(a: (B, B), b: (B, B)) returns (B, B) { // -> c + match (a, b) { +case ((a1, a2), (b1, b2)) { +return (Add.add(a1, b1), fun(a2, b2)); +} +} } contract Compose { - public function main() -> word { + function main() public returns (word) { let res = fun ((B.T, B.T, B.F), (B.F, B.F, B.T)); - match res { - | (r1, r2, r3) => return Typedef.rep(r1); - } + match (res) { +case (r1, r2, r3) { +return Typedef.rep(r1); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.sol index 11c7a15e..d64d5421 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-elem-no-storagecopy.sol @@ -2,18 +2,18 @@ // storage array: `CanStore` for `storage(array(t))` -- which every field access // goes through -- requires `t:StorageCopy`. Rejecting this at compile time is // what keeps `a = b` from silently shallow-copying a type it cannot copy. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -data Odd = Odd(word); +enum Odd { Odd(word) } contract NoCopy { reserved : word; - xs : array(Odd); + xs : array; - function main() -> uint256 { + function main() returns (uint256) { return Length.length(xs); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.sol index 2d89a295..fce7f1fb 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/array-push-no-canstore.sol @@ -2,18 +2,18 @@ // something `storage(t)` can store. A type with no `CanStore` instance is // rejected -- this is the constraint `storage(t):CanStore(v)` on ArrayPush, // distinct from the `t:StorageCopy` one that whole-array assignment needs. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -data Odd = Odd(word); +enum Odd { Odd(word) } contract PushNoStore { reserved : word; - function main() -> uint256 { - let arr : storage(array(Odd)) = storage(0x100); + function main() returns (uint256) { + let arr : storage> = storage(0x100); ArrayPush.push(arr, Odd(1)); return uint256(0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.sol index 7af42326..92d583a8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-bad-target.sol @@ -1,6 +1,6 @@ // An array literal may only be assigned to a storage *array* field: storeArrayLit // does not unify with a plain word field. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -8,7 +8,7 @@ pragma no-bounded-variable-condition ; contract ArrayLitBadTarget { n : uint256; - function main() -> uint256 { + function main() returns (uint256) { n = [1, 2, 3]; return n; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.sol index effe3a14..efd851b1 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/arraylit-mixed-types.sol @@ -1,14 +1,14 @@ // All elements of an array literal must share one type: unifying uint256 with // address must fail. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract ArrayLitMixed { - function main() -> uint256 { + function main() returns (uint256) { let a : address = Typedef.abs(0x1234); - let m : memory(DynArray(uint256)) = [uint256(1), a]; + let m : memory> = [uint256(1), a]; return m[uint256(0)]; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.sol index 2037d58a..6ac3d2b7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-no-return.sol @@ -1,6 +1,6 @@ // mstore does not return a value, so it cannot be assigned. contract Test { - public function main() { + function main() public { let x : word; assembly { x := mstore(1, 1) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.sol index be96a1bb..d77b3f7f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-assign-non-word.sol @@ -3,9 +3,9 @@ // is a tagged inl/inr pair) would corrupt that layout, so the type checker // must reject this program. contract AsmBool { - public function main() -> word { + function main() public returns (word) { let b : bool = false; assembly { b := add(1, 1) } - if b { return 1; } else { return 0; } + if ( b ) { return 1; } else { return 0; } } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.sol index 9a7b997f..61b625cc 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/asm-let-no-return.sol @@ -1,6 +1,6 @@ // mstore does not return a value, so it cannot initialize a `let`. contract Test { - public function main() { + function main() public { assembly { let x := mstore(1, 1) } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.sol index 748b5c80..9f201dee 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-minimal.sol @@ -2,11 +2,11 @@ // This SHOULD FAIL - variable 'bad' in context but not in instance head -forall a . class a:TestBound {} -forall a b . class a:TestHelper(b) {} +trait TestBound {} +trait TestHelper {} -data TestType(x) = TestType; +enum TestType { TestType } // Variable 'bad' appears in context but not in instance head // Should fail bound variable check -forall x . bad:TestHelper(x) => instance TestType(x):TestBound {} +impl TestBound> where bad: TestHelper {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.sol index 96695759..94cd1505 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bound-only-test.sol @@ -1,10 +1,10 @@ // Test only bound variable check, disable Patterson -forall a . class a:TestBound {} -forall a b . class a:TestHelper(b) {} +trait TestBound {} +trait TestHelper {} -data TestType(x) = TestType; +enum TestType { TestType } // Variable 'bad' appears in context but not in instance head // Should fail bound variable check -forall x . bad:TestHelper(x) => instance TestType(x):TestBound {} +impl TestBound> where bad: TestHelper {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.sol index 9288943a..dd37461d 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/bug-spec-generic-let.sol @@ -13,37 +13,50 @@ // Expected: compiles successfully. // Actual (before fix): PANIC: Type mismatch expected uint256 actual (uint256,uint256) -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; pragma no-patterson-condition; pragma no-coverage-condition; pragma no-bounded-variable-condition; -data Pair = MkPair(uint256, uint256); +enum Pair { MkPair(uint256, uint256) } -instance Pair : Generic((uint256, uint256)) { - function from(x : Pair) -> (uint256, uint256) { - match x { | Pair.MkPair(a, b) => return (a, b); } +impl Generic { + function from(x: Pair) returns (uint256, uint256) { + match (x) { +case Pair.MkPair(a, b) { +return (a, b); +} +} } - function to(x : (uint256, uint256)) -> Pair { - match x { | (a, b) => return Pair.MkPair(a, b); } + function to(x: (uint256, uint256)) returns (Pair) { + match (x) { +case (a, b) { +return Pair.MkPair(a, b); +} +} } } contract BugSpecGenericLet { constructor() {} - function roundtrip(a : uint256, b : uint256) -> uint256 { + function roundtrip(a: uint256, b: uint256) returns (uint256) { let p : Pair = Pair.MkPair(a, b); - let encoded : memory(bytes) = abi_encode(p); + let encoded : memory = abi_encode(p); let decoded : (uint256, uint256) = abi_decode(encoded, @(uint256, uint256), @MemoryWordReader); - match decoded { - | (x, y) => - match and(Eq.eq(x, a), Eq.eq(y, b)) { - | true => return uint256(1); - | false => return uint256(0); - } - } + match (decoded) { +case (x, y) { +match (and(Eq.eq(x, a), Eq.eq(y, b))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.snap index cc4d06ec..2dd3e13d 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.snap @@ -1,15 +1,15 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol --- -error[SC0001]: parse error: unexpected `}` - --> /catenable-err.solc:3:1 +error[SC0001]: parse error: unexpected `->` + --> /catenable-err.sol:2:21 | -1 | forall t.class t:Catenable { +1 | trait Catenable { 2 | function cat(x:t) -> memory(bytes) + | ^^ unexpected token 3 | } - | ^ unexpected token | - = note: expecting `->`, or `;` - = note: while parsing type + = note: expecting `;`, `payable`, or `public` + = note: while parsing function signature diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol index 5bbf71e2..0507fe38 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/catenable-err.sol @@ -1,3 +1,3 @@ -forall t.class t:Catenable { +trait Catenable { function cat(x:t) -> memory(bytes) } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.sol index 01856331..e52a1d4d 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-return-type-miss.sol @@ -1,9 +1,9 @@ -data bytes32 = bytes32(word); +enum bytes32 { bytes32(word) } -forall t . class t:Memory { +trait Memory { function encodeInto(v: t, target: word); } -instance bytes32:Memory { +impl Memory { function encodeInto(v: bytes32, target: word) {} } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.sol index ee30b07b..b11ab376 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/class-type-name-collision.sol @@ -1,6 +1,5 @@ -data Foo = MkFoo; +enum Foo { MkFoo } -forall a. -class a:Foo { - function foo(x:a) -> word; +trait Foo { + function foo(x: a) returns (word) ; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.sol index a49febd9..82842abd 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/comp.sol @@ -1,3 +1,3 @@ -function compose (f,g,x) { +function compose(f: function(b) returns (c), g: function(a) returns (b), x: a) { return f(g(x)); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.sol index 54ca326e..cbe2e96c 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/complexproxy.sol @@ -1,35 +1,34 @@ -data Proxy(a) = Proxy; +enum Proxy { Proxy } -function add(x:word, y: word) {return x;} +function add(x:word, y: word) returns (word) {return x;} -class self:BaseMemoryType { - function memorySize(x:Proxy(self)) -> word; +trait BaseMemoryType { + function memorySize(x: Proxy) returns (word) ; } -instance word:BaseMemoryType { - function memorySize(x:Proxy(word)) -> word { +impl BaseMemoryType { + function memorySize(x: Proxy) returns (word) { return 32; } } -forall a b . a:BaseMemoryType, b:BaseMemoryType => - instance (a,b):BaseMemoryType { +impl BaseMemoryType<(a, b)> where a: BaseMemoryType, b: BaseMemoryType { - function memorySize(x) -> word { // not correct semantically, just for debugging - return add(BaseMemoryType.memorySize(Proxy:Proxy(a)), + function memorySize(x: Proxy<(a, b)>) returns (word) { // not correct semantically, just for debugging + return add(BaseMemoryType.memorySize(@a), // BaseMemoryType.memorySize(Proxy:Proxy(b)) - morefun(Proxy:Proxy(b)) + morefun(@b) ); } } // this should trigger a type error. -forall t. function morefun(p:Proxy(t)) -> word { - return BaseMemoryType.memorySize(Proxy:Proxy(t)); +function morefun(p: Proxy) returns (word) { + return BaseMemoryType.memorySize(@t); } contract TestMemoryType { - public function main() -> word { - return BaseMemoryType.memorySize(Proxy:Proxy( (word,word) )); + function main() public returns (word) { + return BaseMemoryType.memorySize(@(word, word)); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.sol index 303c3b03..9513ebde 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/compose_desugared.sol @@ -1,43 +1,41 @@ -forall a b c d e . d : invokable(b,c) - , e : invokable(a,b) - => function compose(f : d, g : e) -> t_closure1(a,b,c,d,e) { +function compose(f: d, g: e) returns (t_closure1) where d: invokable, e: invokable { return t_closure1(f,g); } -data t_closure1(a,b,c,d,e) = t_closure1(d,e); +enum t_closure1 { t_closure1(d, e) } -forall a b c d e . d : invokable(b,c), e : invokable(a,b) => - function lambda2(c : t_closure1(a,b,c,d,e), x : a) -> c { - match c { - | t_closure1(f, g) => - return invokable.invoke(f, invokable.invoke(g,x)); - } +function lambda2(c: t_closure1, x: a) returns (c) where d: invokable, e: invokable { + match (c) { +case t_closure1(f, g) { +return invokable.invoke(f, invokable.invoke(g,x)); +} +} } -forall a b c d e . d : invokable(b,c) - , e : invokable(a,b) - => instance t_closure1(a,b,c,d,e) : invokable(a,c) { - function invoke(self : t_closure1(a,b,c,d,e), args : a) -> c { +impl invokable, a, c> where d: invokable, e: invokable { + function invoke(self: t_closure1, args: a) returns (c) { return lambda2(self, args); } } -data t_id3(a) = t_id3 ; +enum t_id3 { t_id3 } -forall a . function id (x : a) -> a { +function id(x: a) returns (a) { return x; } -forall a . instance t_id3(a) : invokable(a,a) { - function invoke(self : t_id3(a), args : a) -> a { - match self { - | t_id3 => return id(args) ; - } +impl invokable, a, a> { + function invoke(self: t_id3, args: a) returns (a) { + match (self) { +case t_id3 { +return id(args) ; +} +} } } contract Foo { - public function main() -> word { + function main() public returns (word) { let f = compose(t_id3, t_id3); return invokable.invoke(f, 0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol index 17a2fcec..982605dd 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol @@ -1,20 +1,20 @@ -data Zero; -data Succ(a); +enum Zero {} +enum Succ {} -forall self res . class self:TAdd(res) {} -forall a . instance (Zero, a):TAdd(a) {} -forall a b c . (b, a):TAdd(c) => instance (Succ(b), a):TAdd(Succ(c)) {} +trait TAdd {} +impl TAdd<(Zero, a), a> {} +impl TAdd<(Succ, a), Succ> where (b, a): TAdd {} -forall lhs rhs . class lhs:Eq(rhs) {} -forall a . instance a:Eq(a) {} +trait Eq {} +impl Eq {} // this should work but doesnt: forall sizel sizer elem sizeout . (sizel, sizer):TAdd(sizeout) -forall sizel sizer elem sizeout pairSizelSizer . pairSizelSizer:Eq((sizel, sizer)), pairSizelSizer:TAdd(sizeout) => function concat(lhs:memory(array(sizel, elem)), rhs:memory(array(sizer, elem))) -> memory(array(sizeout, elem)) { - return memory(0) : memory(array(sizeout, elem)); // :D +function concat(lhs: memory>, rhs: memory>) returns (memory>) where pairSizelSizer: Eq<(sizel, sizer)>, pairSizelSizer: TAdd { + return memory(0) ; // :D } -data Itself(a) = ItselfRuntimeTag; +enum Itself { ItselfRuntimeTag } data array(size, elem) = array; data memory(a) = memory(word); From e5201092d4cbf339df455084861f15f8759904a6 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 050/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples Co-authored-by: Codex --- .../fail/test/examples/cases/const-array.sol | 65 ++--- .../contract-local-type-escapes-fail.sol | 16 +- .../fail/test/examples/cases/default-inst.sol | 19 +- .../cases/default-instance-missing.sol | 17 +- .../examples/cases/default-instance-weak.sol | 21 +- .../examples/cases/derive-unknown-class.sol | 8 +- .../fail/test/examples/cases/dispatch.sol | 232 ++++++++++-------- .../cases/dot-expression-no-context-fail.sol | 4 +- .../cases/dot-expression-unknown-fail.sol | 4 +- .../examples/cases/duplicated-type-name.sol | 4 +- .../examples/cases/fallback-with-args.snap | 6 +- .../examples/cases/fallback-with-args.sol | 6 +- .../examples/cases/fallback-with-return.snap | 11 +- .../examples/cases/fallback-with-return.sol | 6 +- .../fail/test/examples/cases/field-access.sol | 8 +- .../fail/test/examples/cases/for-let-post.sol | 4 +- .../cases/generic-manual-no-pragma.sol | 16 +- .../cases/generic-product-no-pragma.sol | 28 ++- .../examples/cases/generic-sum-no-pragma.sol | 40 +-- .../test/examples/cases/index-example.sol | 49 ++-- .../instance-closure-error-invalid-member.sol | 8 +- .../cases/instance-context-wrong-kind.sol | 6 +- .../examples/cases/instance-wrong-sig.sol | 22 +- .../fail/test/examples/cases/joinErr.sol | 34 ++- .../fail/test/examples/cases/listeq.sol | 8 +- .../fail/test/examples/cases/mainproxy.sol | 16 +- .../cases/match-compiler-undef-asm.sol | 13 +- .../test/examples/cases/missing-instance.sol | 18 +- .../test/examples/cases/nano-desugared.sol | 209 ++++++++-------- 29 files changed, 485 insertions(+), 413 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol index 982605dd..fca4449a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/const-array.sol @@ -16,25 +16,26 @@ function concat(lhs: memory { ItselfRuntimeTag } -data array(size, elem) = array; -data memory(a) = memory(word); +enum array { array } +enum memory { memory(word) } -forall self indexType elementType . class self:IndexAccessible (indexType, elementType){ +trait IndexAccessible { function set(self:self, ix:indexType, val:elementType); - function at(self:self, ix:indexType) -> elementType; + function at(self: self, ix: indexType) returns (elementType) ; } -forall self . class self:ToWord{ - function toWord(self:Itself(self)) -> word; +trait ToWord { + function toWord(self: Itself) returns (word) ; } -instance Zero : ToWord { - function toWord(zero) { return 0; } +impl ToWord { + function toWord(zero: Itself) { return 0; } } -forall prev . prev:ToWord => instance Succ(prev) : ToWord { - function toWord(self: Itself(Succ(prev))) { - let returnVal : word = ToWord.toWord(Itself.ItselfRuntimeTag:Itself(prev)); +impl ToWord> where prev: ToWord { + function toWord(self: Itself>) { + let prevTag : Itself = Itself.ItselfRuntimeTag; + let returnVal : word = ToWord.toWord(prevTag); assembly { returnVal := add(1, returnVal) } @@ -42,13 +43,13 @@ forall prev . prev:ToWord => instance Succ(prev) : ToWord { } } -forall self . class self:MemoryType { - function load(ptr:word) -> self; +trait MemoryType { + function load(ptr: word) returns (self) ; function store(ptr:word, value:self); } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let val : word; assembly { val := mload(ptr) } return val; @@ -58,9 +59,10 @@ instance word:MemoryType { } } -forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, elem)) : IndexAccessible(word, elem) { - function at(self, index) -> elem { - let sizeValue = ToWord.toWord(Itself.ItselfRuntimeTag:Itself(size)); +impl IndexAccessible>, word, elem> where size: ToWord, elem: MemoryType { + function at(self: memory>, index: word) returns (elem) { + let sizeTag : Itself = Itself.ItselfRuntimeTag; + let sizeValue = ToWord.toWord(sizeTag); // this should work but doesn't // assembly { // if iszero(lt(index, sizeValue)) { @@ -68,18 +70,20 @@ forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, // } //} - match self { - | memory(offset) => - let x = offset; // can't use this inside the assembly block :-( + match (self) { +case memory(offset) { +let x = offset; // can't use this inside the assembly block :-( assembly { index := add(x, mul(32, index)) } return MemoryType.load(index); - } +} +} } - function set(self, index, val) { - let sizeValue = ToWord.toWord(Itself.ItselfRuntimeTag:Itself(size)); + function set(self: memory>, index: word, val: elem) { + let sizeTag : Itself = Itself.ItselfRuntimeTag; + let sizeValue = ToWord.toWord(sizeTag); //assembly { // if iszero(lt(index, sizeValue)) { @@ -87,14 +91,15 @@ forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, // } //} - match self { - | memory(offset) => - let x = offset; // can't use this inside the assembly block :-( + match (self) { +case memory(offset) { +let x = offset; // can't use this inside the assembly block :-( assembly { index := add(x, mul(32, index)) } MemoryType.store(index, val); - } +} +} } } @@ -102,8 +107,8 @@ forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, contract Array { - public function main() { - let arr : memory(array(Succ(Succ(Succ(Succ(Zero)))), word)) = memory(42); // = (1,2,3,4,5,6,7,8,9,10); + function main() public { + let arr : memory>>>, word>> = memory(42); // = (1,2,3,4,5,6,7,8,9,10); IndexAccessible.set(arr, 4, 33); // this (correctly) typechecks but doesn't specialize diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.sol index 9ed8f249..6a082272 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/contract-local-type-escapes-fail.sol @@ -1,19 +1,21 @@ // A data type declared inside a contract is private to that contract: it may // not be referenced from outside. Qualification (A.Secret) keeps the bare name // `Secret` out of the top-level scope, so this must fail name resolution. -import std.{*}; +import * from std; contract A { - data Secret = S; + enum Secret { S } - public function useIt() -> word { - match Secret.S { - | Secret.S => return 1; - } + function useIt() public returns (word) { + match (Secret.S) { +case Secret.S { +return 1; +} +} } } // `Secret` is not in scope here — it belongs to contract A. -function leak(x : Secret) -> word { +function leak(x: Secret) returns (word) { return 0; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.sol index 0cd1b9e6..4ffebbde 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-inst.sol @@ -1,19 +1,18 @@ -class self:Test { function f(x:self); } +trait Test { function f(x:self); } -default instance a:Test { function f(x:self) {}} +default impl Test { function f(x:self) {}} -data memory(a) = memory(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum Proxy { Proxy } -instance memory(memory(word)):Test { function f(x:self) {}} +impl Test>> { function f(x:self) {}} -forall a. -function f(p:Proxy(a)) { - let x:memory(a); +function f(p: Proxy) { + let x:memory; Test.f(x); } function g() { - f(Proxy:Proxy(memory(memory(word)))); // needs to choose default instance in Test.f - f(Proxy:Proxy(memory(word))); // needs to choose concrete instance + f(@memory>); // needs to choose default instance in Test.f + f(@memory); // needs to choose concrete instance } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.sol index 59e710a2..84fe0a3e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-missing.sol @@ -1,17 +1,16 @@ -class self:Test { function f(x:self); } +trait Test { function f(x:self); } -data memory(a) = memory(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum Proxy { Proxy } -instance memory(memory(word)):Test { function f(x:self) {}} +impl Test>> { function f(x:self) {}} -forall a. -function f(p:Proxy(a)) { - let x:memory(a); +function f(p: Proxy) { + let x:memory; Test.f(x); } function g() { - f(Proxy:Proxy(memory(memory(word)))); // needs to choose default instance in Test.f - f(Proxy:Proxy(memory(word))); // needs to choose concrete instance + f(@memory>); // needs to choose default instance in Test.f + f(@memory); // needs to choose concrete instance } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.sol index a9002afa..a8c9b5a5 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/default-instance-weak.sol @@ -1,18 +1,17 @@ -class self:Test(weak) { function f(x:self) -> weak; } +trait Test { function f(x: self) returns (weak) ; } -data memory(a) = memory(word); -data Proxy(a) = Proxy; -data Bool = True | False; -default instance a:Test(word) { function f(x:a) -> word { return 42; }} +enum memory { memory(word) } +enum Proxy { Proxy } +enum Bool { True, False } +default impl Test { function f(x: a) returns (word) { return 42; }} -instance memory(memory(word)):Test(Bool) { function f(x:self) { return Bool.True; }} +impl Test>, Bool> { function f(x:self) returns (Bool) { return Bool.True; }} // If we choose the default instance to typecheck f, // this will pass type-checking, since ``r`` is word. // But: for a = memory(word), ``r`` will be ``bool`` and this is invalid! -forall a. -function f(p:Proxy(a)) { - let x:memory(a); +function f(p: Proxy) { + let x:memory; let r :word = Test.f(x); assembly { sstore(0, r) @@ -20,6 +19,6 @@ function f(p:Proxy(a)) { } function g() { - f(Proxy:Proxy(memory(memory(word)))); // valid, since default instance is used - f(Proxy:Proxy(memory(word))); // PROBLEM: now we have a bool cross the assembly barrier + f(@memory>); // valid, since default instance is used + f(@memory); // PROBLEM: now we have a bool cross the assembly barrier } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.sol index 41ff931a..123936df 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/derive-unknown-class.sol @@ -1,12 +1,12 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(NoSuchClass)] -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } -function useIt() -> bool { +function useIt() returns (bool) { return true; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.sol index f33527b9..d507db9f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dispatch.sol @@ -1,50 +1,50 @@ // --- Preliminaries --- -data Bool = True | False; -data Proxy(a) = Proxy; +enum Bool { True, False } +enum Proxy { Proxy } // --- Core Data Types --- // A contract contains a tuple of methods and a single fallback // TODO: implement receive() -data Contract(methods, fb) = Contract(methods,fb); +enum Contract { Contract(methods, fb) } // A method contains an implementation (fn) as well as it's name and type signature -data Method(name, args, rets, fn) = Method(name, args, rets, fn); +enum Method { Method(name, args, rets, fn) } // Contains the implementation for the fallback (fn) as well as it's type signature -data Fallback(args, rets, fn) = Fallback(args, rets, fn); +enum Fallback { Fallback(args, rets, fn) } // --- Method Selectors --- // For each method in a contract the compiler generates a unique type and // produces a `Selector` instance for that type that returns the selector hash -forall nm . class nm:Selector { - function hash(prx: Proxy(nm)) -> word; +trait Selector { + function hash(prx: Proxy) returns (word) ; } // Method has a Selector if its name has a Selector -forall name args rets fn . name:Selector => instance Method(name,args,rets,fn):Selector { - function hash(prx: Proxy(Method(name,args,rets,fn))) -> word { - return Selector.hash(Proxy : Proxy(name)); +impl Selector> where name: Selector { + function hash(prx: Proxy>) returns (word) { + return Selector.hash(@name); } } // --- Method Execution --- // Describes how to execute a given method / fallback -forall ty callvalueCheckStatus . class ty:ExecMethod { - function exec(x: ty, pstatus : Proxy(callvalueCheckStatus)) -> (); +trait ExecMethod { + function exec(x: ty, pstatus: Proxy) ; } // If fn matches the provided args/ret types, then we can execute any method -forall name args rets fn callvalueCheckStatus . fn:invokable(args,ret) => instance Method(name,Proxy(args),Proxy(rets),fn):ExecMethod { - function exec(m : Method(name,args,rets,fn), pstatus : Proxy(callvalueCheckStatus)) -> () { - match m { - | Method(nm,args,rets,fn) => - // check callvalue - MethodLevelCallvalueCheck.checkCallvalue(Proxy : Proxy(Method(name,args,rets,fn)), pstatus); +impl ExecMethod, Proxy, fn>> where fn: invokable { + function exec(m: Method, pstatus: Proxy) { + match (m) { +case Method(nm,args,rets,fn) { +// check callvalue + MethodLevelCallvalueCheck.checkCallvalue(@Method, pstatus); // check we have enough calldata for the head of args // abi decode args from calldata @@ -53,17 +53,18 @@ forall name args rets fn callvalueCheckStatus . fn:invokable(args,ret) => instan // returndata copy encoded returns // evm return return (); - } +} +} } } // If fn matches the provided args/ret types, then we can execute any fallback -forall args rets fn callvalueCheckStatus . fn:invokable(args,ret) => instance Fallback(Proxy(args),Proxy(rets),fn):ExecMethod { - function exec(fb : Fallback(args,rets,fn), pstatus : Proxy (callvalueCheckStatus)) -> () { - match fb { - | Fallback(args, rets, fn) => - // check callvalue - MethodLevelCallvalueCheck.checkCallvalue(Proxy : Proxy(Fallback(args,rets,fn)), pstatus); +impl ExecMethod, Proxy, fn>> where fn: invokable { + function exec(fb: Fallback, pstatus: Proxy) { + match (fb) { +case Fallback(args, rets, fn) { +// check callvalue + MethodLevelCallvalueCheck.checkCallvalue(@Fallback, pstatus); // check we have enough calldata for the head of args // abi decode args from calldata @@ -72,119 +73,142 @@ forall args rets fn callvalueCheckStatus . fn:invokable(args,ret) => instance Fa // returndata copy encoded returns // evm return return (); - } +} +} } } // --- Method Dispatch --- // For a given tuple of methods this executes the method specified by the first four bytes of calldata -forall ty callvalueCheckStatus . class ty:RunDispatch { - function go(methods : ty, pstatus : Proxy(callvalueCheckStatus)) -> (); +trait RunDispatch { + function go(methods: ty, pstatus: Proxy) ; } // We can dispatch to a single executable method with a known selector // TODO: do we need this instance? -forall m callvalueCheckStatus . m:ExecMethod, m:Selector => instance m:RunDispatch { - function go(method : m, pstatus : Proxy(callvalueCheckStatus)) -> () { - match selector_matches(Proxy : Proxy(m)) { - | Bool.True => ExecMethod.exec(method, pstatus); - | Bool.False => return (); - } +impl RunDispatch where m: ExecMethod, m: Selector { + function go(method: m, pstatus: Proxy) { + match (selector_matches(@m)) { +case Bool.True { +ExecMethod.exec(method, pstatus); +} +case Bool.False { +return (); +} +} } } // We can dispatch to a tuple of executable methods with a known selector -forall n m callvalueCheckStatus . n:ExecMethod, n:Selector, m:ExecMethod, m:Selector => instance (n,m):RunDispatch { - function go(methods : (n,m), pstatus : Proxy(callvalueCheckStatus)) -> () { - match methods { - | (method_n, method_m) => - match selector_matches(Proxy : Proxy(n)) { - | Bool.True => ExecMethod.exec(method_n); - | Bool.False => match selector_matches(Proxy : Proxy(m)) { - | Bool.True => ExecMethod.exec(method_m, pstatus); - | Bool.False => return (); - } - } - } +impl RunDispatch<(n, m)> where n: ExecMethod, n: Selector, m: ExecMethod, m: Selector { + function go(methods: (n, m), pstatus: Proxy) { + match (methods) { +case (method_n, method_m) { +match (selector_matches(@n)) { +case Bool.True { +ExecMethod.exec(method_n); +} +case Bool.False { +match (selector_matches(@m)) { +case Bool.True { +ExecMethod.exec(method_m, pstatus); +} +case Bool.False { +return (); +} +} +} +} +} +} } } // Recursive instance -forall n m callvalueCheckStatus . n:ExecMethod, n:Selector, m:RunDispatch => instance (n,m):RunDispatch { - function go(methods : (n,m), pstatus : Proxy(callvalueCheckStatus)) -> () { - match methods { - | (method_n, rest) => - match selector_matches(Proxy : Proxy(n)) { - | Bool.True => ExecMethod.exec(method_n, pstatus); - | Bool.False => RunDispatch.go(rest, pstatus); - } - } +impl RunDispatch<(n, m)> where n: ExecMethod, n: Selector, m: RunDispatch { + function go(methods: (n, m), pstatus: Proxy) { + match (methods) { +case (method_n, rest) { +match (selector_matches(@n)) { +case Bool.True { +ExecMethod.exec(method_n, pstatus); +} +case Bool.False { +RunDispatch.go(rest, pstatus); +} +} +} +} } } // TODO: we only wanna do the calldataload once // Given evidence of a name with a known selector, we can check if it matches the selector in the first four bytes of calldata -forall name . name:Selector => function selector_matches(prx : Proxy(name)) -> Bool { +function selector_matches(prx: Proxy) returns (Bool) where name: Selector { let hash = Selector.hash(prx); let res : word; assembly { let sel := shr(224, calldataload(0)) res := eq(sel, hash) } - match res { - | 0 => return Bool.False; - | _ => return Bool.True; - } + match (res) { +case 0 { +return Bool.False; +} +default { +return Bool.True; +} +} } // --- Callvalue Checks --- // If every method on a contract is non payable, we lift the callvalue check to run before method dispatch // NonPayable instances should be generated by the compiler as part of desugaring -forall ty . class ty:NonPayable {} -forall ty . class ty:AllNonPayable {} -forall n m . n:NonPayable, m:AllNonPayable => instance (n,m):AllNonPayable {} +trait NonPayable {} +trait AllNonPayable {} +impl AllNonPayable<(n, m)> where n: NonPayable, m: AllNonPayable {} -data CallvalueChecked; +enum CallvalueChecked {} -data CallvalueUnchecked; -forall ty . class ty:MethodsMustCheckCalldata {} -instance CallvalueUnchecked:MethodsMustCheckCalldata {} +enum CallvalueUnchecked {} +trait MethodsMustCheckCalldata {} +impl MethodsMustCheckCalldata {} // If every method is non payable we run the callvalue check before method dispatch -forall ty ret . class ty:TopLevelCallvalueCheck(ret) { - function checkCallvalue(prx : Proxy(ty)) -> Proxy(ret); +trait TopLevelCallvalueCheck { + function checkCallvalue(prx: Proxy) returns (Proxy) ; } -forall methods . default instance methods:TopLevelCallvalueCheck(CallvalueUnchecked) { - function checkCallvalue(prx : Proxy(methods)) -> Proxy(CallvalueUnchecked) { return Proxy : Proxy(CallvalueUnchecked); } +default impl TopLevelCallvalueCheck { + function checkCallvalue(prx: Proxy) returns (Proxy) { return @CallvalueUnchecked; } } -forall methods . methods:AllNonPayable => instance methods:TopLevelCallvalueCheck(CallvalueChecked) { - function checkCallvalue(prx : Proxy(methods)) -> Proxy(CallvalueChecked) { +impl TopLevelCallvalueCheck where methods: AllNonPayable { + function checkCallvalue(prx: Proxy) returns (Proxy) { assembly { if gt(callvalue(), 0) { mstore(0,0x2) revert(0,32) } } - return Proxy : Proxy(CallvalueChecked); + return @CallvalueChecked; } } // If only some methods are non payable, then we run the check during method execution -forall ty status . class ty:MethodLevelCallvalueCheck { - function checkCallvalue(pty : Proxy(ty), pstatus : Proxy(status)) -> (); +trait MethodLevelCallvalueCheck { + function checkCallvalue(pty: Proxy, pstatus: Proxy) ; } -forall method status . default instance method:MethodLevelCallvalueCheck { - function checkCallvalue(pty : Proxy(method), pstatus : Proxy(status)) -> () { } +default impl MethodLevelCallvalueCheck { + function checkCallvalue(pty: Proxy, pstatus: Proxy) { } } -forall method status . method:NonPayable, status:MethodsMustCheckCalldata => instance method:MethodLevelCallvalueCheck { - function checkCallvalue(pty : Proxy(method), pstatus : Proxy(status)) -> (){ +impl MethodLevelCallvalueCheck where method: NonPayable, status: MethodsMustCheckCalldata { + function checkCallvalue(pty: Proxy, pstatus: Proxy) { assembly { if gt(callvalue(), 0) { mstore(0, 0x1) @@ -197,22 +221,22 @@ forall method status . method:NonPayable, status:MethodsMustCheckCalldata => ins // --- Contract Execution --- // Describes how to execute a given contract -forall c . class c:RunContract { - function exec(v : c) -> (); +trait RunContract { + function exec(v: c) ; } // If we have a dispatch for the contracts methods, and we know how to execute it's fallback, then we can define an entrypoint -forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(methods, fb):RunContract { - function exec(c : Contract(methods, fb)) -> () { - match c { - | Contract(ms, fb) => - // set free memory pointer to the output of memoryguard +impl RunContract> where methods: RunDispatch, fb: ExecMethod { + function exec(c: Contract) { + match (c) { +case Contract(ms, fb) { +// set free memory pointer to the output of memoryguard // https://docs.soliditylang.org/en/v0.8.30/yul.html#memoryguard // TODO: we will need to consider immutables here at some point... // assembly { mstore(0x40, memoryguard(128)) } // if all methods are non payable then check callvalue - let callvalueChecked = TopLevelCallvalueCheck.checkCallvalue(Proxy : Proxy((fb, methods))); + let callvalueChecked = TopLevelCallvalueCheck.checkCallvalue(@(fb, methods)); // check that we have at least 4 bytes of calldata let haveSelector : word; @@ -220,15 +244,19 @@ forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(meth haveSelector := lt(3, calldatasize()) } - match haveSelector { - | 0 => assembly { revert(0,0) } - | _ => - // dispatch to method based on selector + match (haveSelector) { +case 0 { +assembly { revert(0,0) } +} +default { +// dispatch to method based on selector RunDispatch.go(ms, callvalueChecked); // run fallback if no methods matched ExecMethod.exec(fb); - } - } +} +} +} +} } } @@ -236,14 +264,14 @@ forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(meth // compiler generated -function revert_handler() -> () { +function revert_handler() { assembly { revert(0,0) } } -data C_Add2_Selector = C_Add2_Selector; +enum C_Add2_Selector { C_Add2_Selector } -instance C_Add2_Selector:Selector { - function hash(prx: Proxy(C_Add2_Selector)) -> word { +impl Selector { + function hash(prx: Proxy) returns (word) { // This would be keccak256("add2(uint256,uint256)") >> 224 // Compiler computes this at compile time return 0x29fcda33; // placeholder value @@ -253,16 +281,16 @@ instance C_Add2_Selector:Selector { // transform contract C { - public function add2(x : word, y : word) -> word { + function add2(x: word, y: word) public returns (word) { let ret : word; assembly { ret := add(x,y) } return ret; } - public function main() -> word { + function main() public returns (word) { let c = Contract( - Method(C_Add2_Selector, Proxy : Proxy((word,word)), Proxy : Proxy(word), add2), - Fallback(Proxy : Proxy(()),Proxy : Proxy(()),revert_handler) + Method(C_Add2_Selector, @(word, word), @word, add2), + Fallback(@(),@(),revert_handler) ); RunContract.exec(c); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.sol index 485ed798..6472dc4e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-no-context-fail.sol @@ -1,6 +1,6 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function bad() -> Option { +function bad() returns (Option) { let x = .Some(1); return x; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.sol index 11ab2af7..6a44271a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/dot-expression-unknown-fail.sol @@ -1,5 +1,5 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function bad() -> Option { +function bad() returns (Option) { return .Nope(1); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.sol index 18627795..c5164fba 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/duplicated-type-name.sol @@ -1,5 +1,5 @@ -data Foo = Bar; -data Foo = Baz; +enum Foo { Bar } +enum Foo { Baz } function main() { let x = Foo.Baz; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.snap index 6e6585c5..86797ab7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.snap @@ -1,13 +1,13 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol --- error[SC0001]: fallback function must not declare input parameters - --> /fallback-with-args.solc:7:13 + --> /fallback-with-args.sol:7:13 | 6 | -7 | fallback(x: uint256) -> () { +7 | fallback(x: uint256) { | ^^^^^^^^^^^^ 8 | revert("fallback-was-called"); | diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol index 59387aed..0cda10a8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-args.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract BadFallback { constructor() {} - fallback(x: uint256) -> () { + fallback(x: uint256) { revert("fallback-was-called"); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.snap index d9026f8e..c8bc231a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.snap @@ -1,14 +1,15 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol --- -error[SC0001]: fallback function must return unit (`()`) - --> /fallback-with-return.solc:7:19 +error[SC0001]: parse error: unexpected identifier `returns` + --> /fallback-with-return.sol:7:16 | 6 | -7 | fallback() -> uint256 { - | ^^^^^^^ +7 | fallback() returns (uint256) { + | ^^^^^^^ unexpected token 8 | return uint256(0); | + = note: expecting `payable`, `public`, or `{` = note: while parsing fallback definition diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol index ca9e5223..3fa6df89 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/fallback-with-return.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract BadFallback { constructor() {} - fallback() -> uint256 { + fallback() returns (uint256) { return uint256(0); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.sol index b53e151f..1f61323e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/field-access.sol @@ -1,18 +1,18 @@ -import std.{*}; +import * from std; contract PoC { field : word; - public function set_x(b: bool) -> bool { + function set_x(b: bool) public returns (bool) { field = b; // BUG: `word` shouldn't be unified with `bool`. return b; } - public function init(foo: bool) -> () { + function init(foo: bool) public { field = 2; } - public function main () -> () { + function main() public { } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.sol index a7f1b11d..a1f8ae93 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/for-let-post.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract C { - public function main() -> word { + function main() public returns (word) { let i : word = 0; let s : word = 99; for(i=0;i<=0;let j=1) { s = j; i = i + 1; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.sol index 6551643c..b1b27c71 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-manual-no-pragma.sol @@ -1,18 +1,22 @@ // Error case: manual Generic instance without pragma no-generic-instance-for. // The compiler must reject this with a conflict error. -import std.Generic.{*}; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; -data Foo = MkFoo(word); +enum Foo { MkFoo(word) } -instance Foo : Generic(word) { - function from(x : Foo) -> word { - match x { | Foo.MkFoo(v) => return v; } +impl Generic { + function from(x: Foo) returns (word) { + match (x) { +case Foo.MkFoo(v) { +return v; +} +} } - function to(v : word) -> Foo { + function to(v: word) returns (Foo) { return Foo.MkFoo(v); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.sol index bb2fb4db..69b8580e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-product-no-pragma.sol @@ -1,21 +1,29 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-patterson-condition; pragma no-coverage-condition; pragma no-bounded-variable-condition; -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } // Manual Generic instance without pragma no-generic-instance-for Point. // The compiler must reject this with a conflict error. -instance Point : Generic((uint256, uint256)) { - function from(p : Point) -> (uint256, uint256) { - match p { | Point(x, y) => return (x, y); } +impl Generic { + function from(p: Point) returns (uint256, uint256) { + match (p) { +case Point(x, y) { +return (x, y); +} +} } - function to(t : (uint256, uint256)) -> Point { - match t { | (x, y) => return Point(x, y); } + function to(t: (uint256, uint256)) returns (Point) { + match (t) { +case (x, y) { +return Point(x, y); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.sol index 49923afb..3d04cb34 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/generic-sum-no-pragma.sol @@ -1,27 +1,35 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-patterson-condition; pragma no-coverage-condition; pragma no-bounded-variable-condition; -data Option(a) = None | Some(a); +enum Option { None, Some(a) } // Manual Generic instance without pragma no-generic-instance-for Option. // The compiler must reject this with a conflict error. -instance Option(uint256) : Generic(sum((), uint256)) { - function from(x : Option(uint256)) -> sum((), uint256) { - match x { - | Option.None => return inl(()); - | Option.Some(v) => return inr(v); - } +impl Generic, sum<(), uint256>> { + function from(x: Option) returns (sum<(), uint256>) { + match (x) { +case Option.None { +return inl(()); +} +case Option.Some(v) { +return inr(v); +} +} } - function to(r : sum((), uint256)) -> Option(uint256) { - match r { - | inl(_) => return Option.None; - | inr(v) => return Option.Some(v); - } + function to(r: sum<(), uint256>) returns (Option) { + match (r) { +case inl(_) { +return Option.None; +} +case inr(v) { +return Option.Some(v); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.sol index db138d6c..787433c2 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/index-example.sol @@ -1,38 +1,36 @@ -data storage(a) = storage(word); -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storage { storage(word) } +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -data mapping(member, index) = mapping(word, Proxy(member), Proxy(index)); // storage by default +enum mapping { mapping(word, Proxy, Proxy) } // storage by default // data mapRef(a) = mapRef(word); //ref to a map elem -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -forall a . instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) { +impl Assign, a> { + function assign(l:storageRef, y:a) { } } -forall self fieldType offsetType . class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall self memberRefType . class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } // ------------------------------------------------------------------ // Contract field access // ------------------------------------------------------------------ -forall cxt fieldSelector fieldType offsetType - . StructField(cxt, fieldSelector):CStructField(fieldType, offsetType) - => instance MemberAccessProxy(cxt, fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(cxt, fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, storageRef> where StructField: CStructField { + function memberAccess(x: MemberAccessProxy) returns (storageRef) { return storageRef(0x100); } } @@ -41,20 +39,19 @@ forall cxt fieldSelector fieldType offsetType // Indexed access // ------------------------------------------------------------------ -data mapping(index, member) = mapping(word); -data IndexAccessProxy(map, index, member) = IndexAccessProxy(map, index); -data IndexAccessProxy2(map, index, member) = IndexAccessProxy2(map, index, Proxy(member)); +enum mapping { mapping(word) } +enum IndexAccessProxy { IndexAccessProxy(map, index) } +enum IndexAccessProxy2 { IndexAccessProxy2(map, index, Proxy) } -forall map index member. - instance IndexAccessProxy(storageRef(mapping(index,member)), index, member):LValueMemberAccess(storageRef(member)) { - function memberAccess(x:IndexAccessProxy(storageRef(map), index, member)) -> storageRef(member) { +impl LValueMemberAccess member)>, index, member>, storageRef> { + function memberAccess(x: IndexAccessProxy, index, member>) returns (storageRef) { return storageRef(0); } } -data MintCtx = MintCtx; -data balances_sel = balances_sel; -instance StructField(MintCtx, balances_sel):CStructField(mapping(word,word), ()) {} +enum MintCtx { MintCtx } +enum balances_sel { balances_sel } +impl CStructField, mapping(word => word), ()> {} function mint(amount:word) { let bal_prx = MemberAccessProxy(MintCtx, balances_sel); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.sol index ecd0fc2a..3e72850d 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-closure-error-invalid-member.sol @@ -1,9 +1,9 @@ -forall t . class t:CtFun { - function ct(x : t) -> ((t) -> t); +trait CtFun { + function ct(x: t) returns (function(t) returns (t)) ; } -instance word:CtFun { - function ct(x : word) -> ((word) -> word) { +impl CtFun { + function ct(x: word) returns (function(word) returns (word)) { return lam(y : bool) { return x; }; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.sol index 8487114f..a8e6a0ed 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-context-wrong-kind.sol @@ -1,5 +1,5 @@ -forall a b . class a : Foo(b) {} +trait Foo {} -forall a. class a:C {} +trait C {} -forall t. t:Foo => instance (word,t):C {} +impl C<(word, t)> where t: Foo {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.sol index ea5b8d7e..7623901a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/instance-wrong-sig.sol @@ -1,15 +1,15 @@ -data uint256 = uint256(word); -data Proxy(a) = Proxy; -forall self . class self:ABIAttribs { - function headSize(ty:Proxy(self)) -> word; - function isStatic(ty:Proxy(self)) -> bool; +enum uint256 { uint256(word) } +enum Proxy { Proxy } +trait ABIAttribs { + function headSize(ty: Proxy) returns (word) ; + function isStatic(ty: Proxy) returns (bool) ; } -instance ():ABIAttribs { - function headSize(ty : Proxy(uint256)) -> word { return 0; } - function isStatic(ty : Proxy(uint256)) -> bool { return true; } +impl ABIAttribs<()> { + function headSize(ty: Proxy) returns (word) { return 0; } + function isStatic(ty: Proxy) returns (bool) { return true; } } -instance uint256:ABIAttribs { - function headSize(ty : Proxy(uint256)) -> word { return 32; } - function isStatic(ty : Proxy(uint256)) -> bool { return true; } +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return true; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.sol index 6ae54697..d6729bf2 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/joinErr.sol @@ -1,25 +1,33 @@ contract Option { - data Option(a) = None | Some(a); - data Bool = False | True; + enum Option { None, Some(a) } + enum Bool { False, True } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { + function join(mmx: Option>) public returns (Option) { let result = Option.None; - match mmx { - | Option.Some(Option.Some(x)) => result = Option.Some(x); - | Option.None => result = Option.None; - } + match (mmx) { +case Option.Some(Option.Some(x)) { +result = Option.Some(x); +} +case Option.None { +result = Option.None; +} +} return result; } - public function main() -> word { + function main() public returns (word) { return maybe(0, join(Option.Some(Option.Some(Bool.False)))); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.sol index 21299f76..6f2f5494 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/listeq.sol @@ -1,8 +1,8 @@ -data List(a) = Nil | Cons(a,List(a)); -data Bool = False | True; +enum List { Nil, Cons(a, List) } +enum Bool { False, True } -forall a . class a : Eq { - function eq (x : a, y : a) -> Bool ; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } function foo () { diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.sol index 1e3f5c87..b7a7b38b 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/mainproxy.sol @@ -1,22 +1,22 @@ -data Proxy(a) = Proxy; +enum Proxy { Proxy } -class self:BaseMemoryType { - function memorySize(x:Proxy(self)) -> word; +trait BaseMemoryType { + function memorySize(x: Proxy) returns (word) ; } -instance word:BaseMemoryType { - function memorySize(x:Proxy(self)) -> word { +impl BaseMemoryType { + function memorySize(x: Proxy) returns (word) { return 32; } } -function morefun(p:Proxy(t)) -> word { return BaseMemoryType.memorySize(Proxy:Proxy(t)); +function morefun(p: Proxy) returns (word) { return BaseMemoryType.memorySize(@t); } contract TestMemoryType { - public function main() -> word { - return morefun(Proxy:Proxy(word)); + function main() public returns (word) { + return morefun(@word); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.sol index 28b89fdc..e9e7b2a4 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/match-compiler-undef-asm.sol @@ -1,19 +1,20 @@ -data Foo(a) = Foo(word); +enum Foo { Foo(word) } -forall a . function read(x : Foo(a)) -> word { +function read(x: Foo) returns (word) { let res : word; match (x) { - | Foo(w) => - assembly { +case Foo(w) { +assembly { res := w } - } +} +} return res; } contract Bla { - public function main () -> word { + function main() public returns (word) { return read(Foo(42)); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.sol index 6bdaf00a..b41d8bb6 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/missing-instance.sol @@ -1,23 +1,23 @@ // Note: this class has no instances! -forall abs rep . class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -forall self . class self:MemoryType { - function load(ptr:word) -> self; +trait MemoryType { + function load(ptr: word) returns (self) ; } -instance word:MemoryType { - function load(ptr:word) -> word { - return Typedef.abs(MemoryType.load(ptr) : word); +impl MemoryType { + function load(ptr: word) returns (word) { + return Typedef.abs(MemoryType.load(ptr) ); // `abs` does not make sense here, but it triggers the bug: // the typechecker should complain about missing instance here } } contract C { - public function main() -> word { + function main() public returns (word) { let ptr : word = 0; // if we inline the let below into return then another bug occurs: main is typed as forall a. () -> a // let w:word = MemoryType.load(0); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol index 055dc9f8..76a9968b 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol @@ -1,16 +1,16 @@ -function addW (x : word, y : word) { +function addW (x : word, y : word) returns (word) { let res : word ; assembly { res := add(x, y) } return res; } -function subW (x : word, y : word) { +function subW (x : word, y : word) returns (word) { let res : word ; assembly { res := sub(x, y) } return res; } -function addU (x : uint, y : uint) -> uint { +function addU(x: uint, y: uint) returns (uint) { let res : word ; let xw : word = Num.toWord(x) ; let yw : word = Num.toWord(y) ; @@ -18,14 +18,14 @@ function addU (x : uint, y : uint) -> uint { } return uint(res); } -function hash1 (x : word) -> word { +function hash1(x: word) returns (word) { let result : word = 0 ; assembly { mstore(0, x) result := keccak256(0, 32) } return result; } -function hash2 (x : word, y : word) -> word { +function hash2(x: word, y: word) returns (word) { let result : word = 0 ; assembly { mstore(0, x) mstore(32, y) @@ -33,170 +33,183 @@ function hash2 (x : word, y : word) -> word { } return result; } -data Bool = False | True ; -function not (b : Bool) -> Bool { +enum Bool { False, True } +function not(b: Bool) returns (Bool) { match (b) { - | Bool.False => - return Bool.True; - | Bool.True => - return Bool.False; - } +case Bool.False { +return Bool.True; +} +case Bool.True { +return Bool.False; +} } -function or (x : Bool, y : Bool) -> Bool { +} +function or(x: Bool, y: Bool) returns (Bool) { match (x) { - | Bool.False => - return y; - | Bool.True => - return Bool.True; - } +case Bool.False { +return y; } -function fromBool (b) { +case Bool.True { +return Bool.True; +} +} +} +function fromBool (b: Bool) returns (word) { match (b) { - | Bool.False => - return 0; - | Bool.True => - return 1; - } +case Bool.False { +return 0; +} +case Bool.True { +return 1; } -function toBool (x : word) { +} +} +function toBool (x : word) returns (Bool) { match (x) { - | 0 => - return Bool.False; - | _ => - return Bool.True; - } +case 0 { +return Bool.False; +} +default { +return Bool.True; +} } -forall a . class a : Num { - function toWord (x : a) -> word; - function fromWord (x : word) -> a; - function add (x : a, y : a) -> a; - function sub (x : a, y : a) -> a; - function eq (x : a, y : a) -> Bool; - function gt (x : a, y : a) -> Bool; } -instance word : Num { - function toWord (x : word) -> word { +trait Num { + function toWord(x: a) returns (word) ; + function fromWord(x: word) returns (a) ; + function add(x: a, y: a) returns (a) ; + function sub(x: a, y: a) returns (a) ; + function eq(x: a, y: a) returns (Bool) ; + function gt(x: a, y: a) returns (Bool) ; +} +impl Num { + function toWord(x: word) returns (word) { return x; } - function fromWord (x : word) -> word { + function fromWord(x: word) returns (word) { return x; } - function add (x : word, y : word) -> word { + function add(x: word, y: word) returns (word) { return addW(x, y); } - function sub (x : word, y : word) -> word { + function sub(x: word, y: word) returns (word) { return addW(x, y); } - function eq (x : word, y : word) -> Bool { + function eq(x: word, y: word) returns (Bool) { let res : word ; assembly { res := eq(x, y) } return toBool(res); } - function gt (x : word, y : word) -> Bool { + function gt(x: word, y: word) returns (Bool) { let res : word ; assembly { res := gt(x, y) } return toBool(res); } } -forall a . a : Num => function ge (x : a, y : a) -> Bool { +function ge(x: a, y: a) returns (Bool) where a: Num { return or(Num.gt(x, y), Num.eq(x, y)); } -data uint = uint(word) ; -instance uint : Num { - function toWord (x : uint) -> word { +enum uint { uint(word) } +impl Num { + function toWord(x: uint) returns (word) { match (x) { - | uint(y) => - return y; - } +case uint(y) { +return y; +} +} } - function fromWord (x : word) -> uint { + function fromWord(x: word) returns (uint) { return uint(x); } - function add (x : uint, y : uint) -> uint { + function add(x: uint, y: uint) returns (uint) { return uint(addW(Num.toWord(x), Num.toWord(y))); } - function sub (x : uint, y : uint) -> uint { + function sub(x: uint, y: uint) returns (uint) { return uint(subW(Num.toWord(x), Num.toWord(y))); } - function eq (x : uint, y : uint) -> Bool { + function eq(x: uint, y: uint) returns (Bool) { return Num.eq(Num.toWord(x), Num.toWord(y)); } - function gt (x : uint, y : uint) -> Bool { + function gt(x: uint, y: uint) returns (Bool) { return Num.gt(Num.toWord(x), Num.toWord(y)); } } -forall abs rep . class abs : Typedef (rep) { - function rep (x : abs) -> rep; - function abs (x : rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -instance word : Typedef (word) { - function rep (x : word) -> word { +impl Typedef { + function rep(x: word) returns (word) { return x; } - function abs (x : word) -> word { + function abs(x: word) returns (word) { return x; } } -instance uint : Typedef (word) { - function rep (x : uint) -> word { +impl Typedef { + function rep(x: uint) returns (word) { match (x) { - | uint(y) => - return y; - } +case uint(y) { +return y; +} +} } - function abs (x : word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data address = address(word) ; -instance address : Typedef (word) { - function rep (x : address) -> word { +enum address { address(word) } +impl Typedef { + function rep(x: address) returns (word) { match (x) { - | address(y) => - return y; - } +case address(y) { +return y; +} +} } - function abs (x : word) -> address { + function abs(x: word) returns (address) { return address(x); } } -data storage (a) = storage(word) ; -data ContractStorage (cxt) = ContractStorage(cxt) ; -data storageRef (a) = storageRef(word) ; -data Proxy (a) = Proxy ; -data mapping (member, index) = mapping(word, Proxy(member), Proxy(index)) ; -data mapRef (a) = mapRef(word) ; -forall a . instance storage(a) : Typedef (word) { - function rep (x : storage(a)) -> word { +enum storage { storage(word) } +enum ContractStorage { ContractStorage(cxt) } +enum storageRef { storageRef(word) } +enum Proxy { Proxy } +enum mapping { mapping(word, Proxy, Proxy) } +enum mapRef { mapRef(word) } +impl Typedef, word> { + function rep(x: storage) returns (word) { match (x) { - | storage(y) => - return y; - } +case storage(y) { +return y; +} +} } - function abs (x : word) -> storage(a) { + function abs(x: word) returns (storage) { return storage(x); } } -forall a . instance storageRef(a) : Typedef (word) { - function rep (x : storageRef(a)) -> word { +impl Typedef, word> { + function rep(x: storageRef) returns (word) { match (x) { - | storageRef(y) => - return y; - } +case storageRef(y) { +return y; +} +} } - function abs (x : word) -> storageRef(a) { + function abs(x: word) returns (storageRef) { return storageRef(x); } } -forall lhs rhs . class lhs : Assign (rhs) { - function assign (l : lhs, r : rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref (a) = ref(a) ; -forall a . instance ref(a) : Assign (a) { - function assign (l : ref(a), r : a) -> () { +enum ref { ref(a) } +impl Assign, a> { + function assign(l: ref, r: a) { return (); } } From 922a20fc0b89478d17513526af21006b0870b5a0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 051/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples Co-authored-by: Codex --- .../test/examples/cases/nano-desugared.sol | 207 ++++++++-------- .../fail/test/examples/cases/noconstr.sol | 8 +- .../cases/overlap-synonym-detected.sol | 12 +- .../cases/overlap-synonym-missed-order.sol | 12 +- .../overlap-synonym-missed-two-synonyms.sol | 12 +- .../test/examples/cases/overlapping-heads.sol | 12 +- .../test/examples/cases/patterson-bug.sol | 49 ++-- .../cases/payable-toplevel-function.snap | 8 +- .../cases/payable-toplevel-function.sol | 2 +- .../cases/pragma_merge_fail_coverage.sol | 8 +- .../cases/pragma_merge_fail_patterson.sol | 4 +- .../examples/cases/pragma_merge_import.sol | 12 +- .../examples/cases/pragma_merge_verify.sol | 6 +- .../fail/test/examples/cases/proxy1.sol | 10 +- .../examples/cases/public-constructor.snap | 8 +- .../examples/cases/public-constructor.sol | 8 +- .../test/examples/cases/public-fallback.snap | 8 +- .../test/examples/cases/public-fallback.sol | 6 +- .../cases/public-top-level-function.snap | 8 +- .../cases/public-top-level-function.sol | 6 +- .../examples/cases/reference-encoding.sol | 173 ++++++------- .../test/examples/cases/reference-test.sol | 55 +++-- .../fail/test/examples/cases/reference.sol | 28 +-- .../test/examples/cases/references-daniel.sol | 232 +++++++++--------- .../require-annotation-contract-method.sol | 4 +- 25 files changed, 459 insertions(+), 439 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol index 76a9968b..d8761ebe 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/nano-desugared.sol @@ -213,14 +213,14 @@ impl Assign, a> { return (); } } -forall self . class self : StorageType { - function sload (ptr : word) -> self; - function store (ptr : word, value : self) -> (); +trait StorageType { + function sload(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -forall self . class self : StorageSize { - function size (x : Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -function sload_ (x : word) -> word { +function sload_(x: word) returns (word) { let res : word ; assembly { res := sload(x) } @@ -230,151 +230,154 @@ function sstore_ (a : word, v : word) { assembly { sstore(a, v) } } -instance word : StorageType { - function sload (ptr : word) -> word { +impl StorageType { + function sload(ptr: word) returns (word) { let r : word ; assembly { r := sload(ptr) } return r; } - function store (ptr : word, value : word) -> () { + function store(ptr: word, value: word) { assembly { sstore(ptr, value) } } } -instance uint : StorageType { - function sload (ptr : word) -> uint { - return Typedef.abs(sload_(ptr)) : uint; +impl StorageType { + function sload(ptr: word) returns (uint) { + return Typedef.abs(sload_(ptr)) ; } - function store (ptr : word, value : uint) -> () { + function store(ptr: word, value: uint) { return sstore_(ptr, Typedef.rep(value)); } } -instance address : StorageType { - function sload (ptr : word) -> address { - return Typedef.abs(sload_(ptr)) : address; +impl StorageType
{ + function sload(ptr: word) returns (address) { + return Typedef.abs(sload_(ptr)) ; } - function store (ptr : word, value : address) -> () { + function store(ptr: word, value: address) { return sstore_(ptr, Typedef.rep(value)); } } -forall a . a : StorageType => instance storageRef(a) : Assign (a) { - function assign (l : storageRef(a), y : a) -> () { +impl Assign, a> where a: StorageType { + function assign(l: storageRef, y: a) { StorageType.store(Typedef.rep(l), y); } } -forall self fieldType offsetType . class self :CStructField(fieldType, offsetType) { +trait CStructField { } -data StructField (structType, fieldSelector) = StructField(structType) ; -data MemberAccessProxy (a, field, offset) = MemberAccessProxy(a, field) ; -forall a field offset . function memberAccessD1 (x : MemberAccessProxy(a, field, offset)) -> a { +enum StructField { StructField(structType) } +enum MemberAccessProxy { MemberAccessProxy(a, field) } +function memberAccessD1(x: MemberAccessProxy) returns (a) { match (x) { - | MemberAccessProxy(y, z) => - return y; - } +case MemberAccessProxy(y, z) { +return y; +} } -forall self memberRefType . class self : LValueMemberAccess (memberRefType) { - function memberAccess (x : self) -> memberRefType; } -forall self memberValueType . class self : RValueMemberAccess (memberValueType) { - function memberAccess (x : self) -> memberValueType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector) :CStructField(fieldType, offsetType), offsetType : StorageSize => instance MemberAccessProxy(storage(structType), fieldSelector, offsetType) : LValueMemberAccess (storageRef(fieldType)) { - function memberAccess (x : MemberAccessProxy(storage(structType), fieldSelector, offsetType)) -> storageRef(fieldType) { +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; +} +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr : word = Typedef.rep(memberAccessD1(x)) ; - let size : word = StorageSize.size(Proxy : Proxy(offsetType)) ; + let size : word = StorageSize.size(@offsetType) ; assembly { ptr := add(ptr, size) } return storageRef(ptr); } } -instance () : StorageSize { - function size (x : Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word : StorageSize { - function size (x : Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance uint : StorageSize { - function size (x : Proxy(uint)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance address : StorageSize { - function size (x : Proxy(address)) -> word { +impl StorageSize
{ + function size(x: Proxy
) returns (word) { return 1; } } -forall a b . a : StorageSize, b : StorageSize => instance (a, b) : StorageSize { - function size (x : Proxy((a, b))) -> word { - let a_sz : word = StorageSize.size(Proxy : Proxy(a)) ; - let b_sz : word = StorageSize.size(Proxy : Proxy(b)) ; +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz : word = StorageSize.size(@a) ; + let b_sz : word = StorageSize.size(@b) ; assembly { a_sz := add(a_sz, b_sz) } return a_sz; } } -forall cxt fieldSelector fieldType offsetType . StructField(ContractStorage(cxt), fieldSelector) :CStructField(fieldType, offsetType), offsetType : StorageSize => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType) : LValueMemberAccess (storageRef(fieldType)) { - function memberAccess (x : MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField, fieldSelector>: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr : word = 256 ; - let offsetSize : word = StorageSize.size(Proxy : Proxy(offsetType)) ; + let offsetSize : word = StorageSize.size(@offsetType) ; assembly { ptr := add(ptr, offsetSize) } return storageRef(ptr); } } -forall cxt fieldSelector fieldType offsetType . StructField(ContractStorage(cxt), fieldSelector) :CStructField(fieldType, offsetType), fieldType : StorageType, offsetType : StorageSize => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType) : RValueMemberAccess (fieldType) { - function memberAccess (x : MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField, fieldSelector>: CStructField, fieldType: StorageType, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr : word = 256 ; - let offsetSize : word = StorageSize.size(Proxy : Proxy(offsetType)) ; - return StorageType.sload(addW(ptr, offsetSize)) : fieldType; + let offsetSize : word = StorageSize.size(@offsetType) ; + return StorageType.sload(addW(ptr, offsetSize)) ; } } -data mapping (index, member) = mapping(word) ; -forall member index . instance mapping(index, member) : Typedef (word) { - function rep (x : mapping(index, member)) -> word { +enum mapping { mapping(word) } +impl Typedef member), word> { + function rep(x: mapping(index => member)) returns (word) { match (x) { - | mapping(y) => - return y; - } +case mapping(y) { +return y; +} +} } - function abs (x : word) -> mapping(index, member) { + function abs(x: word) returns (mapping(index => member)) { return mapping(x); } } -forall index member . instance mapping(index, member) : StorageSize { - function size (x : Proxy(mapping(index, member))) -> word { +impl StorageSize member)> { + function size(x: Proxy member)>) returns (word) { return 1; } } -data IndexAccessProxy (map, index, member) = IndexAccessProxy(map, index) ; -forall index member . index : Typedef (word) => instance IndexAccessProxy(storageRef(mapping(index, member)), index, member) : LValueMemberAccess (storageRef(member)) { - function memberAccess (x : IndexAccessProxy(storageRef(mapping(index, member)), index, member)) -> storageRef(member) { +enum IndexAccessProxy { IndexAccessProxy(map, index) } +impl LValueMemberAccess member)>, index, member>, storageRef> where index: Typedef { + function memberAccess(x: IndexAccessProxy member)>, index, member>) returns (storageRef) { return storageRef(indexStorageSlot(x)); } } -forall map index member . index : Typedef (word), member : StorageType, map : Typedef (word) => instance IndexAccessProxy(map, index, member) : RValueMemberAccess (member) { - function memberAccess (x : IndexAccessProxy(map, index, member)) -> member { +impl RValueMemberAccess, member> where index: Typedef, member: StorageType, map: Typedef { + function memberAccess(x: IndexAccessProxy) returns (member) { let slot : word = indexStorageSlot(x) ; return StorageType.sload(slot); } } -forall index map member . map : Typedef (word), index : Typedef (word) => function indexStorageSlot (x : IndexAccessProxy(map, index, member)) -> word { +function indexStorageSlot(x: IndexAccessProxy) returns (word) where map: Typedef, index: Typedef { match (x) { - | IndexAccessProxy(map, i) => - let mapptr : word = Typedef.rep(map) ; +case IndexAccessProxy(map, i) { +let mapptr : word = Typedef.rep(map) ; let rawidx : word = Typedef.rep(i) ; let loc : word = hash2(mapptr, rawidx) ; return loc; - } } -forall a b . a : RValueMemberAccess (b) => function rval (x : a) -> b { +} +} +function rval(x: a) returns (b) where a: RValueMemberAccess { return RValueMemberAccess.memberAccess(x); } -function caller () -> address { +function caller() returns (address) { let res : word ; assembly { res := caller() } @@ -389,64 +392,66 @@ function require1fail () { } function require1 (cond : Bool) { match (cond) { - | Bool.False => - return require1fail(); - | Bool.True => - return (); - } +case Bool.False { +return require1fail(); +} +case Bool.True { +return (); +} +} } -function nop () -> () { +function nop() { return (); } -data UintCxt = UintCxt ; -data reserved_sel = reserved_sel ; -instance StructField(ContractStorage(UintCxt), reserved_sel) :CStructField(word, ()) { +enum UintCxt { UintCxt } +enum reserved_sel { reserved_sel } +impl CStructField, reserved_sel>, word, ()> { } -data msg_sender_sel = msg_sender_sel ; -instance StructField(ContractStorage(UintCxt), msg_sender_sel) :CStructField(address, (word, ())) { +enum msg_sender_sel { msg_sender_sel } +impl CStructField, msg_sender_sel>, address, (word, ())> { } -data owner_sel = owner_sel ; -instance StructField(ContractStorage(UintCxt), owner_sel) :CStructField(address, (word, (address, ()))) { +enum owner_sel { owner_sel } +impl CStructField, owner_sel>, address, (word, (address, ()))> { } -data decimals_sel = decimals_sel ; -instance StructField(ContractStorage(UintCxt), decimals_sel) :CStructField(uint, (word, (address, (address, ())))) { +enum decimals_sel { decimals_sel } +impl CStructField, decimals_sel>, uint, (word, (address, (address, ())))> { } -data totalSupply_sel = totalSupply_sel ; -instance StructField(ContractStorage(UintCxt), totalSupply_sel) :CStructField(uint, (word, (address, (address, (uint, ()))))) { +enum totalSupply_sel { totalSupply_sel } +impl CStructField, totalSupply_sel>, uint, (word, (address, (address, (uint, ()))))> { } -data balances_sel = balances_sel ; -instance StructField(ContractStorage(UintCxt), balances_sel) :CStructField(mapping(address, uint), (word, (address, (address, (uint, (uint, ())))))) { +enum balances_sel { balances_sel } +impl CStructField, balances_sel>, mapping(address => uint), (word, (address, (address, (uint, (uint, ())))))> { } contract Uint { - public function mint (amount : uint) { + function mint(amount: uint) public { Assign.assign(LValueMemberAccess.memberAccess(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)))), Num.add(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)))), amount)); Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), totalSupply_sel)), Num.add(rval(MemberAccessProxy(ContractStorage(UintCxt), totalSupply_sel)), amount)); } - public function transferFrom (src : address, dst : address, amt : uint) -> Bool { + function transferFrom(src: address, dst: address, amt: uint) public returns (Bool) { require1(ge(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), src)), amt)); withdraw(src, amt); deposit(dst, amt); return Bool.True; } - public function withdraw (src : address, amt : uint) { - Assign.assign(LValueMemberAccess.memberAccess(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), src)), Num.sub(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), src)), amt) : uint); + function withdraw(src: address, amt: uint) public { + Assign.assign(LValueMemberAccess.memberAccess(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), src)), Num.sub(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), src)), amt) ); } - public function deposit (dst : address, amt : uint) { - Assign.assign(LValueMemberAccess.memberAccess(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), dst)), Num.add(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), dst)), amt) : uint); + function deposit(dst: address, amt: uint) public { + Assign.assign(LValueMemberAccess.memberAccess(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), dst)), Num.add(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), dst)), amt) ); } - public function init () { + function init() public { Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)), address(81985529216486895)); Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), msg_sender_sel)), caller()); Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), decimals_sel)), Num.fromWord(18)); } - public function main () -> uint { + function main() public returns (uint) { init(); mint(uint(1000)); mint(uint(1000)); let amt = uint(1) ; let src : address = rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)) ; transferFrom(rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), msg_sender_sel)), uint(42)); - require1(Bool.True) : (); - return rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), msg_sender_sel)))):uint; + require1(Bool.True) ; + return rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), msg_sender_sel)))); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.sol index 286d0ee6..7f2634ce 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/noconstr.sol @@ -1,17 +1,17 @@ -class a : Foo { - function foo (x : a) -> word; +trait Foo { + function foo(x: a) returns (word) ; } // here the constraint a : Foo is // defered to outer scope where the // error should be detected. -function bla (x : a) -> word { +function bla(x: a) returns (word) { return Foo.foo(x); } contract Test { - public function main() { + function main() public returns (word) { return bla(1); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.sol index fe64a653..78d4fbe0 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-detected.sol @@ -1,13 +1,13 @@ type W = word; -forall self . class self:IdTy { - function id(x:self) -> self; +trait IdTy { + function id(x: self) returns (self) ; } -instance W:IdTy { - function id(x:W) -> W { return x; } +impl IdTy { + function id(x: W) returns (W) { return x; } } -instance word:IdTy { - function id(x:word) -> word { return 0; } +impl IdTy { + function id(x: word) returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.sol index faa30e06..c47074d6 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-order.sol @@ -1,13 +1,13 @@ type W = word; -forall self . class self:IdTy { - function id(x:self) -> self; +trait IdTy { + function id(x: self) returns (self) ; } -instance word:IdTy { - function id(x:word) -> word { return 0; } +impl IdTy { + function id(x: word) returns (word) { return 0; } } -instance W:IdTy { - function id(x:W) -> W { return x; } +impl IdTy { + function id(x: W) returns (W) { return x; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.sol index 31cb10fa..023094be 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlap-synonym-missed-two-synonyms.sol @@ -1,14 +1,14 @@ type W = word; type V = word; -forall self . class self:IdTy { - function id(x:self) -> self; +trait IdTy { + function id(x: self) returns (self) ; } -instance W:IdTy { - function id(x:W) -> W { return x; } +impl IdTy { + function id(x: W) returns (W) { return x; } } -instance V:IdTy { - function id(x:V) -> V { return 0; } +impl IdTy { + function id(x: V) returns (V) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.sol index 152ad54f..38382c67 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/overlapping-heads.sol @@ -1,15 +1,15 @@ -forall a b . class a : Foo(b) { - function foo (x : a, y : word) -> b; +trait Foo { + function foo(x: a, y: word) returns (b) ; } -instance () : Foo (()) { - function foo (x : (), y : word) -> () { +impl Foo<(), ()> { + function foo(x: (), y: word) { return (); } } -forall a . instance a : Foo (()) { - function foo (x : a, y : word) -> () { +impl Foo { + function foo(x: a, y: word) { return (); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.sol index 4e636df6..d6f0eba0 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/patterson-bug.sol @@ -1,29 +1,29 @@ -data storage(a) = storage(word); -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storage { storage(word) } +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -data mapping(member, index) = mapping(word, Proxy(member), Proxy(index)); // storage by default +enum mapping { mapping(word, Proxy, Proxy) } // storage by default // data mapRef(a) = mapRef(word); //ref to a map elem -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -forall a . instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) -> () { +impl Assign, a> { + function assign(l: storageRef, y: a) { } } -forall self fieldType offsetType . class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall self memberRefType . class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } // ------------------------------------------------------------------ @@ -31,10 +31,8 @@ forall self memberRefType . class self:LValueMemberAccess(memberRefType) { // ------------------------------------------------------------------ -forall cxt fieldSelector fieldType offsetType - . StructField(cxt, fieldSelector):CStructField(fieldType, offsetType) - => instance MemberAccessProxy(cxt, fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(cxt, fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, storageRef> where StructField: CStructField { + function memberAccess(x: MemberAccessProxy) returns (storageRef) { return storageRef(0x100); } } @@ -43,20 +41,19 @@ forall cxt fieldSelector fieldType offsetType // Indexed access // ------------------------------------------------------------------ -data mapping(index, member) = mapping(word); -data IndexAccessProxy(map, index, member) = IndexAccessProxy(map, index); -data IndexAccessProxy2(map, index, member) = IndexAccessProxy2(map, index, Proxy(member)); +enum mapping { mapping(word) } +enum IndexAccessProxy { IndexAccessProxy(map, index) } +enum IndexAccessProxy2 { IndexAccessProxy2(map, index, Proxy) } -forall map index member. - instance IndexAccessProxy(storageRef(mapping(index,member)), index, member):LValueMemberAccess(storageRef(member)) { - function memberAccess(x:IndexAccessProxy(storageRef(map), index, member)) -> storageRef(member) { +impl LValueMemberAccess member)>, index, member>, storageRef> { + function memberAccess(x: IndexAccessProxy, index, member>) returns (storageRef) { return storageRef(0); } } -data MintCtx = MintCtx; -data balances_sel = balances_sel; -instance StructField(MintCtx, balances_sel):CStructField(mapping(word,word), ()) {} +enum MintCtx { MintCtx } +enum balances_sel { balances_sel } +impl CStructField, mapping(word => word), ()> {} function mint(amount:word) { let bal_prx = MemberAccessProxy(MintCtx, balances_sel); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.snap index 505c4182..cc018808 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.snap @@ -1,14 +1,14 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol --- error[SC0001]: `payable` is only allowed on a function, constructor, or fallback inside a contract - --> /payable-toplevel-function.solc:3:1 + --> /payable-toplevel-function.sol:3:20 | 2 | // never on a top-level function. This must fail to parse. -3 | payable function deposit() -> uint256 { - | ^^^^^^^ +3 | function deposit() payable returns (uint256) { + | ^^^^^^^ 4 | return 0; | = note: while parsing function signature diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol index 18f778fc..c9fbc3ef 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/payable-toplevel-function.sol @@ -1,5 +1,5 @@ // `payable` is only valid on a function/fallback inside a contract, // never on a top-level function. This must fail to parse. -payable function deposit() -> uint256 { +function deposit() payable returns (uint256) { return 0; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.sol index 2576051f..24d78ee1 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_coverage.sol @@ -1,10 +1,10 @@ // Negative test for pragma merging - should fail import pragma_merge_base; -forall a . class a:TestFailClass {} +trait TestFailClass {} -data FailType(x) = FailType; +enum FailType { FailType } // should fail because TestFailCoverage doesn't have no-coverage-condition -forall a b . class a:TestFailCoverage(b) {} -forall x y . instance FailType(x):TestFailCoverage(y) {} +trait TestFailCoverage {} +impl TestFailCoverage, y> {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.sol index 89637290..0187b84a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_fail_patterson.sol @@ -5,7 +5,7 @@ import pragma_merge_base; // --- Patterson Violation --- -forall a . class a:TestFailClass {} +trait TestFailClass {} // Should fail because TestFailClass doesn't have no-patterson-condition -forall U . U:TestClassP1, U:TestClassP2, U:TestClassP3 => instance U:TestFailClass {} +impl TestFailClass where U: TestClassP1, U: TestClassP2, U: TestClassP3 {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.sol index 418fb766..44e7f726 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_import.sol @@ -6,17 +6,17 @@ import pragma_merge_base; // Add more pragmas - these should merge with imported ones -forall a b . class a:TestClassC3(b) {} -forall a . class a:TestClassB4 {} +trait TestClassC3 {} +trait TestClassB4 {} // fails coverage & patterson (pragma set here) -forall i j . (i,j):TestClassP1 => instance i:TestClassC3(j) {} +impl TestClassC3 where (i, j): TestClassP1 {} // fails coverage & patterson (pragma set in base) -forall i j . (i,j):TestClassP1 => instance i:TestClassP3(j) {} +impl TestClassP3 where (i, j): TestClassP1 {} // fails bound var & patterson (pragma set here) -forall a c . c:TestClassB1(a) => instance TestType1(a):TestClassB4 {} +impl TestClassB4> where c: TestClassB1 {} // fails bound var & patterson (pragma set in base) -forall a c . c:TestClassB1(a) => instance TestType1(a):TestClassB3 {} +impl TestClassB3> where c: TestClassB1 {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.sol index 123f9b51..05d1787a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/pragma_merge_verify.sol @@ -4,10 +4,10 @@ import pragma_merge_base; -data VerifyType(x) = VerifyType; +enum VerifyType { VerifyType } // Would fail without imported pragma no-patterson-condition TestClassP3 -forall a . (a,word):TestClassP3(a) => instance a:TestClassP3(word) {} +impl TestClassP3 where (a, word): TestClassP3 {} // Would fail without imported pragma no-coverage-condition TestClassC1 -forall p q . instance VerifyType(p):TestClassC1(q) {} +impl TestClassC1, q> {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.sol index 34da29be..bfcce334 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/proxy1.sol @@ -1,9 +1,9 @@ -data Proxy(a) = Proxy; +enum Proxy { Proxy } -forall a. class a:C { - function fun(p:Proxy(a)) -> word; +trait C { + function fun(p: Proxy) returns (word) ; } -forall t. function morefun(p:Proxy(t)) -> word { - return C.fun(Proxy:Proxy(t)); +function morefun(p: Proxy) returns (word) { + return C.fun(@t); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.snap index 8ccc711b..9140c4d2 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.snap @@ -1,14 +1,14 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol --- error[SC0001]: constructor is implicitly public; remove the 'public' keyword - --> /public-constructor.solc:5:5 + --> /public-constructor.sol:5:19 | 4 | contract PublicConstructor { -5 | public constructor() {} - | ^^^^^^ +5 | constructor() public {} + | ^^^^^^ 6 | | = note: while parsing constructor definition diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol index 99728d16..73b60c1e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-constructor.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PublicConstructor { - public constructor() {} + constructor() public {} - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.snap index 1a08cc64..694dfc94 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.snap @@ -1,14 +1,14 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol --- error[SC0001]: fallback is implicitly public; remove the 'public' keyword - --> /public-fallback.solc:7:5 + --> /public-fallback.sol:7:16 | 6 | -7 | public fallback() -> () { - | ^^^^^^ +7 | fallback() public { + | ^^^^^^ 8 | revert("fallback-was-called"); | = note: while parsing fallback definition diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol index a4a37821..020d3fa8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-fallback.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PublicFallback { constructor() {} - public fallback() -> () { + fallback() public { revert("fallback-was-called"); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.snap index 5bf70516..3c4fd6f0 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.snap @@ -1,14 +1,14 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol --- error[SC0001]: 'public' is only allowed on functions declared inside a contract - --> /public-top-level-function.solc:6:1 + --> /public-top-level-function.sol:6:19 | 5 | // top-level function (outside any `contract { … }` body) must be rejected. -6 | public function answer() -> uint256 { - | ^^^^^^ +6 | function answer() public returns (uint256) { + | ^^^^^^ 7 | return uint256(42); | = note: while parsing function signature diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol index 4e553ad1..f65df4b9 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/public-top-level-function.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // `public` is a contract-function visibility modifier. Applying it to a // top-level function (outside any `contract { … }` body) must be rejected. -public function answer() -> uint256 { +function answer() public returns (uint256) { return uint256(42); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.sol index 93ae8736..3bafd3fc 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-encoding.sol @@ -1,128 +1,135 @@ /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { +impl MemoryType { + function load(ptr: word) returns (uint) { return Typedef.abs(MemoryType.load(ptr)); } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return MemoryType.store(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) { +impl Assign, a> where a: MemoryType { + function assign(l:memoryRef, y:a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field . -function memberAccessD1(x:MemberAccessProxy(a, field)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } // This is *a lot* of pragmas... -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector):CStructField(fieldType, offsetType), offsetType:MemorySize => instance MemberAccessProxy(memory(structType), fieldSelector):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector)) -> memoryRef(fieldType) { +impl LValueMemberAccess, fieldSelector>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -130,29 +137,29 @@ forall structType fieldSelector fieldType offsetType . StructField(structType, f } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -forall a b. a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -160,38 +167,38 @@ forall a b. a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector):CStructField(fieldType, offsetType), fieldType:MemoryType, offsetType:MemorySize => instance MemberAccessProxy(memory(structType), fieldSelector):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector)) -> fieldType { +impl RValueMemberAccess, fieldSelector>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); // BUG: Something wrong here? Complains about ptr not being word... /*assembly { ptr := add(ptr, size) }*/ - return MemoryType.load(Typedef.abs(ptr)):fieldType; + return MemoryType.load(Typedef.abs(ptr)); } } ////// Testing // struct S { x:word; y:uint; z:word; } -data S = S(word, uint, word); -data x_sel = x_sel; -data y_sel = y_sel; -data z_sel = z_sel; +enum S { S(word, uint, word) } +enum x_sel { x_sel } +enum y_sel { y_sel } +enum z_sel { z_sel } -instance StructField(S, x_sel):CStructField(word, ()) {} -instance StructField(S, y_sel):CStructField(uint, word) {} +impl CStructField, word, ()> {} +impl CStructField, uint, word> {} // BUG: This next one should really be the following, but that breaks weirdly: // (I get a patterson condition violation on an invoke instance for g) // instance StructField(S, z_sel):CStructField(word, (word,uint)) {} // So instead I use: -instance StructField(S, z_sel):CStructField(word, word) {} +impl CStructField, word, word> {} function f() { - let x:memory(word); - let y:memory(word); + let x:memory; + let y:memory; // x = y Assign.assign(ref(x), y); /* @@ -205,7 +212,7 @@ function f() { } function g() { - let s:memory(S) = Typedef.abs(0x80); + let s:memory = Typedef.abs(0x80); let y:word = 42; let z:uint = uint(42); // s.x = y @@ -220,7 +227,7 @@ function g() { Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, z_sel)), RValueMemberAccess.memberAccess(MemberAccessProxy(s, x_sel))); } contract C { - public function main() { + function main() public { f(); g(); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.sol index a7922668..9481706a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference-test.sol @@ -1,54 +1,57 @@ -data memory(a) = memory(word); +enum memory { memory(word) } -class abs:Typedef(rep) { - function abs(v:rep) -> abs; - function rep(v:abs) -> rep; +trait Typedef { + function abs(v: rep) returns (abs) ; + function rep(v: abs) returns (rep) ; } -instance memory(a):Typedef(word) { - function abs(ptr:word) -> memory(a) { +impl Typedef, word> { + function abs(ptr: word) returns (memory) { return memory(ptr); } - function rep(v:memory(a)) -> word { - match v { - | memory(ptr) => return ptr; - } + function rep(v: memory) returns (word) { + match (v) { +case memory(ptr) { +return ptr; +} +} } } -class self:Test { - function test(x:self) -> word; +trait Test { + function test(x: self) returns (word) ; } -instance word:Test { - function test(x:word) -> word { +impl Test { + function test(x: word) returns (word) { return x; } } -data test(a) = test(memory(a)); +enum test { test(memory) } -instance test(a):Typedef(memory(a)) { - function rep(x:test(a)) -> memory(a) { - match x { - | test(m) => return m; - } +impl Typedef, memory> { + function rep(x: test) returns (memory) { + match (x) { +case test(m) { +return m; +} +} } - function abs(m:memory(a)) -> test(a) { + function abs(m: memory) returns (test) { return test(m); } } -forall abs rep . test(abs):Typedef(rep), rep:Test => - instance test(abs):Test { - function test(x:test(abs)) -> word { +impl Test> where test: Typedef, rep: Test { + function test(x: test) returns (word) { return Test.test(Typedef.rep(x)); } } contract C { - public function main() { - let x:test(word) = test(memory(42)); + function main() public { + let x:test = test(memory(42)); let ptr:word = Test.test(x); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.sol index 23c8e63f..26969ba4 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/reference.sol @@ -1,26 +1,26 @@ -class ref : Ref(deref) { - function load (r:ref) -> deref; - function store(r:ref, v:deref) -> unit; +trait Ref { + function load(r: ref) returns (deref) ; + function store(r: ref, v: deref) returns (unit) ; } -data stack(a) = stack(a); +enum stack { stack(a) } -instance stack(a) : Ref(a) { +impl Ref, a> { } -data MemberAccess(ty, field) = MemberAccess(ty); +enum MemberAccess { MemberAccess(ty) } -data PairFst = PairFst; -data PairSnd = PairSnd; +enum PairFst { PairFst } +enum PairSnd { PairSnd } -data XRef(st, field, fieldType) = XRef(st, field); -forall r : Ref (a,b) . instance XRef(r, PairFst, a) : Ref(a) {} -forall r : Ref (a,b) . instance XRef(r, PairSnd, b) : Ref(b) {} +enum XRef { XRef(st, field) } +impl Ref, a> where r: Ref {} +impl Ref, b> where r: Ref {} contract AssignNested { - public function main() { - let x : stack( (word, (word, word)) ); - let z : stack( (word, (word, word)) ); + function main() public returns (word) { + let x : stack<(word, (word, word))>; + let z : stack<(word, (word, word))>; // either of the next lines is fine on their own, but not together Ref.store( XRef(z,PairFst), 21); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.sol index 4260971e..daa3d81f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/references-daniel.sol @@ -1,235 +1,243 @@ /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data xunit = xunit; +enum xunit { xunit } -data uint = uint(word); +enum uint { uint(word) } -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { +impl MemoryType { + function load(ptr: word) returns (uint) { return Typedef.abs(MemoryType.load(ptr)); } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return MemoryType.store(ptr, Typedef.rep(value)); } } -forall a . a:MemoryType => -instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) { +impl Assign, a> where a: MemoryType { + function assign(l:memoryRef, y:a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field) = MemberAccessProxy(a, Proxy(field)); +enum MemberAccessProxy { MemberAccessProxy(a, Proxy) } -forall a field . -function memberAccessPtr(x:MemberAccessProxy(memory(a), field)) -> word { - match x { - | MemberAccessProxy(y,z) => match y { - | memory(ptr) => return ptr; - } - } +function memberAccessPtr(x: MemberAccessProxy, field>) returns (word) { + match (x) { +case MemberAccessProxy(y,z) { +match (y) { +case memory(ptr) { +return ptr; +} +} +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } -instance xunit:MemorySize { - function size(x:Proxy(xunit)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -data zero = zero; -data suc(a) = suc(a); +enum zero { zero } +enum suc { suc(a) } -forall a b . instance MemberAccessProxy(memory((a, b)), zero) : Typedef (word) {} -forall a b . instance MemberAccessProxy(memory((a,b)), zero):LValueMemberAccess(memoryRef(a)) { - function memberAccess(mptr:MemberAccessProxy(memory((a,b)), zero), f:Proxy(zero)) -> memoryRef(a) { +impl Typedef, zero>, word> {} +impl LValueMemberAccess, zero>, memoryRef> { + function memberAccess(mptr: MemberAccessProxy, zero>, f: Proxy) returns (memoryRef) { let ptr:word = Typedef.rep(mptr); return memoryRef(ptr); } } -forall a b c n. MemberAccessProxy(memory(b), n):LValueMemberAccess(c), a:MemorySize => -instance MemberAccessProxy(memory((a,b)), suc(n)):LValueMemberAccess(c) { - function memberAccess(map:MemberAccessProxy(memory((a,b)), suc(n)), f:Proxy(suc(n))) -> c { +impl LValueMemberAccess, suc>, c> where MemberAccessProxy, n>: LValueMemberAccess, a: MemorySize { + function memberAccess(map: MemberAccessProxy, suc>, f: Proxy>) returns (c) { let ptr:word = memberAccessPtr(map); - let sz:word = MemorySize.size(Proxy:Proxy(a)); + let sz:word = MemorySize.size(@a); assembly { ptr := add(ptr, sz) } - let newPtr:memory(b) = memory(ptr); - return LValueMemberAccess.memberAccess(MemberAccessProxy(newPtr, Proxy:Proxy(n))); + let newPtr:memory = memory(ptr); + return LValueMemberAccess.memberAccess(MemberAccessProxy(newPtr, @n)); } } -instance MemberAccessProxy(memory(a), zero) : LValueMemberAccess (word) {} -instance MemberAccessProxy(memory(a), suc(zero)) : LValueMemberAccess (uint) {} -instance MemberAccessProxy(memory(a), suc(suc(zero))) : LValueMemberAccess (word) {} -instance word:Assign(word){} -instance uint:Assign(uint){} +impl LValueMemberAccess, zero>, word> {} +impl LValueMemberAccess, suc>, uint> {} +impl LValueMemberAccess, suc>>, word> {} +impl Assign {} +impl Assign {} ////// Testing // struct S { x:word; y:uint; z:word; } -data S = S(word, uint, word); -data x_sel = x_sel; -data y_sel = y_sel; -data z_sel = z_sel; - -instance S:Typedef((word, uint, word)) { - function abs(x:(word, uint, word)) -> S { - match x { - | (a, b, c) => return S(a, b, c); - } +enum S { S(word, uint, word) } +enum x_sel { x_sel } +enum y_sel { y_sel } +enum z_sel { z_sel } + +impl Typedef { + function abs(x: (word, uint, word)) returns (S) { + match (x) { +case (a, b, c) { +return S(a, b, c); +} +} } - function rep(x:S) -> (word, uint, word) { - match x { - | S(a, b, c) => return (a, b, c); - } + function rep(x: S) returns (word, uint, word) { + match (x) { +case S(a, b, c) { +return (a, b, c); +} +} } } // The idea here would be to generate these particularly on the definition of a struct with fields. -forall c rep . S:Typedef(rep), MemberAccessProxy(memory(rep), zero):LValueMemberAccess(word) => -instance MemberAccessProxy(memory(S), x_sel):LValueMemberAccess(word) { - function memberAccess(map:MemberAccessProxy(memory(S), x_sel), f:Proxy(x_sel)) -> word { - return (LValueMemberAccess.memberAccess(MemberAccessProxy(memory(memberAccessPtr(map)):memory(rep), Proxy:Proxy(zero))) : word); +impl LValueMemberAccess, x_sel>, word> where S: Typedef, MemberAccessProxy, zero>: LValueMemberAccess { + function memberAccess(map: MemberAccessProxy, x_sel>, f: Proxy) returns (word) { + return (LValueMemberAccess.memberAccess(MemberAccessProxy(memory(memberAccessPtr(map)), @zero)) ); } } -forall c rep . S:Typedef(rep), MemberAccessProxy(memory(rep), suc(zero)):LValueMemberAccess(uint) => -instance MemberAccessProxy(memory(S), y_sel):LValueMemberAccess(uint) { - function memberAccess(map:MemberAccessProxy(memory(S), y_sel), f:Proxy(y_sel)) -> uint { - return LValueMemberAccess.memberAccess(MemberAccessProxy(memory(memberAccessPtr(map)):memory(rep), Proxy:Proxy(suc(zero)))); +impl LValueMemberAccess, y_sel>, uint> where S: Typedef, MemberAccessProxy, suc>: LValueMemberAccess { + function memberAccess(map: MemberAccessProxy, y_sel>, f: Proxy) returns (uint) { + return LValueMemberAccess.memberAccess(MemberAccessProxy(memory(memberAccessPtr(map)), @suc)); } } -forall c rep . S:Typedef(rep), MemberAccessProxy(memory(rep), suc(suc(zero))):LValueMemberAccess(word) => -instance MemberAccessProxy(memory(S), z_sel):LValueMemberAccess(word) { - function memberAccess(map:MemberAccessProxy(memory(S), z_sel), f:Proxy(z_sel)) -> word { - return LValueMemberAccess.memberAccess(MemberAccessProxy(memory(memberAccessPtr(map)):memory(rep), Proxy:Proxy(suc(suc(zero))))); +impl LValueMemberAccess, z_sel>, word> where S: Typedef, MemberAccessProxy, suc>>: LValueMemberAccess { + function memberAccess(map: MemberAccessProxy, z_sel>, f: Proxy) returns (word) { + return LValueMemberAccess.memberAccess(MemberAccessProxy(memory(memberAccessPtr(map)), @suc>)); } } function f() { - let x:memory(word); - let y:memory(word); + let x:memory; + let y:memory; x = y; } function g() { - let s:memory(S) = Typedef.abs(0x80); + let s:memory = Typedef.abs(0x80); let x:word = 42; let y:uint = Typedef.abs(21); let z:word = 7; // s.x = x; - Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, Proxy:Proxy(x_sel))), x); + Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, @x_sel)), x); // s.y = y; - Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, Proxy:Proxy(y_sel))), y); + Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, @y_sel)), y); // s.z = z; - Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, Proxy:Proxy(z_sel))), z); + Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, @z_sel)), z); } contract C { - public function main() { + function main() public { f(); g(); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.sol index 55bd2005..fe6e0760 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-contract-method.sol @@ -1,10 +1,10 @@ // Error: contract method missing return type annotation contract Doubler { - public function double(x : word) { + function double(x: word) public { return x; } - public function main() -> word { + function main() public returns (word) { return double(21); } } From ae1de6ef608f5aed28255fe1b69a078f289fce09 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 052/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples Co-authored-by: Codex --- .../require-annotation-missing-both.snap | 14 +++ .../require-annotation-missing-param.snap | 14 +++ .../require-annotation-missing-param.sol | 2 +- .../cases/require-annotation-mutual.sol | 2 +- .../examples/cases/return-fun-bad-arity.sol | 2 +- .../examples/cases/return-fun-bad-param.sol | 2 +- .../examples/cases/return-fun-bad-return.sol | 2 +- .../examples/cases/return-fun-bad-sig.sol | 2 +- .../examples/cases/return-fun-not-fun.sol | 2 +- .../fail/test/examples/cases/signature.sol | 6 +- .../fail/test/examples/cases/simpleIfExpr.sol | 2 +- .../fail/test/examples/cases/simpleIfStmt.sol | 2 +- .../fail/test/examples/cases/skolem-let.sol | 6 +- .../cases/storage-adt-mapping-field-fail.sol | 10 +- .../fail/test/examples/cases/string-const.sol | 2 +- .../test/examples/cases/subject-index.sol | 49 ++++---- .../test/examples/cases/subject-reduction.sol | 47 ++++--- .../examples/cases/subsumption-constraint.sol | 12 +- .../test/examples/cases/subsumption-test.sol | 4 +- .../examples/cases/super-class-cycle-fail.sol | 12 +- .../cases/super-class-recursive-arg.sol | 10 +- .../examples/cases/synonym-arity-mismatch.sol | 4 +- .../examples/cases/synonym-long-cycle.sol | 2 +- .../test/examples/cases/synonym-recursive.sol | 2 +- .../examples/cases/synonym-self-recursive.sol | 2 +- .../examples/cases/tabled-answer-reuse.sol | 12 +- .../test/examples/cases/tabled-cycle-fail.sol | 12 +- .../cases/tabled-left-recursive-fail.sol | 8 +- .../examples/cases/tabled-mutual-chain.sol | 18 +-- .../examples/cases/toplevel-constructor.snap | 6 +- .../examples/cases/toplevel-fallback.snap | 10 +- .../test/examples/cases/toplevel-fallback.sol | 2 +- .../examples/cases/unbound-instance-var.sol | 13 +- .../examples/cases/unconstrained-instance.sol | 26 ++-- .../test/examples/cases/user-op-lambda.snap | 14 +-- .../test/examples/cases/user-op-lambda.sol | 6 +- .../fail/test/examples/cases/vartyped.sol | 2 +- .../fail/test/examples/cases/weirdfoo.sol | 6 +- .../corpus/fail/test/examples/cases/xref.sol | 116 ++++++++++-------- .../cases/yul-multi-return-arity-fail.sol | 2 +- .../fail/test/examples/comptime/OneOne.sol | 10 +- .../comptime/ct_param_poly_runtime.sol | 12 +- .../examples/comptime/ct_param_runtime.sol | 6 +- .../fail/test/examples/comptime/fromInt.sol | 55 ++++----- .../fail/test/examples/comptime/fromInt2.sol | 34 +++-- .../fail/test/examples/comptime/fromInt3.sol | 30 +++-- .../fail/test/examples/comptime/fromLit.sol | 25 ++-- .../comptime/string-mem-runtime-fail.sol | 4 +- .../fail/test/examples/dispatch/fib.sol | 6 +- .../fail/test/examples/invokable/021nid.sol | 8 +- .../examples/invokable/022nid-invoke.snap | 15 --- .../test/examples/invokable/022nid-invoke.sol | 18 +-- .../fail/test/examples/invokable/024lamid.sol | 6 +- .../examples/invokable/025lamid-invoke.snap | 15 --- .../examples/invokable/025lamid-invoke.sol | 14 +-- .../test/examples/invokable/026capture.snap | 15 --- .../test/examples/invokable/026capture.sol | 24 ++-- .../test/examples/invokable/027retfun.snap | 15 --- .../test/examples/invokable/027retfun.sol | 24 ++-- .../test/examples/invokable/028modifier.snap | 15 --- .../test/examples/invokable/028modifier.sol | 36 +++--- .../fail/test/examples/invokable/031enum.snap | 15 --- .../fail/test/examples/invokable/031enum.sol | 30 +++-- 63 files changed, 425 insertions(+), 474 deletions(-) create mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.snap create mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.snap delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.snap delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.snap delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.snap delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.snap delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.snap delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.snap diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.snap new file mode 100644 index 00000000..e6f79c4d --- /dev/null +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.snap @@ -0,0 +1,14 @@ +--- +source: crates/parser/tests/diagnostics.rs +expression: value +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-both.sol +--- +error[SC0001]: named function parameter requires an explicit type + --> /require-annotation-missing-both.sol:2:13 + | +1 | // Error: top-level free function with no annotations at all +2 | function id(x) { + | ^ +3 | return x; + | + = note: while parsing function signature diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.snap new file mode 100644 index 00000000..cde6c2bc --- /dev/null +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.snap @@ -0,0 +1,14 @@ +--- +source: crates/parser/tests/diagnostics.rs +expression: value +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol +--- +error[SC0001]: named function parameter requires an explicit type + --> /require-annotation-missing-param.sol:2:14 + | +1 | // Error: top-level free function with an unannotated parameter +2 | function add(x, y: word) returns (word) { + | ^ +3 | let res : word; + | + = note: while parsing function signature diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol index 5d498984..c410bf70 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-missing-param.sol @@ -1,5 +1,5 @@ // Error: top-level free function with an unannotated parameter -function add(x, y : word) -> word { +function add(x, y: word) returns (word) { let res : word; assembly { res := add(x, y) } return res; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.sol index dc7fd31e..f8e5afe1 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/require-annotation-mutual.sol @@ -3,6 +3,6 @@ function foo(x : word) { return bar(x); } -function bar(x : word) -> word { +function bar(x: word) returns (word) { return foo(x); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.sol index 4eaf6ae1..fe0be4df 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-arity.sol @@ -1,6 +1,6 @@ // INCORRECT: the signature promises a one-argument function (word) -> word, // but the returned lambda takes two arguments. -function makeF(x : word) -> ((word) -> word) { +function makeF(x: word) returns (function(word) returns (word)) { return lam (y : word, z : word) -> word { let res : word; assembly { diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.sol index b93c35b0..7113ddf6 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-param.sol @@ -1,7 +1,7 @@ // INCORRECT: the returned lambda's parameter is `bool`, but the signature // promises (word) -> word. Closure conversion would erase the arrow type; // the single-pass checker must still reject this. -function makeAdder(x : word) -> ((word) -> word) { +function makeAdder(x: word) returns (function(word) returns (word)) { return lam (y : bool) -> word { return x; }; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.sol index a6cb6efa..f80ad2b5 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-return.sol @@ -1,6 +1,6 @@ // INCORRECT: the returned lambda's body has type bool, but the signature // promises the result is word. -function makeConst(x : word) -> ((word) -> word) { +function makeConst(x: word) returns (function(word) returns (word)) { return lam (y : word) -> bool { return true; }; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.sol index 21021b25..413edc24 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-bad-sig.sol @@ -1,6 +1,6 @@ // INCORRECT: signature says the result consumes a bool ((bool) -> word), // but the returned lambda consumes a word. -function makeF(x : word) -> ((bool) -> word) { +function makeF(x: word) returns (function(bool) returns (word)) { return lam (y : word) -> word { return x; }; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.sol index 686b2236..8f407cbb 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/return-fun-not-fun.sol @@ -1,5 +1,5 @@ // INCORRECT: the signature promises a function (word) -> word, but the body // returns a plain word instead of a function. -function makeF(x : word) -> ((word) -> word) { +function makeF(x: word) returns (function(word) returns (word)) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.sol index 1be7243b..baf36972 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/signature.sol @@ -1,8 +1,8 @@ -class self:Typedef(underlyingType) { - function rep(x:self) -> underlyingType; +trait Typedef { + function rep(x: self) returns (underlyingType) ; } -forall t:Typedef(word) . function tripleFun(x:t) { +function tripleFun(x: t) returns (word) where t: Typedef { return Typedef.rep(x); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.sol index a6c812a8..65d96131 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfExpr.sol @@ -1,3 +1,3 @@ contract SimpleIfStmt { - public function main() { return (if (true) then 1 else 0); } + function main() public { return ( (true) ? 1 : 0); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.sol index 80e672f2..c81311f0 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/simpleIfStmt.sol @@ -1,3 +1,3 @@ contract SimpleIfStmt { - public function main() { if (true) {return 1;} else {return 0;} } + function main() public { if (true) {return 1;} else {return 0;} } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.sol index 2f8ea1c6..975ef8fd 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/skolem-let.sol @@ -1,13 +1,13 @@ -forall a. function fromWord(x: word) -> a { +function fromWord(x: word) returns (a) { let result : a; assembly { result := x } return result; } contract Unsafe { - public function main() { - fromWord(7):(); + function main() public returns (word) { + fromWord(7); return 42; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.sol index 15f842a6..15856de8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/storage-adt-mapping-field-fail.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // A mapping cannot be a field of a data type. std only provides // `storage(mapping(k,v)) : CanStore(storage(mapping(k,v)))` — the slot handle @@ -12,7 +12,7 @@ import std.StorageGeneric.{*}; // (Even if it did, that instance's store/load are `unimplemented()`: copying a // mapping is not a meaningful storage operation.) -data Wrapper = Wrapper(mapping(uint256, uint256)); +enum Wrapper { Wrapper(mapping(uint256 => uint256)) } contract C { w : Wrapper; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.sol index 735a6d6f..58e78346 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/string-const.sol @@ -1,5 +1,5 @@ contract Answer { - public function main() { + function main() public { return "42"; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.sol index 667f65e5..70b4f2d8 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-index.sol @@ -1,37 +1,35 @@ -data storage(a) = storage(word); -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storage { storage(word) } +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -data mapping(member, index) = mapping(word, Proxy(member), Proxy(index)); +enum mapping { mapping(word, Proxy, Proxy) } -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -forall a . instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) { +impl Assign, a> { + function assign(l:storageRef, y:a) { } } -forall self fieldType offsetType . class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall self memberRefType . class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } // ------------------------------------------------------------------ // Contract field access // ------------------------------------------------------------------ -forall cxt fieldSelector fieldType offsetType - . StructField(cxt, fieldSelector):CStructField(fieldType, offsetType) - => instance MemberAccessProxy(cxt, fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(cxt, fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, storageRef> where StructField: CStructField { + function memberAccess(x: MemberAccessProxy) returns (storageRef) { return storageRef(0x100); } } @@ -40,19 +38,18 @@ forall cxt fieldSelector fieldType offsetType // Indexed access // ------------------------------------------------------------------ -data mapping(index, member) = mapping(word); -data IndexAccessProxy(map, index, member) = IndexAccessProxy(map, index); +enum mapping { mapping(word) } +enum IndexAccessProxy { IndexAccessProxy(map, index) } -forall map index member. - instance IndexAccessProxy(storageRef(map), index, member):LValueMemberAccess(storageRef(member)) { - function memberAccess(x:IndexAccessProxy(storageRef(map), index, member)) -> storageRef(member) { +impl LValueMemberAccess, index, member>, storageRef> { + function memberAccess(x: IndexAccessProxy, index, member>) returns (storageRef) { return storageRef(0); } } -data MintCtx = MintCtx; -data balances_sel = balances_sel; -instance StructField(MintCtx, balances_sel):CStructField(mapping(word,word), ()) {} +enum MintCtx { MintCtx } +enum balances_sel { balances_sel } +impl CStructField, mapping(word => word), ()> {} function mint(amount:word) { let bal_prx = MemberAccessProxy(MintCtx, balances_sel); @@ -71,7 +68,7 @@ instance StructField(MintCtx, balances_sel):CStructField(mapping(word,word), ()) } contract Map { - public function main () { + function main() public { mint(1000); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.sol index f1d32e96..4ef1c00b 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subject-reduction.sol @@ -1,37 +1,35 @@ -data storage(a) = storage(word); -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storage { storage(word) } +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -data mapping(member, index) = mapping(word, Proxy(member), Proxy(index)); +enum mapping { mapping(word, Proxy, Proxy) } -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -forall a . instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) { +impl Assign, a> { + function assign(l:storageRef, y:a) { } } -forall self fieldType offsetType . class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall self memberRefType . class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } // ------------------------------------------------------------------ // Contract field access // ------------------------------------------------------------------ -forall cxt fieldSelector fieldType offsetType - . StructField(cxt, fieldSelector):CStructField(fieldType, offsetType) - => instance MemberAccessProxy(cxt, fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(cxt, fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, storageRef> where StructField: CStructField { + function memberAccess(x: MemberAccessProxy) returns (storageRef) { return storageRef(0x100); } } @@ -40,20 +38,19 @@ forall cxt fieldSelector fieldType offsetType // Indexed access // ------------------------------------------------------------------ -data mapping(index, member) = mapping(word); -data IndexAccessProxy(map, index, member) = IndexAccessProxy(map, index); +enum mapping { mapping(word) } +enum IndexAccessProxy { IndexAccessProxy(map, index) } -forall map index member. - instance IndexAccessProxy(storageRef(map), index, member):LValueMemberAccess(storageRef(member)) { - function memberAccess(x:IndexAccessProxy(storageRef(map), index, member)) -> storageRef(member) { +impl LValueMemberAccess, index, member>, storageRef> { + function memberAccess(x: IndexAccessProxy, index, member>) returns (storageRef) { return storageRef(0); } } -data MintCtx = MintCtx; -data balances_sel = balances_sel; -instance StructField(MintCtx, balances_sel):CStructField(mapping(word,word), ()) {} +enum MintCtx { MintCtx } +enum balances_sel { balances_sel } +impl CStructField, mapping(word => word), ()> {} function mint(amount:word) { let bal_prx = MemberAccessProxy(MintCtx, balances_sel); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.sol index bf0cd6b5..42135de5 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-constraint.sol @@ -1,22 +1,22 @@ // This code should FAIL, but PASSES! -data Bool = True | False; +enum Bool { True, False } -forall a . class a : MyCls { - function f(x : a, y : a) -> Bool; +trait MyCls { + function f(x: a, y: a) returns (Bool) ; } -forall a . function the_bug(x : a, y : a) -> Bool { +function the_bug(x: a, y: a) returns (Bool) { return MyCls.f(x, y); } contract Foo { - public function x() { + function x() public { let b1 = Bool.True; let b2 = Bool.False; the_bug(b1, b2); } - public function main() { + function main() public { x(); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.sol index 014b0a36..cb1057f7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/subsumption-test.sol @@ -1,7 +1,7 @@ -function id (x) -> word { +function id(x: word) returns (word) { return x; } -forall a . function fakeid(x : word) -> a { +function fakeid(x: word) returns (a) { return x ; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.sol index c6567a6b..cde3b317 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-cycle-fail.sol @@ -1,15 +1,15 @@ -forall a . a:B => class a:A {} -forall a . a:A => class a:B {} -forall a . class a:C {} +trait A where a: B {} +trait B where a: A {} +trait C {} -forall a . a:C => function needsC(x:a) -> () { +function needsC(x: a) where a: C { return (); } -forall a . a:A => function cannotGetC(x:a) -> () { +function cannotGetC(x: a) where a: A { return needsC(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.sol index c6b0c2d9..ef3d82cf 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/super-class-recursive-arg.sol @@ -1,17 +1,17 @@ pragma no-patterson-condition A; -data Wrap(a) = Wrap(a); +enum Wrap { Wrap(a) } -forall a . Wrap(a):A => class a:A {} +trait A where Wrap: A {} -forall a . Wrap(a):A => function needsWrappedA(x:a) -> () { +function needsWrappedA(x: a) where Wrap: A { return (); } -forall a . a:A => function shouldUseSuperclass(x:a) -> () { +function shouldUseSuperclass(x: a) where a: A { return needsWrappedA(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.sol index 0486adc2..93780c46 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-arity-mismatch.sol @@ -1,5 +1,5 @@ -type F(a) = pair(a, word); +type F(a) = pair; -function main() -> F(word, word) { +function main() returns (F) { return pair(42, 0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.sol index d06783dc..46d626c6 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-long-cycle.sol @@ -3,6 +3,6 @@ type A = B; type B = C; type C = A; -function main() -> word { +function main() returns (word) { return 0; } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.sol index 3e34ef4c..3fcc1e8b 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-recursive.sol @@ -2,7 +2,7 @@ type A = B; type B = A; contract RecursiveTest { - public function main() -> word { + function main() public returns (word) { return 0; } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.sol index 9ecb567d..d79ec946 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/synonym-self-recursive.sol @@ -1,6 +1,6 @@ // Self-recursive synonym should be rejected type A = A; -function main() -> word { +function main() returns (word) { return 0; } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.sol index d815c67e..13f3124a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-answer-reuse.sol @@ -1,16 +1,16 @@ pragma no-patterson-condition Derived; -forall a . class a:Seed {} -forall a . class a:Derived {} +trait Seed {} +trait Derived {} -instance word:Seed {} +impl Seed {} -forall a . a:Seed => instance a:Derived {} +impl Derived where a: Seed {} -forall a . a:Derived, a:Derived => function needsDerivedTwice(x:a) -> () { +function needsDerivedTwice(x: a) where a: Derived, a: Derived { return (); } -function main() -> () { +function main() { return needsDerivedTwice(0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.sol index 3402f733..a0813eb7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-cycle-fail.sol @@ -1,16 +1,16 @@ pragma no-patterson-condition A; pragma no-patterson-condition B; -forall a . class a:A {} -forall a . class a:B {} +trait A {} +trait B {} -forall a . a:B => instance a:A {} -forall a . a:A => instance a:B {} +impl A where a: B {} +impl B where a: A {} -forall a . a:A => function needsA(x:a) -> () { +function needsA(x: a) where a: A { return (); } -function main() -> () { +function main() { return needsA(0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.sol index 1784286e..ae8b3736 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-left-recursive-fail.sol @@ -1,13 +1,13 @@ pragma no-patterson-condition Loop; -forall a . class a:Loop {} +trait Loop {} -forall a . a:Loop => instance a:Loop {} +impl Loop where a: Loop {} -forall a . a:Loop => function needsLoop(x:a) -> () { +function needsLoop(x: a) where a: Loop { return (); } -function main() -> () { +function main() { return needsLoop(0); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.sol index d195a58a..709fd904 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/tabled-mutual-chain.sol @@ -1,18 +1,18 @@ -data WrapA(a) = WrapA(a); -data WrapB(a) = WrapB(a); +enum WrapA { WrapA(a) } +enum WrapB { WrapB(a) } -forall a . class a:A {} -forall a . class a:B {} +trait A {} +trait B {} -instance word:A {} +impl A {} -forall a . a:A => instance WrapB(a):B {} -forall a . a:B => instance WrapA(a):A {} +impl B> where a: A {} +impl A> where a: B {} -forall a . a:A => function needsA(x:a) -> () { +function needsA(x: a) where a: A { return (); } -function main() -> () { +function main() { return needsA(WrapA(WrapB(0))); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.snap index facde07c..5589e99c 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.snap @@ -1,10 +1,10 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-constructor.sol --- -error[SC0001]: could not parse top-level item near `constructor() {}`; expected a declaration starting with `import`, `pragma`, `type`, `data`, `class`, `instance`, `contract`, or `function` - --> /toplevel-constructor.solc:3:1 +error[SC0001]: could not parse top-level item near `constructor() {}`; expected a declaration starting with `import`, `pragma`, `type`, `enum`, `trait`, `impl`, `contract`, or `function` + --> /toplevel-constructor.sol:3:1 | 1 | // A `constructor` may only be declared inside a contract. 2 | // At the top level this must fail to parse. diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.snap index 08088eb0..cdfeed62 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.snap @@ -1,12 +1,12 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol --- -error[SC0001]: could not parse top-level item near `fallback() -> () {}`; expected a declaration starting with `import`, `pragma`, `type`, `data`, `class`, `instance`, `contract`, or `function` - --> /toplevel-fallback.solc:3:1 +error[SC0001]: could not parse top-level item near `fallback() {}`; expected a declaration starting with `import`, `pragma`, `type`, `enum`, `trait`, `impl`, `contract`, or `function` + --> /toplevel-fallback.sol:3:1 | 1 | // A `fallback` may only be declared inside a contract. 2 | // At the top level this must fail to parse. -3 | fallback() -> () {} - | ^^^^^^^^^^^^^^^^^^^ +3 | fallback() {} + | ^^^^^^^^^^^^^ diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol index 850ecf86..f5bc0367 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/toplevel-fallback.sol @@ -1,3 +1,3 @@ // A `fallback` may only be declared inside a contract. // At the top level this must fail to parse. -fallback() -> () {} +fallback() {} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.sol index 7b2e1a8b..86a8b1bc 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unbound-instance-var.sol @@ -1,16 +1,15 @@ -forall self. -class self:C { - function size(x:self) -> word; +trait C { + function size(x: self) returns (word) ; } -instance ():C { - function size(x:()) -> word { +impl C<()> { + function size(x: ()) returns (word) { return 0; } } -instance uint:C { - function size(x:uint) -> word { +impl C { + function size(x: uint) returns (word) { return 1; } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.sol index 6e838cc5..9a6955b0 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/unconstrained-instance.sol @@ -1,23 +1,25 @@ -data memory(t) = memory(word); +enum memory { memory(word) } -class t:ValueTy { - function rep(x:t) -> word; +trait ValueTy { + function rep(x: t) returns (word) ; } -instance memory(t) : ValueTy { - function rep(x: memory(t)) -> word { - match x { - | memory(w) => return w; - }; +impl ValueTy> { + function rep(x: memory) returns (word) { + match (x) { +case memory(w) { +return w; +} +} } } -class ref:Ref(deref) { - function store(loc: ref, value: deref) -> (); +trait Ref { + function store(loc: ref, value: deref) ; } -instance memory(t) : Ref(t) { - function store(loc: memory(t), value: t) -> () { +impl Ref, t> { + function store(loc: memory, value: t) { // We don't have a `ValueTy` bound on `t` anywhere, so this should raise a type error... let vw = ValueTy.rep(value); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.snap index 08755e85..a4826c37 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.snap +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.snap @@ -1,10 +1,10 @@ --- source: crates/parser/tests/diagnostics.rs expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.solc +input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol --- -error[SC0001]: could not parse top-level item near `infixl 70 (^^) => pow;`; expected a declaration starting with `import`, `pragma`, `type`, `data`, `class`, `instance`, `contract`, or `function` - --> /user-op-lambda.solc:6:1 +error[SC0001]: could not parse top-level item near `infixl 70 (^^) => pow;`; expected a declaration starting with `import`, `pragma`, `type`, `enum`, `trait`, `impl`, `contract`, or `function` + --> /user-op-lambda.sol:6:1 | 5 | 6 | infixl 70 (^^) => pow; @@ -13,12 +13,12 @@ error[SC0001]: could not parse top-level item near `infixl 70 (^^) => pow;`; exp | --- -error[SC0001]: parse error: unexpected `^` - --> /user-op-lambda.solc:17:47 +error[SC0001]: parse error: unexpected `;` + --> /user-op-lambda.sol:17:50 | 16 | // operator (^^) used inside a lambda body 17 | let f = lam(x : word) -> word { return x ^^ 3; }; - | ^ unexpected token + | ^ unexpected token 18 | return f(2); | - = note: expecting `!`, `(`, `.`, `@`, `[`, `if`, `lam`, or `~` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol index ec2d8cd5..02b88be6 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/user-op-lambda.sol @@ -1,18 +1,18 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; infixl 70 (^^) => pow; -function pow(b : word, e : word) -> word { +function pow(b: word, e: word) returns (word) { let r : word; assembly { r := exp(b, e) } return r; } contract UserOpLambda { - function main() -> word { + function main() returns (word) { // operator (^^) used inside a lambda body let f = lam(x : word) -> word { return x ^^ 3; }; return f(2); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.sol index 3b89a402..68249b3e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/vartyped.sol @@ -1,4 +1,4 @@ function foo () { - let f : (word) -> word = lam (x) { return x ; } ; + let f : function(word) returns (word) = lam (x) { return x ; } ; return f(1); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.sol index a94677e9..c077a262 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/weirdfoo.sol @@ -1,5 +1,5 @@ -data W(a) = W(a); -class a: Foo {function foo(); } -instance ((word, a) : Foo) => (word, W(a)) : Foo { +enum W { W(a) } +trait Foo {function foo(); } +impl Foo<(word, W)> { function foo() {} } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.sol index d3cc27d2..0cc13002 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/xref.sol @@ -6,7 +6,7 @@ function add_(x:word, y:word) { // _add is not a legal identifier :( return res; } -function mload_(x:word) -> word { +function mload_(x: word) returns (word) { let res: word; assembly { res := mload(x) @@ -18,102 +18,116 @@ function mstore_(a:word, v:word) { assembly { mstore(a,v) } } -forall r d . class r:Ref(d) { function load(x:r) -> d; function store(x:r, v:d) -> ();} +trait Ref { function load(x: r) returns (d) ; function store(x: r, v: d) ;} -forall self underlyingType . class self:Typedef(underlyingType) { - function rep(x:self) -> underlyingType; // abbr: x.rep = Typedef.rep(x) - function abs(x:underlyingType) -> self; // abbr: x.abs +trait Typedef { + function rep(x: self) returns (underlyingType) ; // abbr: x.rep = Typedef.rep(x) + function abs(x: underlyingType) returns (self) ; // abbr: x.abs } -data Proxy(a) = Proxy; +enum Proxy { Proxy } -data M(a) = M(word); +enum M { M(word) } -forall a . instance M(a) : Typedef(word) { - function rep(m : M(a)) -> word { match m { | M(w) => return w; }} - function abs(w : word) -> M(a) { return M(w); } +impl Typedef, word> { + function rep(m: M) returns (word) { match (m) { +case M(w) { +return w; +} +}} + function abs(w: word) returns (M) { return M(w); } } -forall Self . class Self:MemoryType { - function memorySize(p:Proxy(Self)) -> word; +trait MemoryType { + function memorySize(p: Proxy) returns (word) ; /* inline function sizeof(Self) -> word { // an abbreviation to avoid writing Proxy; wasteful unless inlined return memorySize(Proxy:Proxy(self)); } */ - function memoryStep(word, self:Self) -> word; - function mload(r:word) -> Self; - function mstore(r:word, v:Self) -> (); + function memoryStep(offset: word, self: Self) returns (word) ; + function mload(r: word) returns (Self) ; + function mstore(r: word, v: Self) ; } -forall Self . Self:MemoryType => function sizeof(self:Self) -> word { - return MemoryType.memorySize(Proxy:Proxy(Self)); +function sizeof(self: Self) returns (word) where Self: MemoryType { + return MemoryType.memorySize(@Self); } -forall a d . class a:MemoryRef(d) { function addr(r:a) -> word; } -forall a . instance M(a):MemoryRef(a) { function addr(r:M(a)) -> word {return Typedef.rep(r);} } +trait MemoryRef { function addr(r: a) returns (word) ; } +impl MemoryRef, a> { function addr(r: M) returns (word) {return Typedef.rep(r);} } -forall a . function xaddr(r:M(a)) -> word { return MemoryRef.addr(r); } -forall a b . function asMemRefTo(r:M(a), p:Proxy(b)) -> M(b) { return Typedef.abs(xaddr(r)); } +function xaddr(r: M) returns (word) { return MemoryRef.addr(r); } +function asMemRefTo(r: M, p: Proxy) returns (M) { return Typedef.abs(xaddr(r)); } -forall a . a:MemoryType => function stepStore(aa: word, va: a) -> word { +function stepStore(aa: word, va: a) returns (word) where a: MemoryType { MemoryType.mstore(aa, va); - return add_(aa, MemoryType.memorySize(Proxy:Proxy(a))); + return add_(aa, MemoryType.memorySize(@a)); } -forall Self r . Self:MemoryType, r:MemoryRef(Self) => instance r : Ref(Self) { - function load(r:M(Self)) -> Self { return MemoryType.mload(xaddr(r)); } - function store(r:M(Self), v:Self) -> () { MemoryType.mstore(xaddr(r), v); } +impl Ref where Self: MemoryType, r: MemoryRef { + function load(r: M) returns (Self) { return MemoryType.mload(xaddr(r)); } + function store(r: M, v: Self) { MemoryType.mstore(xaddr(r), v); } } -instance word:MemoryType { - function memorySize(p:Proxy(word)) -> word { return 32; } - function memoryStep(a:word, self:word) -> word { return add_(a,32); } - function mload(a: word) -> word { return mload_(a); } - function mstore(a: word, v:word) -> () { mstore_(a, v); } +impl MemoryType { + function memorySize(p: Proxy) returns (word) { return 32; } + function memoryStep(a: word, self: word) returns (word) { return add_(a,32); } + function mload(a: word) returns (word) { return mload_(a); } + function mstore(a: word, v: word) { mstore_(a, v); } } -forall a b . a:MemoryType, b:MemoryType => instance (a,b) : MemoryType { - function memorySize(p:Proxy((a,b))) -> word { - return add_(MemoryType.memorySize(Proxy:Proxy(a)), MemoryType.memorySize(Proxy:Proxy(a)) ); +impl MemoryType<(a, b)> where a: MemoryType, b: MemoryType { + function memorySize(p: Proxy<(a, b)>) returns (word) { + return add_(MemoryType.memorySize(@a), MemoryType.memorySize(@a) ); } - function mload(aa:word) -> (a,b) { + function mload(aa: word) returns (a, b) { let va = MemoryType.mload(aa); let ab = add_(aa, sizeof(va)); let vb = MemoryType.mload(ab); return (va,vb); } - function mstore(aa:word, v: (a,b)) -> () { - match v { | pair(va, vb) => mstore2(aa, va, vb); } // match-compiler cannot compile mopre than 1 stmt in a branch :( + function mstore(aa: word, v: (a, b)) { + match (v) { +case pair(va, vb) { +mstore2(aa, va, vb); +} +} // match-compiler cannot compile mopre than 1 stmt in a branch :( } } -forall a b . a: MemoryType, b: MemoryType => function mstore2(aa:word, va:a, vb: b) { //needed because of bug in match-compiler +function mstore2(aa: word, va: a, vb: b) where a: MemoryType, b: MemoryType { //needed because of bug in match-compiler let ab = stepStore(aa, va); MemoryType.mstore(ab, vb); } -data XRef(st, field, fieldType) = XRef(st, field); -data PairFst = PairFst; -data PairSnd = PairSnd; +enum XRef { XRef(st, field) } +enum PairFst { PairFst } +enum PairSnd { PairSnd } -forall a b r . r:MemoryRef ( (a,b)), a:MemoryType, b:MemoryType => instance XRef(r, PairFst, a) : MemoryRef(a) { - function addr(xr : XRef(r, PairFst, a)) -> word { - match xr { | XRef(r, _) => return MemoryRef.addr(r); } +impl MemoryRef, a> where r: MemoryRef<(a, b)>, a: MemoryType, b: MemoryType { + function addr(xr: XRef) returns (word) { + match (xr) { +case XRef(r, _) { +return MemoryRef.addr(r); +} +} } } -forall a b r . r:MemoryRef ((a,b)), a:MemoryType, b:MemoryType => instance XRef(r, PairSnd, b) : MemoryRef(b) { - function addr(xr : XRef (r, PairSnd, b)) -> word { - match xr { - | XRef(r, _) => return add_(MemoryRef.addr(r), MemoryType.memorySize(Proxy : Proxy(b))); - } +impl MemoryRef, b> where r: MemoryRef<(a, b)>, a: MemoryType, b: MemoryType { + function addr(xr: XRef) returns (word) { + match (xr) { +case XRef(r, _) { +return add_(MemoryRef.addr(r), MemoryType.memorySize(@b)); +} +} } } contract Ref219 { - public function main() { - let mp:M((word, word, word)) = M(96); // no alloc yet + function main() public { + let mp:M<(word, word, word)> = M(96); // no alloc yet let p = (1,16,25); Ref.store(mp, p); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.sol index de58b945..1d6a5f43 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/cases/yul-multi-return-arity-fail.sol @@ -2,7 +2,7 @@ // values but 3 names are being assigned, so this Yul is invalid and the type // checker must report the arity error. contract YulMultiRetBad { - public function main() -> word { + function main() public returns (word) { let x : word; let y : word; let z : word; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.sol index 0c74f7ba..5ba804da 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/OneOne.sol @@ -1,4 +1,4 @@ -function addWord(l: word, r: word) -> word { +function addWord(l: word, r: word) returns (word) { let rw : word; assembly { rw := add(l,r); @@ -6,9 +6,9 @@ function addWord(l: word, r: word) -> word { return rw; } -function zero () { 0 } -function one() { addWord(1, zero()) } +function zero () returns (word) { 0 } +function one() returns (word) { addWord(1, zero()) } contract OneOne { - function main() -> word { addWord(one(), one()) } -} \ No newline at end of file + function main() returns (word) { addWord(one(), one()) } +} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.sol index e67a24c1..66341e77 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_poly_runtime.sol @@ -6,22 +6,22 @@ */ import std; -forall t. class t : Wrap { - function unwrap(comptime x : t) -> comptime word; +trait Wrap { + function unwrap(comptime x: t) returns (comptime) ; } -instance word : Wrap { - function unwrap(comptime x : word) -> comptime word { +impl Wrap { + function unwrap(comptime x: word) returns (comptime) { return x; } } -forall t. t:Wrap => function process(z : t) -> word { +function process(z: t) returns (word) where t: Wrap { return Wrap.unwrap(z); } contract ComptimeParamPolyRuntime { - function main() -> word { + function main() returns (word) { return process(42); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.sol index 496cb2a7..d9dd45f3 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/ct_param_runtime.sol @@ -7,13 +7,13 @@ import std; contract ComptimeParamRuntime { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function process(value : word) -> word { + function process(value: word) returns (word) { return double(value); } - function main() -> word { + function main() returns (word) { return process(21); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.sol index f1525446..77a338b9 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt.sol @@ -10,42 +10,39 @@ import std; type uint = uint256; // misleads instance solver -forall i. -class i : Int { - function fromWord(x:word) -> comptime i; // meaning result is comptime whenever arg is +trait Int { + function fromWord(x: word) returns (comptime) ; // meaning result is comptime whenever arg is - function toWord(x:i) -> comptime word; + function toWord(x: i) returns (comptime) ; } -instance word : Int { - function fromWord(x:word) -> comptime word { x } - function toWord(x:word) -> comptime word { x } +impl Int { + function fromWord(x: word) returns (comptime) { x } + function toWord(x: word) returns (comptime) { x } } -instance uint : Int { - function fromWord(x:word) -> comptime uint { uint256(x) } - function toWord(x:uint) -> comptime word { Typedef.rep(x) } +impl Int { + function fromWord(x: word) returns (comptime) { uint256(x) } + function toWord(x: uint) returns (comptime) { Typedef.rep(x) } } // specialised for numbers -forall a b. a:Int, b:Int => function fromInt(x:a) -> b { Int.fromWord(Int.toWord(x)) } -forall a b. a:Int, b:Int => function staticInt(comptime x:a) -> comptime b { Int.fromWord(Int.toWord(x)) } +function fromInt(x: a) returns (b) where a: Int, b: Int { Int.fromWord(Int.toWord(x)) } +function staticInt(comptime x: a) returns (comptime) where a: Int, b: Int { Int.fromWord(Int.toWord(x)) } // limited usability -forall a b r. a:Typedef(r), b:Typedef(r) => function dynamic_cast(x:a) -> b { Typedef.abs(Typedef.rep(x):r) } -forall a b r. a:Typedef(r), b:Typedef(r) => function static_cast(comptime x:a) -> comptime b { Typedef.abs(Typedef.rep(x):r) } +function dynamic_cast(x: a) returns (b) where a: Typedef, b: Typedef { Typedef.abs(Typedef.rep(x)) } +function static_cast(comptime x: a) returns (comptime) where a: Typedef, b: Typedef { Typedef.abs(Typedef.rep(x)) } // wider usability -forall a b r. a:Typedef(r), b:Typedef(r) => -function dynamic_cast_via(p:@r, x:a) -> b { Typedef.abs(Typedef.rep(x):r) } +function dynamic_cast_via(p: @r, x: a) returns (b) where a: Typedef, b: Typedef { Typedef.abs(Typedef.rep(x)) } -forall a b r. a:Typedef(r), b:Typedef(r) => -function static_cast_via(comptime p:@r, comptime x:a) -> comptime b { Typedef.abs(Typedef.rep(x):r) } +function static_cast_via(comptime p: @r, comptime x: a) returns (comptime) where a: Typedef, b: Typedef { Typedef.abs(Typedef.rep(x)) } // maybe: `comptime function static_cast_via` as equivalent notation -function notcomptime(x:word) -> word { +function notcomptime(x: word) returns (word) { let res : word; assembly { res := mload(0) @@ -53,30 +50,30 @@ function notcomptime(x:word) -> word { return res; } -forall a. function id(x:a) -> comptime a { x } -function id_uint(x:uint) -> comptime uint { x } +function id(x: a) returns (comptime) { x } +function id_uint(x: uint) returns (comptime) { x } contract FromWord { constructor() {} - function f1(x : word) -> comptime word { x } - function f2(x : uint) -> comptime uint { x } - function g() -> uint { - let y1 : comptime uint256 = static_cast( // cast on top level of comptime let + function f1(x: word) returns (comptime) { x } + function f2(x: uint) returns (comptime) { x } + function g() returns (uint) { + let y1 : comptime = static_cast( // cast on top level of comptime let f1( static_cast(42) //cast a literal - could be fromWord/staticInt )); - let y2 : comptime uint256 = staticInt( id_uint(staticInt(42)) ); // cast at literal, cast at let + let y2 : comptime = staticInt( id_uint(staticInt(42)) ); // cast at literal, cast at let let z = notcomptime(Typedef.rep(y1)); // no cast - not comptime let t = dynamic_cast(y1); // just testing return t; } - function h() -> comptime uint256 { - let y2 : comptime uint256 = staticInt( ( staticInt(42) ):uint256); // error w/o type annotation + function h() returns (comptime) { + let y2 : comptime = staticInt( ( staticInt(42) )); // error w/o type annotation return y2; } - function main() { + function main() returns (uint) { return g(); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.sol index c2714fab..b5aa5e9a 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt2.sol @@ -1,45 +1,43 @@ // import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; import std; -forall i. -class i : Int { - function fromWord(x:word) -> comptime i; // meaning result is comptime whenever arg is +trait Int { + function fromWord(x: word) returns (comptime) ; // meaning result is comptime whenever arg is - function toWord(x:i) -> comptime word; + function toWord(x: i) returns (comptime) ; } -instance uint256 : Int { - function fromWord(x:word) -> uint256 { Typedef.abs(x) } - function toWord(y:uint256) -> word { Typedef.rep(y) } +impl Int { + function fromWord(x: word) returns (uint256) { Typedef.abs(x) } + function toWord(y: uint256) returns (word) { Typedef.rep(y) } } -instance uint256 : Mul { - function mul(x: uint256, y: uint256) -> uint256 { +impl Mul { + function mul(x: uint256, y: uint256) returns (uint256) { Int.fromWord(Mul.mul(Int.toWord(x), Int.toWord(y))) } } -instance word : Int { - function fromWord(x:word) -> word { x } - function toWord(y:word) -> word { y } +impl Int { + function fromWord(x: word) returns (word) { x } + function toWord(y: word) returns (word) { y } } -function bitAnd(x:word, y:word) -> comptime word { +function bitAnd(x: word, y: word) returns (comptime) { let res : word; assembly { res := and(x,y) } return res; } -forall a. a: Num => -function fromLit(x:word) -> a { Num.fromWord(x) } +function fromLit(x: word) returns (a) where a: Num { Num.fromWord(x) } contract FromInt { - function main() -> uint256 { + function main() returns (uint256) { let a : uint256 = fromLit(1); - let b : comptime uint256 = fromLit((2 + 2)); // CTE + let b : comptime = fromLit((2 + 2)); // CTE let c : uint256 = fromLit(3) + fromLit(3); // RTE // let d : comptime word = fromLit(bitAnd(0xff,keccakLit("foo"+"bar"))); // CTE - let d : comptime word = fromLit(bitAnd(0xff,keccakLit("foo"+"bar"))); // CTE + let d : comptime = fromLit(bitAnd(0xff,keccakLit("foo"+"bar"))); // CTE let k = fromLit(40); return k+2; diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.sol index 88d4cacf..b4342875 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromInt3.sol @@ -1,40 +1,38 @@ // import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; import std; -forall i. -class i : Int { - function fromWord(x:word) -> comptime i; // meaning result is comptime whenever arg is +trait Int { + function fromWord(x: word) returns (comptime) ; // meaning result is comptime whenever arg is - function toWord(x:i) -> comptime word; + function toWord(x: i) returns (comptime) ; } -instance uint256 : Int { - function fromWord(x:word) -> uint256 { Typedef.abs(x) } - function toWord(y:uint256) -> word { Typedef.rep(y) } +impl Int { + function fromWord(x: word) returns (uint256) { Typedef.abs(x) } + function toWord(y: uint256) returns (word) { Typedef.rep(y) } } -instance uint256 : Mul { - function mul(x: uint256, y: uint256) -> uint256 { +impl Mul { + function mul(x: uint256, y: uint256) returns (uint256) { Int.fromWord(Mul.mul(Int.toWord(x), Int.toWord(y))) } } -instance word : Int { - function fromWord(x:word) -> word { x } - function toWord(y:word) -> word { y } +impl Int { + function fromWord(x: word) returns (word) { x } + function toWord(y: word) returns (word) { y } } -function bitAnd(x:word, y:word) -> comptime word { +function bitAnd(x: word, y: word) returns (comptime) { let res : word; assembly { res := and(x,y) } return res; } -forall a. a: Num => -function fromLit(x:word) -> a { Num.fromWord(x) } +function fromLit(x: word) returns (a) where a: Num { Num.fromWord(x) } contract FromInt { - function main() -> uint256 { + function main() returns (uint256) { let k = fromLit(40); return k+2; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.sol index 52b6d15a..fe5f2d21 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/fromLit.sol @@ -1,18 +1,17 @@ import std; -forall a b. class a:FromLit(b) { - function fromLit(l:b) -> a; +trait FromLit { + function fromLit(l: b) returns (a) ; } -forall a b. a:FromLit(b) => -function fromLit(l:b) -> a { FromLit.fromLit(l) } +function fromLit(l: b) returns (a) where a: FromLit { FromLit.fromLit(l) } -instance word:FromLit(word) { - function fromLit(l:word) -> word { l } +impl FromLit { + function fromLit(l: word) returns (word) { l } } -instance uint256:FromLit(word) { - function fromLit(l:word) -> uint256 { uint256(l) } +impl FromLit { + function fromLit(l: word) returns (uint256) { uint256(l) } } /* @@ -22,15 +21,15 @@ default instance a:FromLit(a) { function fromLit(l:a) -> a { l } } */ -instance uint256:Mul { - function mul(a:uint256, b:uint256) -> uint256 { uint256(Mul.mul(Typedef.rep(a),Typedef.rep(b))) } +impl Mul { + function mul(a: uint256, b: uint256) returns (uint256) { uint256(Mul.mul(Typedef.rep(a),Typedef.rep(b))) } } -function main() -> uint256 { +function main() returns (uint256) { let a : uint256 = fromLit(1); - let b : comptime uint256 = fromLit(2 + 2); // CTE + let b : comptime = fromLit(2 + 2); // CTE let c : uint256 = fromLit(3) + fromLit(3); // RTE - let d : comptime word = fromLit(keccakLit("foo"+"bar")); // CTE + let d : comptime = fromLit(keccakLit("foo"+"bar")); // CTE return b*b - fromLit(4)*a*c + fromLit(d); // RTE in RTC } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.sol index 0f0ab9ca..7db1a9e9 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/comptime/string-mem-runtime-fail.sol @@ -3,10 +3,10 @@ // Str.fromString conversion, must be rejected by the type checker. import std; -import std.{*}; +import * from std; contract StringMemRuntimeFail { - public function f() -> memory(string) { + function f() public returns (memory) { let s : string = "x"; return s; } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.sol index 3c01cd4b..a768e126 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/dispatch/fib.sol @@ -1,12 +1,12 @@ -import std.dispatch.{*}; +import * from std.dispatch; -function fib(n : word) -> word { +function fib(n: word) returns (word) { if(n < 2) { return n; } else {return fib(n-1) + fib(n-2); } } contract Fib { constructor() {} - public function test() -> uint256 { + function test() public returns (uint256) { return uint256(fib(10)); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.sol index a8deffa3..99aa703e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/021nid.sol @@ -1,15 +1,15 @@ contract Id1 { - public function id(x) { +function id(x: a) public { return x ; } - public function nid() { + function nid() public { return id; } - public function const(x, y) { return x; } +function const(x: a, y: b) public { return x; } - public function main() { + function main() public { return nid(42); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.snap deleted file mode 100644 index 35214316..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.solc ---- -error[SC0001]: parse error: unexpected `instance` - --> /022nid-invoke.solc:12:1 - | -11 | -12 | instance IdToken(a) : Invokable(a,a) { - | ^^^^^^^^ unexpected token -13 | function invoke(token: IdToken(a), arg:a) -> a { - | - = note: expecting `(`, `;`, or `|` - = note: while parsing data declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.sol index 81346bfe..84c3eb53 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/022nid-invoke.sol @@ -1,22 +1,22 @@ -class self : Invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait Invokable { + function invoke(s: self, a: args) returns (ret) ; } - function id(x) { + function id(x: a) returns (a) { return x ; } - data IdToken(a) = IdToken + enum IdToken { IdToken } -instance IdToken(a) : Invokable(a,a) { - function invoke(token: IdToken(a), arg:a) -> a { +impl Invokable, a, a> { + function invoke(token: IdToken, arg: a) returns (a) { return id(arg); } } contract InvokeId { - public function id(x) { + function id(x: a) public returns (a) { return x ; } @@ -26,11 +26,11 @@ contract InvokeId { } */ - public function nidimpl() { + function nidimpl() public returns (IdToken) { return IdToken; } - public function main() { + function main() public returns (word) { // Instead of: `return nid(42)` return invoke(nidimpl(), 42); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.sol index f4e794d5..dc3586d5 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/024lamid.sol @@ -1,11 +1,11 @@ contract Id1 { - public function id(x) { +function id(x: a) public { return x ; } - public function main() { + function main() public { let nid = lam(x) {return x;}; return nid(42); } -} \ No newline at end of file +} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.snap deleted file mode 100644 index d16ac1a3..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.solc ---- -error[SC0001]: parse error: unexpected `instance` - --> /025lamid-invoke.solc:18:1 - | -17 | -18 | instance Lam0Token(a) : Invokable(a,a) { - | ^^^^^^^^ unexpected token -19 | function invoke(token: Lam0Token(a), arg:a) -> a { - | - = note: expecting `(`, `;`, or `|` - = note: while parsing data declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.sol index 0697ad10..3c47533c 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/025lamid-invoke.sol @@ -7,23 +7,23 @@ contract Id1 { } */ -class self : Invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait Invokable { + function invoke(s: self, a: args) returns (ret) ; } -function lam0impl(x: c) -> c { return x; } +function lam0impl(x: c) returns (c) { return x; } -data Lam0Token(a) = Lam0Token +enum Lam0Token { Lam0Token } -instance Lam0Token(a) : Invokable(a,a) { - function invoke(token: Lam0Token(a), arg:a) -> a { +impl Invokable, a, a> { + function invoke(token: Lam0Token, arg: a) returns (a) { return lam0impl(arg); } } contract InvokeLam { -public function main() { +function main() public returns (word) { let nid = Lam0Token; return invoke(nid, 42); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.snap deleted file mode 100644 index 17ad9ef2..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.solc ---- -error[SC0001]: parse error: unexpected `instance` - --> /026capture.solc:31:1 - | -30 | -31 | instance Lam1Closure(a) : Invokable(a,Word) { - | ^^^^^^^^ unexpected token -32 | function invoke(clos: Lam1Closure(a), arg:a) -> Word { - | - = note: expecting `;`, or `|` - = note: while parsing data declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.sol index 4da24815..b588f3be 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/026capture.sol @@ -8,7 +8,7 @@ contract Id1 { } */ -function addW(x: Word, y:Word) -> Word { +function addW(x: Word, y: Word) returns (Word) { let res : Word; assembly { res := add(x, y) @@ -16,29 +16,31 @@ function addW(x: Word, y:Word) -> Word { return res; } -class self : Invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait Invokable { + function invoke(s: self, a: args) returns (ret) ; } // env might be a tuple, here it is a single Word -function lam1impl(env: Word, x: c) -> c { +function lam1impl(env: Word, x: c) returns (c) { let y = env; return addW(x,y); } -data Lam1Closure(a) = Lam1Closure(Word) +enum Lam1Closure { Lam1Closure(Word) } -instance Lam1Closure(a) : Invokable(a,Word) { - function invoke(clos: Lam1Closure(a), arg:a) -> Word { - match clos { - | Lam1Closure(env) => return lam1impl(env, arg); - }; +impl Invokable, a, Word> { + function invoke(clos: Lam1Closure, arg: a) returns (Word) { + match (clos) { +case Lam1Closure(env) { +return lam1impl(env, arg); +} +} } } contract InvokeCapLam { -public function main() { +function main() public returns (Word) { let y = 42; let clos = Lam1Closure(y); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.snap deleted file mode 100644 index 188695b9..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.solc ---- -error[SC0001]: parse error: unexpected `instance` - --> /027retfun.solc:24:1 - | -23 | -24 | instance Lam1Closure(a) : Invokable(a,Word) { - | ^^^^^^^^ unexpected token -25 | function invoke(clos: Lam1Closure(a), arg:a) -> Word { - | - = note: expecting `;`, or `|` - = note: while parsing data declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.sol index 7bdefb80..08eec9fe 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/027retfun.sol @@ -12,32 +12,34 @@ contract Id1 { } */ -class self : Invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait Invokable { + function invoke(s: self, a: args) returns (ret) ; } // env might be a tuple, here it is a single Word -function lam1impl(env: Word, x: c) -> c { return env; } +function lam1impl(env: Word, x: c) returns (c) { return env; } -data Lam1Closure(a) = Lam1Closure(Word) +enum Lam1Closure { Lam1Closure(Word) } -instance Lam1Closure(a) : Invokable(a,Word) { - function invoke(clos: Lam1Closure(a), arg:a) -> Word { - match clos { - | Lam1Closure(env) => return lam1impl(env, arg); - }; +impl Invokable, a, Word> { + function invoke(clos: Lam1Closure, arg: a) returns (Word) { + match (clos) { +case Lam1Closure(env) { +return lam1impl(env, arg); +} +} } } contract InvokeCapLam { -public function foo() { +function foo() public returns (Lam1Closure) { let y = 42; let clos = Lam1Closure(y); return clos; } -public function main() { +function main() public returns (Word) { return invoke(foo(), 17); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.snap deleted file mode 100644 index a2f2f154..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.solc ---- -error[SC0001]: parse error: unexpected `instance` - --> /028modifier.solc:42:1 - | -41 | -42 | instance FooToken:Invokable(Word, Word) { - | ^^^^^^^^ unexpected token -43 | function invoke(self:FooToken, arg: Word) -> Word { - | - = note: expecting `(`, `;`, or `|` - = note: while parsing data declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.sol index 264f49dd..d07927b2 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/028modifier.sol @@ -1,8 +1,8 @@ -function add1(x) { +function add1(x: Word) returns (Word) { return addW(x,1); } -function addW(x: Word, y:Word) -> Word { +function addW(x: Word, y: Word) returns (Word) { let res : Word; assembly { res := add(x, y) @@ -10,8 +10,8 @@ function addW(x: Word, y:Word) -> Word { return res; } -class self : Invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait Invokable { + function invoke(s: self, a: args) returns (ret) ; } @@ -33,14 +33,14 @@ contract Id1 { } */ -function foo(x:Word) -> Word { +function foo(x: Word) returns (Word) { return addW(x, 2); } -data FooToken = FooToken +enum FooToken { FooToken } -instance FooToken:Invokable(Word, Word) { - function invoke(self:FooToken, arg: Word) -> Word { +impl Invokable { + function invoke(self: FooToken, arg: Word) returns (Word) { return foo(arg); } } @@ -48,7 +48,7 @@ instance FooToken:Invokable(Word, Word) { // lambda in add1mod captures a function // so env contains the closure -forall f.(f: Invokable(Word,Word)) => function lam1impl (env : f, a:Word) { +function lam1impl(env: f, a: Word) returns (Word) where f: Invokable { let f = env; return add1(invoke(f, a)); } @@ -56,7 +56,7 @@ forall f.(f: Invokable(Word,Word)) => function lam1impl (env : f, a:Word) { // we want: // data Lam1Closure = f:Invokable(Word,Word) => Lam1Closure(f) -data Lam1Closure(f) = Lam1Closure(f) +enum Lam1Closure { Lam1Closure(f) } /* function extractEnv(clos: Lam1Closure(f)) -> f { @@ -65,22 +65,24 @@ function extractEnv(clos: Lam1Closure(f)) -> f { }; } */ -instance (f:Invokable(Word,Word)) => Lam1Closure(f) : Invokable(Word,Word) { - function invoke(clos, arg:Word) -> Word { - match clos { - | Lam1Closure(env) => return lam1impl(env, arg); - }; +impl Invokable, Word, Word> where f: Invokable { + function invoke(clos: Lam1Closure, arg: Word) returns (Word) { + match (clos) { +case Lam1Closure(env) { +return lam1impl(env, arg); +} +} } } -function add1mod(f) { +function add1mod(f: f) returns (Lam1Closure) where f: Invokable { return Lam1Closure(f); } contract Modifier { -public function main() { +function main() public returns (Word) { let barClos = add1mod(FooToken); return invoke(barClos, 39); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.snap b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.snap deleted file mode 100644 index 973845d8..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.solc ---- -error[SC0001]: parse error: unexpected `instance` - --> /031enum.solc:15:1 - | -14 | -15 | instance Color : Enum { - | ^^^^^^^^ unexpected token -16 | function fromEnum(c) { - | - = note: expecting `(`, `;`, or `|` - = note: while parsing data declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol index b31d30cd..11f15061 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol @@ -1,4 +1,4 @@ -function addW(x: Word, y:Word) -> Word { +function addW(x: Word, y: Word) returns (Word) { let res : Word; assembly { res := add(x, y) @@ -6,23 +6,29 @@ function addW(x: Word, y:Word) -> Word { return res; } -class a:Enum { - function fromEnum(x:a) -> Word; +trait Enum { + function fromEnum(x: a) returns (Word) ; } - data Color = R | G | B + enum Color { R, G, B } -instance Color : Enum { - function fromEnum(c) { - match c { - | R => return 1; - | Color.G => return 2; - | Color.B => return 3; - }; +impl Enum { + function fromEnum(c: Color) returns (Word) { + match (c) { +case R { +return 1; +} +case Color.G { +return 2; +} +case Color.B { +return 3; +} +} } } -data Bool = False | True +enum Bool { False, True } instance Bool : Enum { function fromEnum(b) { From 0db2f2872e576d249a4fac1537702f51a87fd0ad Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 053/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples Co-authored-by: Codex --- .../fail/test/examples/invokable/031enum.sol | 28 +-- .../fail/test/examples/pragmas/bound.sol | 16 +- .../fail/test/examples/spec/010answer.sol | 2 +- .../corpus/fail/test/examples/spec/011id.sol | 8 +- .../corpus/fail/test/examples/spec/012nid.sol | 8 +- .../fail/test/examples/spec/013comp.sol | 10 +- .../fail/test/examples/spec/027sstore.sol | 2 +- .../fail/test/examples/spec/051expreturn.sol | 42 ++-- .../fail/test/examples/spec/051negBool.sol | 38 ++-- .../fail/test/examples/spec/052negPair.sol | 87 ++++---- .../fail/test/examples/spec/052return.sol | 39 ++-- .../fail/test/examples/spec/053return.sol | 33 +-- .../test/examples/spec/101struct1Field.sol | 191 +++++++++-------- .../fail/test/examples/spec/102uintField.sol | 187 +++++++++-------- .../test/examples/spec/103struct3Fields.sol | 195 +++++++++--------- .../test/examples/spec/105nestedStruct.sol | 10 +- 16 files changed, 464 insertions(+), 432 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol index 11f15061..a24fbfc3 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/invokable/031enum.sol @@ -30,27 +30,31 @@ return 3; enum Bool { False, True } -instance Bool : Enum { - function fromEnum(b) { - match b { - | False => return 0; - | Bool.True => return 1; - }; +impl Enum { + function fromEnum(b: Bool) returns (Word) { + match (b) { +case False { +return 0; +} +case Bool.True { +return 1; +} +} } } -data FromEnumToken(a) = FromEnumToken +enum FromEnumToken { FromEnumToken } -class self : Invokable(args, ret) { - function invoke (s:self, a:args) -> ret; +trait Invokable { + function invoke(s: self, a: args) returns (ret) ; } -instance (a:Enum) => FromEnumToken(a) : Invokable(a,Word) { - function invoke(fet : FromEnumToken(a), arg) -> Word { +impl Invokable, a, Word> where a: Enum { + function invoke(fet: FromEnumToken, arg: a) returns (Word) { return fromEnum(arg); } } contract RGB { - public function main() { + function main() public returns (Word) { /* let x = fromEnum(Color.B); let y = fromEnum(Bool.True); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.sol index 546c850d..e76f23eb 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/pragmas/bound.sol @@ -1,15 +1,15 @@ -forall a . class a:D { function f(x:a); } -forall a b . class a:F(b) {} +trait D { function f(x:a); } +trait F {} -data Memory(a) = Memory(word); +enum Memory { Memory(word) } -forall a . instance Memory(a):F(Memory(Memory(Memory(a)))) {} -forall a c . instance (c:D,a:F(c)) => Memory(Memory(Memory(a))):D { - function f(x:Memory(Memory(Memory(a)))) {} +impl F, Memory>>> {} +impl D>>> { + function f(x:Memory>>) {} } -forall b . function g(y:b) { - let x : Memory(Memory(Memory(Memory(b)))); +function g(y: b) { + let x : Memory>>>; f(x); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.sol index 5699ce86..5681aed3 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/010answer.sol @@ -1,5 +1,5 @@ contract Answer { - public function main() { + function main() public { return 42; } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.sol index 2e79a47e..2bd40e99 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/011id.sol @@ -1,14 +1,14 @@ contract Id1 { - data Bool = False | True; + enum Bool { False, True } - public function id(x) { +function id(x: a) public { return x ; } - public function const(x, y) { return x; } +function const(x: a, y: b) public { return x; } - public function main() { + function main() public { return const(id(42), Bool.False); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.sol index a27a6565..687fdf13 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/012nid.sol @@ -1,15 +1,15 @@ contract Id1 { - public function id(x) { +function id(x: a) public { return x ; } - public function nid() { + function nid() public { return id; } - public function const(x, y) { return x; } +function const(x: a, y: b) public { return x; } - public function main() { + function main() public { return const(nid(42), id(1)); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.sol index a6900271..d99f49ac 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/013comp.sol @@ -1,16 +1,16 @@ contract Compose { - public function compose(f,g) { +function compose(f: function(b) returns (c), g: function(a) returns (b)) public { return lam (x) { return f(g(x)); } ; } - public function id(x) { return x; } +function id(x: a) public { return x; } - public function idid() { return compose(id,id); } + function idid() public { return compose(id,id); } - public function main() { + function main() public { let f = compose(id,id); return f(42); } -} \ No newline at end of file +} diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.sol index cfd5619a..e4b8d5f4 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/027sstore.sol @@ -1,5 +1,5 @@ contract Sstore { - public function main() { + function main() public { let res : word; assembly { sstore(0, 42) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.sol index 9bbbd056..7a974592 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051expreturn.sol @@ -1,10 +1,10 @@ -data Bool = False | True; -data W = W(Word); -data U = U; +enum Bool { False, True } +enum W { W(Word) } +enum U { U } // empty class needed since forall expects a nonempty context -class a :Top {} -instance a:Top {} +trait Top {} +impl Top {} /* For experiments, special handling when emitting code */ // this does not work, typechecker forces a ~ b @@ -13,44 +13,50 @@ instance a:Top {} // forall a.(a:Top) => function ereturn(x:a) -> a // or -forall a . function ereturn(x:a) -> Unit { let res: Unit; return res; } +function ereturn(x: a) returns (Unit) { let res: Unit; return res; } // and then cast it to any type using unsafeCast /* simulate match expression x = match { | Bool.False => return 77; | Bool.True => W(22) } */ -function elimBool1(b:Bool) -> Word { +function elimBool1(b: Bool) returns (Word) { let x : W; x = W(1); - match b { - // this works + match (b) { +// this works // | Bool.False => x = unsafeCast(ereturn(77)); // but this does not - unknown intermediate type // | Bool.False => x = unsafeCast(unsafeCast(ereturn(77))); // what about "return(return 77)"? // this works - | Bool.False => x = unsafeCast(ereturn(ereturn(77))); +case Bool.False { +x = unsafeCast(ereturn(ereturn(77))); // but this does not // | Bool.False => x = unsafeCast(ereturn(unsafeCast(ereturn(77)))); - | Bool.True => x = W(22); - } +} +case Bool.True { +x = W(22); +} +} - match x { - | W(y) => return y; - } + match (x) { +case W(y) { +return y; +} +} } // "semicolon" -forall a. function semi(x:a) -> U { return U;} +function semi(x: a) returns (U) { return U;} -forall a b. function unsafeCast(x:a) -> b { +function unsafeCast(x: a) returns (b) { let res: b; return res; } contract ExpReturn { - public function main() -> Word { + function main() public returns (Word) { return elimBool1(Bool.False); // return elimBool1(Bool.False); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.sol index f034aa1b..dd8236c2 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/051negBool.sol @@ -1,29 +1,37 @@ -class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Neg { - function neg (x : B) { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg (x : B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } contract NegBool { - public function fromB(b) { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) public returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } - public function main() { return fromB(Neg.neg(B.F)); } + function main() public returns (word) { return fromB(Neg.neg(B.F)); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.sol index f578d8e9..37bcb652 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052negPair.sol @@ -1,63 +1,70 @@ -class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; -data Pair(a,b) = Pair(a,b); +enum B { F, T } +enum Pair { Pair(a, b) } -instance B : Neg { - function neg (x : B) { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg (x : B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } -function fst (p) { - match p { - | Pair(x,y) => return x; - } +function fst (p: Pair) returns (a) { + match (p) { +case Pair(x,y) { +return x; +} +} } -function snd(p) { - match p { - | Pair(x,y) => return y; - } +function snd(p: Pair) returns (b) { + match (p) { +case Pair(x,y) { +return y; +} +} } -instance (a:Neg,b:Neg) => Pair(a,b):Neg { - function neg(p) { +impl Neg> where a: Neg, b: Neg { + function neg(p: Pair) returns (Pair) { return Pair(Neg.neg (fst(p)), Neg.neg(snd (p))); } } -/* -instance (a:Neg,b:Neg) => Pair(a,b):Neg { - function neg(p) { - match p { - | Pair(a,b) => return Pair(neg(a), neg(b)); - } - } -} -*/ contract NegPair { - public function bnot(x) { - match x { - | B.T => return B.F; - | B.F => return B.T; - } + function bnot(x: B) public returns (B) { + match (x) { +case B.T { +return B.F; +} +case B.F { +return B.T; +} +} } - public function fromB(b) { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) public returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } - public function main() { return fromB(fst(Neg.neg(Pair(B.F,B.T)))); } + function main() public returns (word) { return fromB(fst(Neg.neg(Pair(B.F,B.T)))); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.sol index e62afc9b..f5cc08c4 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/052return.sol @@ -1,6 +1,6 @@ -data Bool = False | True; -data W = W(word); -data U = U; +enum Bool { False, True } +enum W { W(word) } +enum U { U } /* For experiments, special handling when emitting code */ @@ -10,18 +10,19 @@ data U = U; // function ereturn(x:a) -> a // or -function ereturn(x:a) -> unit { let res: unit; return res; } +function ereturn(x: a) returns (unit) { let res: unit; return res; } // and then cast it to any type using unsafeCast /* simulate match expression x = match { | Bool.False => return 77; | Bool.True => W(22) } */ -function elimBool1(b:Bool) -> word { +function elimBool1(b: Bool) returns (word) { let x : W; x = W(1); - match b { - // this works - | Bool.False => x = unsafeCast(ereturn(77)); + match (b) { +// this works +case Bool.False { +x = unsafeCast(ereturn(77)); // but this does not - unknown intermediate type // | Bool.False => x = unsafeCast(unsafeCast(ereturn(77))); // what about "return(return 77)"? @@ -31,26 +32,30 @@ function elimBool1(b:Bool) -> word { // | Bool.False => x = unsafeCast(ereturn(ereturn(77))); // this does not work (monomorphisation fails): // | Bool.False => x = unsafeCast(ereturn(unsafeCast(ereturn(77)))); +} +case Bool.True { +x = W(22); +} +} - | Bool.True => x = W(22); - } - - match x { - | W(y) => return y; - } + match (x) { +case W(y) { +return y; +} +} } // "semicolon" -function semi(x:a) -> U { return U;} +function semi(x: a) returns (U) { return U;} -function unsafeCast(x:a) -> b { +function unsafeCast(x: a) returns (b) { let res: b; return res; } contract ExpReturn { - public function main() -> word { + function main() public returns (word) { return elimBool1(Bool.False); // return elimBool1(Bool.True); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.sol index 0639c116..abab6d7e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/053return.sol @@ -1,35 +1,40 @@ -data Bool = False | True; -data W = W(word); +enum Bool { False, True } +enum W { W(word) } /* For experiments, special handling when emitting code */ -function ereturn(x:a) -> b { let res: b; return res; } +function ereturn(x: a) returns (b) { let res: b; return res; } /* simulate match expression x = match { | Bool.False => return 77; | Bool.True => W(22) } */ -function elimBool1(b:Bool) -> word { +function elimBool1(b: Bool) returns (word) { let x : W; x = W(1); - match b { - // this works - | Bool.False => x = ereturn(77); + match (b) { +// this works +case Bool.False { +x = ereturn(77); // what about "return(return 77)"? // this does not work (monomorphisation fails) // | Bool.False => x = ereturn(ereturn(77)); +} +case Bool.True { +x = W(22); +} +} - | Bool.True => x = W(22); - } - - match x { - | W(y) => return y; - } + match (x) { +case W(y) { +return y; +} +} } contract ExpReturn { - public function main() -> word { + function main() public returns (word) { return elimBool1(Bool.False); // return elimBool1(Bool.True); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.sol index 35840a39..4d230dd9 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/101struct1Field.sol @@ -1,78 +1,84 @@ /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } -instance word:Typedef(word) { - function rep(x:word) -> word { return x; } - function abs(x:word) -> word { return x;} +impl Typedef { + function rep(x: word) returns (word) { return x; } + function abs(x: word) returns (word) { return x;} } -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -function mload_(x:word) -> word { +function mload_(x: word) returns (word) { let res: word; assembly { res := mload(x) @@ -84,70 +90,67 @@ function mstore_(a:word, v:word) { assembly { mstore(a,v) } } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { - return Typedef.abs(mload_(ptr)):uint; // type annotation needed due to a typechecker bug +impl MemoryType { + function load(ptr: word) returns (uint) { + return Typedef.abs(mload_(ptr)); // type annotation needed due to a typechecker bug } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return mstore_(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) { +impl Assign, a> where a: MemoryType { + function assign(l:memoryRef, y:a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field, Proxy(offset)); +enum MemberAccessProxy { MemberAccessProxy(a, field, Proxy) } -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z,p) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z,p) { +return y; +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } // This is *a lot* of pragmas... // pragma no-coverage-condition CStructField, LValueMemberAccess, RValueMemberAccess; // pragma no-patterson-condition LValueMemberAccess, RValueMemberAccess; // pragma no-bounded-variable-condition LValueMemberAccess, RValueMemberAccess; -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); - -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> memoryRef(fieldType) { +trait CStructField {} +enum StructField { StructField(structType) } + +impl LValueMemberAccess, fieldSelector, offsetType>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -155,29 +158,29 @@ forall structType fieldSelector fieldType offsetType } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -185,14 +188,10 @@ forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , fieldType:MemoryType - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -203,23 +202,23 @@ forall structType fieldSelector fieldType offsetType ////// Testing // struct S { fld1:word; } -data S = S(word); -data fld1_sel = fld1_sel; +enum S { S(word) } +enum fld1_sel { fld1_sel } // data y_sel = y_sel; // data z_sel = z_sel; -instance StructField(S, x_sel):CStructField(word, ()) {} +impl CStructField, word, ()> {} // instance StructField(S, y_sel):CStructField(uint, word) {} // BUG: This next one should really be the following, but that breaks weirdly: // (I get a patterson condition violation on an invoke instance for g) -instance StructField(S, z_sel):CStructField(word, (word,uint)) {} +impl CStructField, word, (word, uint)> {} // So instead I use: // instance StructField(S, z_sel):CStructField(word, word) {} function f() { - let x:memory(word); - let y:memory(word); + let x:memory; + let y:memory; // x = y Assign.assign(ref(x), y); /* @@ -232,12 +231,12 @@ function f() { */ } -function g() -> word { - let s:memory(S) = Typedef.abs(0x80); +function g() returns (word) { + let s:memory = Typedef.abs(0x80); - let offset0 : Proxy( () ) = Proxy; + let offset0 : Proxy<()> = Proxy; // s.fld1 = y - let fld1_lval : memoryRef(word) + let fld1_lval : memoryRef = LValueMemberAccess.memberAccess(MemberAccessProxy(s, fld1_sel, offset0)); Assign.assign(fld1_lval, y); // return s.fld1 @@ -247,7 +246,7 @@ function g() -> word { } contract C { - public function main() { + function main() public returns (word) { f(); return g(); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.sol index 629c0762..0bb4659f 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/102uintField.sol @@ -1,12 +1,12 @@ /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } // this does not work :( /* @@ -17,66 +17,72 @@ forall a } */ -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -function mload_(x:word) -> word { +function mload_(x: word) returns (word) { let res: word; assembly { res := mload(x) @@ -88,70 +94,67 @@ function mstore_(a:word, v:word) { assembly { mstore(a,v) } } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { - return Typedef.abs(mload_(ptr)):uint; // type annotation needed due to a typechecker bug +impl MemoryType { + function load(ptr: word) returns (uint) { + return Typedef.abs(mload_(ptr)); // type annotation needed due to a typechecker bug } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return mstore_(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) { +impl Assign, a> where a: MemoryType { + function assign(l:memoryRef, y:a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field, Proxy(offset)); +enum MemberAccessProxy { MemberAccessProxy(a, field, Proxy) } -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z,p) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z,p) { +return y; +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } // This is *a lot* of pragmas... // pragma no-coverage-condition CStructField, LValueMemberAccess, RValueMemberAccess; // pragma no-patterson-condition LValueMemberAccess, RValueMemberAccess; // pragma no-bounded-variable-condition LValueMemberAccess, RValueMemberAccess; -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); - -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> memoryRef(fieldType) { +trait CStructField {} +enum StructField { StructField(structType) } + +impl LValueMemberAccess, fieldSelector, offsetType>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -159,29 +162,29 @@ forall structType fieldSelector fieldType offsetType } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -189,30 +192,26 @@ forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , fieldType:MemoryType - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } - return MemoryType.load(ptr):fieldType; + return MemoryType.load(ptr); } } ////// Testing // struct S { fld1:uint; } -data S = S(uint); -data fld1_sel = fld1_sel; +enum S { S(uint) } +enum fld1_sel { fld1_sel } // data y_sel = y_sel; // data z_sel = z_sel; -instance StructField(S, fld1_sel):CStructField(uint, ()) {} +impl CStructField, uint, ()> {} // instance StructField(S, y_sel):CStructField(uint, uint) {} // BUG: This next one should really be the following, but that breaks weirdly: // (I get a patterson condition violation on an invoke instance for g) @@ -222,8 +221,8 @@ instance StructField(S, fld1_sel):CStructField(uint, ()) {} function f() { - let x:memory(word); - let y:memory(word); + let x:memory; + let y:memory; // x = y Assign.assign(ref(x), y); /* @@ -236,25 +235,25 @@ function f() { */ } -function g() -> word { - let s:memory(S) = Typedef.abs(0x80); +function g() returns (word) { + let s:memory = Typedef.abs(0x80); // let y:word = 42; let z:uint = uint(42); - let offset0 : Proxy( () ) = Proxy; + let offset0 : Proxy<()> = Proxy; // s.fld1 = z - let fld1_lval : memoryRef(uint) + let fld1_lval : memoryRef = LValueMemberAccess.memberAccess(MemberAccessProxy(s, fld1_sel, offset0)); Assign.assign(fld1_lval, z); // return s.fld1 let r : uint = uint(17); r = RValueMemberAccess.memberAccess(MemberAccessProxy(s, fld1_sel, offset0) ); - let r2 : word = Typedef.rep(r : uint); + let r2 : word = Typedef.rep(r ); return r2; } contract C { - public function main() { + function main() public returns (word) { f(); return g(); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.sol index 87bf761b..df3f5d4d 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/103struct3Fields.sol @@ -1,7 +1,7 @@ // v4: Simplified Member AccessProxy (no Proxy(offset)) // variables holding field MAPs -function add(x : word, y : word) { +function add(x : word, y : word) returns (word) { let res: word; assembly { res := add(x, y) @@ -10,13 +10,13 @@ function add(x : word, y : word) { } /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } // this does not work :( /* @@ -27,66 +27,72 @@ forall a } */ -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -function mload_(x:word) -> word { +function mload_(x: word) returns (word) { let res: word; assembly { res := mload(x) @@ -98,66 +104,63 @@ function mstore_(a:word, v:word) { assembly { mstore(a,v) } } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { - return Typedef.abs(mload_(ptr)):uint; +impl MemoryType { + function load(ptr: word) returns (uint) { + return Typedef.abs(mload_(ptr)); } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return mstore_(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) { +impl Assign, a> where a: MemoryType { + function assign(l:memoryRef, y:a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> memoryRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -165,20 +168,20 @@ forall structType fieldSelector fieldType offsetType } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } @@ -194,10 +197,10 @@ forall a b . a:Typedef(b), b:MemorySize } */ -forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -205,48 +208,44 @@ forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , fieldType:MemoryType - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } - return MemoryType.load(ptr):fieldType; + return MemoryType.load(ptr); } } ////// Testing // struct S { fld1:uint; fld2:word; fld3:word } -data S = S; // (uint, word, word); -data fld1_sel = fld1_sel; -data fld2_sel = fld2_sel; -data fld3_sel = fld3_sel; +enum S { S } // (uint, word, word); +enum fld1_sel { fld1_sel } +enum fld2_sel { fld2_sel } +enum fld3_sel { fld3_sel } // form: // instance StructField(S, f_sel):CStructField(ftype, preceding)) {} -instance StructField(S, fld1_sel):CStructField(uint, ()) {} -instance StructField(S, fld2_sel):CStructField(word, uint) {} -instance StructField(S, fld3_sel):CStructField(word, (uint, word)) {} +impl CStructField, uint, ()> {} +impl CStructField, word, uint> {} +impl CStructField, word, (uint, word)> {} -function g() -> word { - let s:memory(S) = Typedef.abs(0x80); - let fld1_map : MemberAccessProxy(memory(S), fld1_sel, ()) = MemberAccessProxy(s, fld1_sel); - let fld2_map : MemberAccessProxy(memory(S), fld2_sel, uint) = MemberAccessProxy(s, fld2_sel); +function g() returns (word) { + let s:memory = Typedef.abs(0x80); + let fld1_map : MemberAccessProxy, fld1_sel, ()> = MemberAccessProxy(s, fld1_sel); + let fld2_map : MemberAccessProxy, fld2_sel, uint> = MemberAccessProxy(s, fld2_sel); let fld3_map = MemberAccessProxy(s, fld3_sel) - : MemberAccessProxy(memory(S), fld3_sel, (uint,word)); + ; // let y:word = 13; let z:uint = uint(13); // s.fld1 = z - let fld1_lval : memoryRef(uint) + let fld1_lval : memoryRef = LValueMemberAccess.memberAccess(fld1_map ); Assign.assign(fld1_lval, z); @@ -270,7 +269,7 @@ function g() -> word { let f3 : word; f3 = RValueMemberAccess.memberAccess(fld3_map); - let f12 = add(Typedef.rep(f1) : word, f2); + let f12 = add(Typedef.rep(f1) , f2); let f123 = add(f12, f3); return f123; @@ -278,7 +277,7 @@ function g() -> word { } contract C { - public function main() { + function main() public returns (word) { return g(); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol index 6a6cc7df..b1c73c3b 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol @@ -1,7 +1,7 @@ // v5: nested struct // variables holding field MAPs -function add(x : word, y : word) { +function add(x : word, y : word) returns (word) { let res: word; assembly { res := add(x, y) @@ -10,13 +10,13 @@ function add(x : word, y : word) { } /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } // this does not work :( /* From fe1a9119062e6d772b0edca457677bd36b13cdee Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 054/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test examples Co-authored-by: Codex --- .../test/examples/spec/105nestedStruct.sol | 232 +++++++++--------- .../test/examples/spec/111storageStruct.sol | 189 +++++++------- .../test/examples/spec/112ContractStorage.sol | 12 +- .../fail/test/examples/spec/113counter.sol | 6 +- .../test/examples/spec/131constructor.sol | 6 +- .../fail/test/examples/spec/135cons3.sol | 19 +- .../fail/test/examples/spec/StorageLib.sol | 186 +++++++------- .../test/examples/spec/attic/051expreturn.sol | 42 ++-- .../test/examples/spec/attic/052return.sol | 39 +-- .../test/examples/spec/attic/053return.sol | 33 +-- 10 files changed, 382 insertions(+), 382 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol index b1c73c3b..b228d7c9 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/105nestedStruct.sol @@ -27,66 +27,72 @@ forall a } */ -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -function mload_(x:word) -> word { +function mload_(x: word) returns (word) { let res: word; assembly { res := mload(x) @@ -98,75 +104,72 @@ function mstore_(a:word, v:word) { assembly { mstore(a,v) } } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { +impl MemoryType { + function load(ptr: word) returns (uint) { return Typedef.abs(mload_(ptr)); } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return mstore_(ptr, Typedef.rep(value)); } } -forall a . instance memory(a):MemoryType { - function load(ptr:word) -> memory(a) { +impl MemoryType> { + function load(ptr: word) returns (memory) { return Typedef.abs(mload_(ptr)); } - function store(ptr:word, value:memory(a)) -> () { + function store(ptr: word, value: memory) { return mstore_(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) { +impl Assign, a> where a: MemoryType { + function assign(l:memoryRef, y:a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> memoryRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -174,27 +177,26 @@ forall structType fieldSelector fieldType offsetType } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -forall a -. instance memory(a):MemorySize { - function size(x:Proxy(memory(a))) -> word { +impl MemorySize> { + function size(x: Proxy>) returns (word) { return 32; } } @@ -210,10 +212,10 @@ forall a b . a:Typedef(b), b:MemorySize } */ -forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -221,55 +223,51 @@ forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , fieldType:MemoryType - , offsetType:MemorySize - => instance MemberAccessProxy(memory(structType), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } - return MemoryType.load(ptr):fieldType; + return MemoryType.load(ptr); } } ////// Testing // struct S { fld1:uint; fld2:word; fld3:word } -data S = S; // (uint, word, word); +enum S { S } // (uint, word, word); // struct W { flds : memory(W) } -data W = W; +enum W { W } -data fld1_sel = fld1_sel; -data fld2_sel = fld2_sel; -data fld3_sel = fld3_sel; +enum fld1_sel { fld1_sel } +enum fld2_sel { fld2_sel } +enum fld3_sel { fld3_sel } -data flds_sel = flds_sel; +enum flds_sel { flds_sel } // form: // instance StructField(S, f_sel):CStructField(ftype, preceding)) {} -instance StructField(S, fld1_sel):CStructField(uint, ()) {} -instance StructField(S, fld2_sel):CStructField(word, uint) {} -instance StructField(S, fld3_sel):CStructField(word, (uint, word)) {} +impl CStructField, uint, ()> {} +impl CStructField, word, uint> {} +impl CStructField, word, (uint, word)> {} -instance StructField(W, flds_sel):CStructField(memory(S), ()) {} +impl CStructField, memory, ()> {} -function makeS() -> memory(S) { - let s:memory(S) = Typedef.abs(0x80); - let fld1_map : MemberAccessProxy(memory(S), fld1_sel, ()) = MemberAccessProxy(s, fld1_sel); - let fld2_map : MemberAccessProxy(memory(S), fld2_sel, uint) = MemberAccessProxy(s, fld2_sel); +function makeS() returns (memory) { + let s:memory = Typedef.abs(0x80); + let fld1_map : MemberAccessProxy, fld1_sel, ()> = MemberAccessProxy(s, fld1_sel); + let fld2_map : MemberAccessProxy, fld2_sel, uint> = MemberAccessProxy(s, fld2_sel); let fld3_map = MemberAccessProxy(s, fld3_sel) - : MemberAccessProxy(memory(S), fld3_sel, (uint,word)); + ; // let y:word = 13; let z:uint = uint(13); // s.fld1 = z - let fld1_lval : memoryRef(uint) + let fld1_lval : memoryRef = LValueMemberAccess.memberAccess(fld1_map ); Assign.assign(fld1_lval, z); @@ -285,12 +283,12 @@ function makeS() -> memory(S) { return s; } -function readS(s:memory(S)) -> word { - let s:memory(S) = Typedef.abs(0x80); - let fld1_map : MemberAccessProxy(memory(S), fld1_sel, ()) = MemberAccessProxy(s, fld1_sel); - let fld2_map : MemberAccessProxy(memory(S), fld2_sel, uint) = MemberAccessProxy(s, fld2_sel); +function readS(s: memory) returns (word) { + let s:memory = Typedef.abs(0x80); + let fld1_map : MemberAccessProxy, fld1_sel, ()> = MemberAccessProxy(s, fld1_sel); + let fld2_map : MemberAccessProxy, fld2_sel, uint> = MemberAccessProxy(s, fld2_sel); let fld3_map = MemberAccessProxy(s, fld3_sel) - : MemberAccessProxy(memory(S), fld3_sel, (uint,word)); + ; // let f1 = s.fld1 let f1 : uint; @@ -303,41 +301,41 @@ function readS(s:memory(S)) -> word { let f3 : word; f3 = RValueMemberAccess.memberAccess(fld3_map); - let f12 = add(Typedef.rep(f1) : word, f2); + let f12 = add(Typedef.rep(f1) , f2); let f123 = add(f12, f3); return f123; } -function rwS() -> word { - let s:memory(S) = makeS(); +function rwS() returns (word) { + let s:memory = makeS(); return readS(s); } -function makeW(s:memory(S)) -> memory(W) { - let w:memory(W) = Typedef.abs(0xe0); - let flds_map : MemberAccessProxy(memory(W), flds_sel, ()) = MemberAccessProxy(w, flds_sel); +function makeW(s: memory) returns (memory) { + let w:memory = Typedef.abs(0xe0); + let flds_map : MemberAccessProxy, flds_sel, ()> = MemberAccessProxy(w, flds_sel); // w.flds = s - let flds_lval : memoryRef(memory(S)) + let flds_lval : memoryRef> = LValueMemberAccess.memberAccess(flds_map ); Assign.assign(flds_lval, s); return w; } -function readW(w:memory(W)) -> memory(S) { - let flds_map : MemberAccessProxy(memory(W), flds_sel, ()) = MemberAccessProxy(w, flds_sel); +function readW(w: memory) returns (memory) { + let flds_map : MemberAccessProxy, flds_sel, ()> = MemberAccessProxy(w, flds_sel); return RValueMemberAccess.memberAccess(flds_map); } contract C { - public function main() { - let s:memory(S) = makeS(); - let w:memory(W) = makeW(s); - let s2:memory(S) = readW(w); + function main() public returns (word) { + let s:memory = makeS(); + let w:memory = makeW(s); + let s2:memory = readW(w); return readS(s2); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.sol index a65ae96c..92759dc9 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/111storageStruct.sol @@ -1,7 +1,7 @@ // v4: Simplified Member AccessProxy (no Proxy(offset)) // variables holding field MAPs -function add(x : word, y : word) { +function add(x : word, y : word) returns (word) { let res: word; assembly { res := add(x, y) @@ -10,13 +10,13 @@ function add(x : word, y : word) { } /////// Construction -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } // this does not work :( /* @@ -27,44 +27,50 @@ forall a } */ -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data storage(a) = storage(word); -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storage { storage(word) } +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -instance storage(a):Typedef(word) { - function rep(x:storage(a)) -> word { - match x { - | storage(y) => return y; - } +impl Typedef, word> { + function rep(x: storage) returns (word) { + match (x) { +case storage(y) { +return y; +} +} } - function abs(x:word) -> storage(a) { + function abs(x: word) returns (storage) { return storage(x); } } -instance storageRef(a):Typedef(word) { - function rep(x:storageRef(a)) -> word { - match x { - | storageRef(y) => return y; - } +impl Typedef, word> { + function rep(x: storageRef) returns (word) { + match (x) { +case storageRef(y) { +return y; +} +} } - function abs(x:word) -> storageRef(a) { + function abs(x: word) returns (storageRef) { return storageRef(x); } } -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } /* @@ -78,17 +84,17 @@ instance ref(a):Assign(a) { } */ -class self:StorageType { - function sload(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait StorageType { + function sload(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -function sload_(x:word) -> word { +function sload_(x: word) returns (word) { let res: word; assembly { res := sload(x) @@ -100,66 +106,63 @@ function sstore_(a:word, v:word) { assembly { sstore(a,v) } } -instance word:StorageType { - function sload(ptr:word) -> word { +impl StorageType { + function sload(ptr: word) returns (word) { let r:word; assembly { r := sload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { sstore(ptr, value) } } } -instance uint:StorageType { - function sload(ptr:word) -> uint { - return Typedef.abs(sload_(ptr)):uint; // type annotation needed due to a typechecker bug +impl StorageType { + function sload(ptr: word) returns (uint) { + return Typedef.abs(sload_(ptr)); // type annotation needed due to a typechecker bug } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return sstore_(ptr, Typedef.rep(value)); } } -forall a . a : StorageType => instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) { +impl Assign, a> where a: StorageType { + function assign(l:storageRef, y:a) { StorageType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(storage(structType), fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(storage(structType), fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); + let size:word = StorageSize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -167,20 +170,20 @@ forall structType fieldSelector fieldType offsetType } } -instance ():StorageSize { - function size(x:Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance uint:StorageSize { - function size(x:Proxy(uint)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } @@ -196,10 +199,10 @@ forall a b . a:Typedef(b), b:StorageSize } */ -forall a b . a:StorageSize, b:StorageSize => instance (a,b):StorageSize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = StorageSize.size(Proxy:Proxy(a)); - let b_sz:word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = StorageSize.size(@a); + let b_sz:word = StorageSize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -207,18 +210,14 @@ forall a b . a:StorageSize, b:StorageSize => instance (a,b):StorageSize { } } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , fieldType:StorageType - , offsetType:StorageSize - => instance MemberAccessProxy(storage(structType), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(storage(structType), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField: CStructField, fieldType: StorageType, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); + let size:word = StorageSize.size(@offsetType); assembly { ptr := add(ptr, size) } - return StorageType.sload(ptr):fieldType; + return StorageType.sload(ptr); } } @@ -227,30 +226,30 @@ forall structType fieldSelector fieldType offsetType ////// Testing // struct S { fld1:uint; fld2:word; fld3:word } -data S = S; // (uint, word, word); -data fld1_sel = fld1_sel; -data fld2_sel = fld2_sel; -data fld3_sel = fld3_sel; +enum S { S } // (uint, word, word); +enum fld1_sel { fld1_sel } +enum fld2_sel { fld2_sel } +enum fld3_sel { fld3_sel } // form: // instance StructField(S, f_sel):CStructField(ftype, preceding)) {} -instance StructField(S, fld1_sel):CStructField(uint, ()) {} -instance StructField(S, fld2_sel):CStructField(word, uint) {} -instance StructField(S, fld3_sel):CStructField(word, (uint, word)) {} +impl CStructField, uint, ()> {} +impl CStructField, word, uint> {} +impl CStructField, word, (uint, word)> {} -function g() -> word { - let s:storage(S) = Typedef.abs(0x80); - let fld1_map : MemberAccessProxy(storage(S), fld1_sel, ()) = MemberAccessProxy(s, fld1_sel); - let fld2_map : MemberAccessProxy(storage(S), fld2_sel, uint) = MemberAccessProxy(s, fld2_sel); +function g() returns (word) { + let s:storage = Typedef.abs(0x80); + let fld1_map : MemberAccessProxy, fld1_sel, ()> = MemberAccessProxy(s, fld1_sel); + let fld2_map : MemberAccessProxy, fld2_sel, uint> = MemberAccessProxy(s, fld2_sel); let fld3_map = MemberAccessProxy(s, fld3_sel) - : MemberAccessProxy(storage(S), fld3_sel, (uint,word)); + ; // let y:word = 13; let z:uint = uint(13); // s.fld1 = z - let fld1_lval : storageRef(uint) + let fld1_lval : storageRef = LValueMemberAccess.memberAccess(fld1_map ); Assign.assign(fld1_lval, z); @@ -274,7 +273,7 @@ function g() -> word { let f3 : word; f3 = RValueMemberAccess.memberAccess(fld3_map); - let f12 = add(Typedef.rep(f1) : word, f2); + let f12 = add(Typedef.rep(f1) , f2); let f123 = add(f12, f3); return f123; @@ -282,7 +281,7 @@ function g() -> word { } contract C { - public function main() { + function main() public returns (word) { return g(); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.sol index f672661a..02e1edf6 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/112ContractStorage.sol @@ -16,16 +16,16 @@ contract Counter { // form: // instance StructField(S, f_sel):CStructField(ftype, preceding)) {} -data CounterCxt = CounterCxt; -data counter_sel = counter_sel; -instance StructField(ContractStorage(CounterCxt), counter_sel):CStructField(word, ()) {} +enum CounterCxt { CounterCxt } +enum counter_sel { counter_sel } +impl CStructField, counter_sel>, word, ()> {} contract Counter { // struct CounterCxt { counter:word } - public function main() -> word { - let cxt : ContractStorage(CounterCxt) = ContractStorage(CounterCxt); - let counter_map : MemberAccessProxy(ContractStorage(CounterCxt), counter_sel, ()) + function main() public returns (word) { + let cxt : ContractStorage = ContractStorage(CounterCxt); + let counter_map : MemberAccessProxy, counter_sel, ()> = MemberAccessProxy(cxt, counter_sel); // let c1 = this.counter diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.sol index 7fd85e4b..985806e7 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/113counter.sol @@ -11,11 +11,11 @@ contract Counter { } */ -data counter_sel = counter_sel; -instance StructField(ContractStorage(()), counter_sel):CStructField(word, ()) {} +enum counter_sel { counter_sel } +impl CStructField, counter_sel>, word, ()> {} contract Counter { - public function main () -> word { + function main() public returns (word) { let counter_map /*: MemberAccessProxy(ContractStorage(()), counter_sel, ()) */ = MemberAccessProxy(ContractStorage(()), counter_sel); Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(()), counter_sel)), add(rval(counter_map), 1)); return rval(counter_map); diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.sol index 4e0381b9..ab26a3ff 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/131constructor.sol @@ -2,13 +2,13 @@ contract Counter { - public function setCounter(v: word) { + function setCounter(v: word) public { assembly { sstore(0x00, v) } } - public function getCounter() -> word { + function getCounter() public returns (word) { let res; assembly { res := sload(0x00) @@ -21,7 +21,7 @@ contract Counter { setCounter(42); } - public function main() -> word { + function main() public returns (word) { return getCounter(); } } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.sol index 9e808a4c..ba775985 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/135cons3.sol @@ -1,10 +1,9 @@ // test constructor with multiple args -import std.{*}; +import * from std; // import prelude; -forall t.t:Typedef(word) => -function log1(v:t, topic:word) -> () { +function log1(v: t, topic: word) where t: Typedef { let w : word = Typedef.rep(v); assembly { mstore(0,w) @@ -15,15 +14,17 @@ function log1(v:t, topic:word) -> () { contract Counter { // setCounter & getCounter are intentionally low-level to avoid clutter - public function setCounter(v: uint256) -> () { - match v { | uint256(w) => - assembly { + function setCounter(v: uint256) public { + match (v) { +case uint256(w) { +assembly { sstore(0x00, w) } - } +} +} } - public function getCounter() -> uint256 { + function getCounter() public returns (uint256) { let res; assembly { res := sload(0x00) @@ -90,7 +91,7 @@ contract Counter { */ // TODO: remove main, use dispatch instead - function main() -> uint256 { + function main() returns (uint256) { return getCounter(); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.sol index 9047f00a..222ac6f1 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/StorageLib.sol @@ -10,14 +10,13 @@ function add(x : word, y : word) { } /////// Construction -forall abs rep. -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } // this does not work :( /* @@ -28,75 +27,75 @@ forall a } */ -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data storage(a) = storage(word); -data ContractStorage(cxt) = ContractStorage(cxt); +enum storage { storage(word) } +enum ContractStorage { ContractStorage(cxt) } -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -forall a. -instance storage(a):Typedef(word) { - function rep(x:storage(a)) -> word { - match x { - | storage(y) => return y; - } +impl Typedef, word> { + function rep(x: storage) returns (word) { + match (x) { +case storage(y) { +return y; +} +} } - function abs(x:word) -> storage(a) { + function abs(x: word) returns (storage) { return storage(x); } } -forall a. -instance storageRef(a):Typedef(word) { - function rep(x:storageRef(a)) -> word { - match x { - | storageRef(y) => return y; - } +impl Typedef, word> { + function rep(x: storageRef) returns (word) { + match (x) { +case storageRef(y) { +return y; +} +} } - function abs(x:word) -> storageRef(a) { + function abs(x: word) returns (storageRef) { return storageRef(x); } } -forall lhs rhs. -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -forall a. -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -forall self. -class self:StorageType { - function sload(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait StorageType { + function sload(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -forall self. -class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -function sload_(x:word) -> word { +function sload_(x: word) returns (word) { let res: word; assembly { res := sload(x) @@ -108,68 +107,63 @@ function sstore_(a:word, v:word) { assembly { sstore(a,v) } } -instance word:StorageType { - function sload(ptr:word) -> word { +impl StorageType { + function sload(ptr: word) returns (word) { let r:word; assembly { r := sload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { sstore(ptr, value) } } } -instance uint:StorageType { - function sload(ptr:word) -> uint { - return Typedef.abs(sload_(ptr)):uint; // type annotation needed due to a typechecker bug +impl StorageType { + function sload(ptr: word) returns (uint) { + return Typedef.abs(sload_(ptr)); // type annotation needed due to a typechecker bug } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return sstore_(ptr, Typedef.rep(value)); } } -forall a . a : StorageType => instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) -> () { +impl Assign, a> where a: StorageType { + function assign(l: storageRef, y: a) { StorageType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +enum MemberAccessProxy { MemberAccessProxy(a, field) } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -forall self memberRefType . -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } -forall self fieldType offsetType . -class self:CStructField(fieldType, offsetType) {} +trait CStructField {} -data StructField(structType, fieldSelector) = StructField(structType); +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(storage(structType), fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(storage(structType), fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); + let size:word = StorageSize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -177,20 +171,20 @@ forall structType fieldSelector fieldType offsetType } } -instance ():StorageSize { - function size(x:Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance uint:StorageSize { - function size(x:Proxy(uint)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } @@ -206,10 +200,10 @@ forall a b . a:Typedef(b), b:StorageSize } */ -forall a b . a:StorageSize, b:StorageSize => instance (a,b):StorageSize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = StorageSize.size(Proxy:Proxy(a)); - let b_sz:word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = StorageSize.size(@a); + let b_sz:word = StorageSize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -220,13 +214,10 @@ forall a b . a:StorageSize, b:StorageSize => instance (a,b):StorageSize { pragma no-patterson-condition RValueMemberAccess; // this is due to ContractStorage(cxt); probably not needed once we have local instances pragma no-coverage-condition LValueMemberAccess, RValueMemberAccess; -forall cxt fieldSelector fieldType offsetType - . StructField(ContractStorage(cxt), fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField, fieldSelector>: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr:word = 0x100; // forge uses at least 1 storage slot - let offsetSize:word = StorageSize.size(Proxy:Proxy(offsetType)); + let offsetSize:word = StorageSize.size(@offsetType); assembly { ptr := add(ptr, offsetSize) @@ -235,19 +226,14 @@ forall cxt fieldSelector fieldType offsetType } } -forall cxt fieldSelector fieldType offsetType - . StructField(ContractStorage(cxt), fieldSelector):CStructField(fieldType, offsetType) - , fieldType:StorageType - , offsetType:StorageSize - => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField, fieldSelector>: CStructField, fieldType: StorageType, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = 0x100; - let offsetSize:word = StorageSize.size(Proxy:Proxy(offsetType)); - return StorageType.sload(add(ptr, offsetSize)):fieldType; + let offsetSize:word = StorageSize.size(@offsetType); + return StorageType.sload(add(ptr, offsetSize)); } } -forall a b. a:RValueMemberAccess(b) => -function rval(x:a) -> b { +function rval(x: a) returns (b) where a: RValueMemberAccess { return RValueMemberAccess.memberAccess(x); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.sol index 33b372b3..37be4543 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/051expreturn.sol @@ -1,10 +1,10 @@ -data Bool = False | True; -data W = W(Word); -data U = U; +enum Bool { False, True } +enum W { W(Word) } +enum U { U } // empty class needed since forall expects a nonempty context -class a :Top {} -instance a:Top {} +trait Top {} +impl Top {} /* For experiments, special handling when emitting code */ // this does not work, typechecker forces a ~ b @@ -13,38 +13,44 @@ instance a:Top {} // forall a.(a:Top) => function ereturn(x:a) -> a // or -forall a:Top . function ereturn(x:a) -> Unit { let res: Unit; return res; } +function ereturn(x: a) returns (Unit) where a: Top { let res: Unit; return res; } // and then cast it to any type using unsafeCast /* simulate match expression x = match { | Bool.False => return 77; | Bool.True => W(22) } */ -function elimBool1(b:Bool) -> Word { +function elimBool1(b: Bool) returns (Word) { let x : W; x = W(1); - match b { - // this works + match (b) { +// this works // | Bool.False => x = unsafeCast(ereturn(77)); // but this does not - unknown intermediate type // | Bool.False => x = unsafeCast(unsafeCast(ereturn(77))); // what about "return(return 77)"? // this works - | Bool.False => x = unsafeCast(ereturn(ereturn(77))); +case Bool.False { +x = unsafeCast(ereturn(ereturn(77))); // but this does not // | Bool.False => x = unsafeCast(ereturn(unsafeCast(ereturn(77)))); - | Bool.True => x = W(22); - }; +} +case Bool.True { +x = W(22); +} +} - match x { - | W(y) => return y; - }; + match (x) { +case W(y) { +return y; +} +} } // "semicolon" -forall a:Top . function semi(x:a) -> U { return U;} +function semi(x: a) returns (U) where a: Top { return U;} -forall a:Top, b:Top . function unsafeCast(x:a) -> b { +function unsafeCast(x: a) returns (b) where a: Top, b: Top { let res: b; return res; } @@ -53,7 +59,7 @@ contract ExpReturn { - public function main() -> Word { + function main() public returns (Word) { return elimBool1(Bool.False); // return elimBool1(Bool.False); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.sol index 620987e9..f5cc08c4 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/052return.sol @@ -1,6 +1,6 @@ -data Bool = False | True; -data W = W(word); -data U = U; +enum Bool { False, True } +enum W { W(word) } +enum U { U } /* For experiments, special handling when emitting code */ @@ -10,18 +10,19 @@ data U = U; // function ereturn(x:a) -> a // or -function ereturn(x:a) -> unit { let res: unit; return res; } +function ereturn(x: a) returns (unit) { let res: unit; return res; } // and then cast it to any type using unsafeCast /* simulate match expression x = match { | Bool.False => return 77; | Bool.True => W(22) } */ -function elimBool1(b:Bool) -> word { +function elimBool1(b: Bool) returns (word) { let x : W; x = W(1); - match b { - // this works - | Bool.False => x = unsafeCast(ereturn(77)); + match (b) { +// this works +case Bool.False { +x = unsafeCast(ereturn(77)); // but this does not - unknown intermediate type // | Bool.False => x = unsafeCast(unsafeCast(ereturn(77))); // what about "return(return 77)"? @@ -31,26 +32,30 @@ function elimBool1(b:Bool) -> word { // | Bool.False => x = unsafeCast(ereturn(ereturn(77))); // this does not work (monomorphisation fails): // | Bool.False => x = unsafeCast(ereturn(unsafeCast(ereturn(77)))); +} +case Bool.True { +x = W(22); +} +} - | Bool.True => x = W(22); - }; - - match x { - | W(y) => return y; - }; + match (x) { +case W(y) { +return y; +} +} } // "semicolon" -function semi(x:a) -> U { return U;} +function semi(x: a) returns (U) { return U;} -function unsafeCast(x:a) -> b { +function unsafeCast(x: a) returns (b) { let res: b; return res; } contract ExpReturn { - public function main() -> word { + function main() public returns (word) { return elimBool1(Bool.False); // return elimBool1(Bool.True); } diff --git a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.sol b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.sol index 29836b50..abab6d7e 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/examples/spec/attic/053return.sol @@ -1,35 +1,40 @@ -data Bool = False | True; -data W = W(word); +enum Bool { False, True } +enum W { W(word) } /* For experiments, special handling when emitting code */ -function ereturn(x:a) -> b { let res: b; return res; } +function ereturn(x: a) returns (b) { let res: b; return res; } /* simulate match expression x = match { | Bool.False => return 77; | Bool.True => W(22) } */ -function elimBool1(b:Bool) -> word { +function elimBool1(b: Bool) returns (word) { let x : W; x = W(1); - match b { - // this works - | Bool.False => x = ereturn(77); + match (b) { +// this works +case Bool.False { +x = ereturn(77); // what about "return(return 77)"? // this does not work (monomorphisation fails) // | Bool.False => x = ereturn(ereturn(77)); +} +case Bool.True { +x = W(22); +} +} - | Bool.True => x = W(22); - }; - - match x { - | W(y) => return y; - }; + match (x) { +case W(y) { +return y; +} +} } contract ExpReturn { - public function main() -> word { + function main() public returns (word) { return elimBool1(Bool.False); // return elimBool1(Bool.True); } From 2288abc1426145c6eec4bfee95cdae1578c3c746 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 055/110] Switch the compiler and fixtures to canonical syntax: parser corpus fail test imports Co-authored-by: Codex --- .../fail/test/imports/select_alias_tail_fail.snap | 15 --------------- .../fail/test/imports/select_alias_tail_fail.sol | 4 ++-- 2 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.snap diff --git a/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.snap b/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.snap deleted file mode 100644 index 34cd0b91..00000000 --- a/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/parser/tests/diagnostics.rs -expression: value -input_file: crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.solc ---- -error[SC0001]: parse error: unexpected `as` - --> /select_alias_tail_fail.solc:1:25 - | -1 | import selectlib.{keep} as keep_; - | ^^ unexpected token -2 | -3 | function main(x: word) -> word { - | - = note: expecting `;` - = note: while parsing import declaration diff --git a/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.sol b/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.sol index ca1765fb..59d06321 100644 --- a/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.sol +++ b/crates/parser/tests/fixtures/corpus/fail/test/imports/select_alias_tail_fail.sol @@ -1,5 +1,5 @@ -import selectlib.{keep} as keep_; +import {keep} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return keep_(x); } From 9297ccd49d230d6361464c951d82239bfa628f01 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 056/110] Switch the compiler and fixtures to canonical syntax: parser corpus known diagnostic gaps test diagnostics Co-authored-by: Codex --- .../test/diagnostics/duplicate-definition.sol | 6 +++--- .../test/diagnostics/not-polymorphic-enough.sol | 2 +- .../test/diagnostics/type-mismatch.sol | 2 +- .../test/diagnostics/undefined-name.sol | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.sol b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.sol index 11e1185e..ea0d4cc1 100644 --- a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.sol +++ b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/duplicate-definition.sol @@ -1,3 +1,3 @@ -function foo() -> word { return 1; } -function foo() -> word { return 2; } -function main() -> word { return foo(); } +function foo() returns (word) { return 1; } +function foo() returns (word) { return 2; } +function main() returns (word) { return foo(); } diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.sol b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.sol index 7400c26c..9411dc19 100644 --- a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.sol +++ b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/not-polymorphic-enough.sol @@ -1,4 +1,4 @@ -forall a . function fromWord(x : word) -> a { +function fromWord(x: word) returns (a) { let result; assembly { result := x } return result; diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.sol b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.sol index 64d7ed2c..2ca138c6 100644 --- a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.sol +++ b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/type-mismatch.sol @@ -1 +1 @@ -function main() -> word { return true; } +function main() returns (word) { return true; } diff --git a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.sol b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.sol index 6aae2ad1..db2d49cd 100644 --- a/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.sol +++ b/crates/parser/tests/fixtures/corpus/known-diagnostic-gaps/test/diagnostics/undefined-name.sol @@ -1 +1 @@ -function main() -> word { return missing; } +function main() returns (word) { return missing; } From 4c6e50012d2e8c48daff3fbd550cb790c14c38aa Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 057/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std ABIGeneric.sol Co-authored-by: Codex --- .../fixtures/corpus/ok/std/ABIGeneric.sol | 187 +++++++++--------- 1 file changed, 95 insertions(+), 92 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.sol b/crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.sol index 84349cd5..c4406998 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/ABIGeneric.sol @@ -8,46 +8,49 @@ export { decode }; -import std.{*}; -import std.opcodes.{mstore}; -import std.Generic.{*}; +import * from std; +import {mstore} from std.opcodes; +import * from std.Generic; -// Marker class. Importing this module brings ABIDeriving into scope, which is +// Marker trait. Importing this module brings ABIDeriving into scope, which is // the signal DeriveGeneric looks for to auto-derive a per-type ABIDecode -// instance for local data types. ABIAttribs / ABIEncode are provided generically +// impl for local data types. ABIAttribs / ABIEncode are provided generically // via the default Generic bridges below, but ABIDecode cannot be a default -// instance (its decode returns the head variable `a` via Generic.to, a +// impl (its decode returns the head variable `a` via Generic.to, a // result-position type variable the specializer cannot monomorphize), so a -// concrete per-type instance is emitted instead — exactly as for storage. -forall self. class self : ABIDeriving {} +// concrete per-type impl is emitted instead — exactly as for storage. +trait ABIDeriving {} // ─── ABIAttribs for the primitive sum(f, g) type ───────────────────────── // headSize = 32 (tag word) + max(headSize(f), headSize(g)) -forall f g . f:ABIAttribs, g:ABIAttribs => -instance sum(f, g) : ABIAttribs { +impl ABIAttribs> where f: ABIAttribs, g: ABIAttribs { // Head footprint. A *dynamic* sum occupies a single offset word in the head // (its tag + branch payload live in the tail), exactly like any other // dynamic type. Only a fully *static* sum is laid out inline as // tag + widest branch; there both branches are static, so their headSize is // their full size and 32 + max(...) is the correct inline footprint. - function headSize(ty : Proxy(sum(f, g))) -> word { - let pf : Proxy(f); - let pg : Proxy(g); - match and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg)) { - | false => return 32; - | true => return 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); - } + function headSize(ty: Proxy>) returns (word) { + let pf : Proxy; + let pg : Proxy; + match (and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg))) { +case false { +return 32; +} +case true { +return 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); +} +} } - function isStatic(ty : Proxy(sum(f, g))) -> bool { - let pf : Proxy(f); - let pg : Proxy(g); + function isStatic(ty: Proxy>) returns (bool) { + let pf : Proxy; + let pg : Proxy; return and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg)); } } // ─── ABIEncode for sum(f, g) ───────────────────────────────────────────── -// This is the exact mirror of `ABIDecoder(sum(f, g), reader):ABIDecode` below. +// This is the exact mirror of `ABIDecoder, reader>: ABIDecode` below. // // A STATIC sum is laid out inline in the head: // [offset + 0 .. offset + 31] : tag word (0 = inl, 1 = inr) @@ -61,41 +64,46 @@ instance sum(f, g) : ABIAttribs { // The tail body is itself an inline [tag][branch] sum, so decode follows the // offset and reads it exactly as it reads a static sum. -forall f g . f:ABIAttribs, f:ABIEncode, g:ABIAttribs, g:ABIEncode => -instance sum(f, g) : ABIEncode { - function encodeInto(x : sum(f, g), basePtr : word, offset : word, tail : word) -> word { - let prx : Proxy(sum(f, g)); - match ABIAttribs.isStatic(prx) { - // STATIC sum: inline tag at basePtr+offset, branch at offset + 32. - | true => - match x { - | inl(v) => - mstore(basePtr + offset, 0); +impl ABIEncode> where f: ABIAttribs, f: ABIEncode, g: ABIAttribs, g: ABIEncode { + function encodeInto(x: sum, basePtr: word, offset: word, tail: word) returns (word) { + let prx : Proxy>; + match (ABIAttribs.isStatic(prx)) { +// STATIC sum: inline tag at basePtr+offset, branch at offset + 32. +case true { +match (x) { +case inl(v) { +mstore(basePtr + offset, 0); return ABIEncode.encodeInto(v, basePtr, offset + 32, tail); - | inr(v) => - mstore(basePtr + offset, 1); +} +case inr(v) { +mstore(basePtr + offset, 1); return ABIEncode.encodeInto(v, basePtr, offset + 32, tail); - } +} +} // DYNAMIC sum: head slot holds a relative offset to the sum body, which // is laid out inline in the tail. headSize(prx) is 32 here (the offset // word), so the inline head footprint is computed from the branches: // 32 (tag) + max(headSize(f), headSize(g)). - | false => - let pf : Proxy(f); - let pg : Proxy(g); +} +case false { +let pf : Proxy; + let pg : Proxy; mstore(basePtr + offset, tail - basePtr); let newBase = tail; let innerHead = 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); let newTail = tail + innerHead; - match x { - | inl(v) => - mstore(newBase, 0); + match (x) { +case inl(v) { +mstore(newBase, 0); return ABIEncode.encodeInto(v, newBase, 32, newTail); - | inr(v) => - mstore(newBase, 1); +} +case inr(v) { +mstore(newBase, 1); return ABIEncode.encodeInto(v, newBase, 32, newTail); - } - } +} +} +} +} } } @@ -111,85 +119,80 @@ instance sum(f, g) : ABIEncode { // field, or as a `T[]` element alongside a bare `bytes`/`string` leaf, which // follows its offset the same way. -forall f g reader . - reader : WordReader, - f : ABIAttribs, - g : ABIAttribs, - ABIDecoder(f, reader) : ABIDecode(f), - ABIDecoder(g, reader) : ABIDecode(g) => -instance ABIDecoder(sum(f, g), reader) : ABIDecode(sum(f, g)) { - function decode(ptr : ABIDecoder(sum(f, g), reader), headOffset : word) -> sum(f, g) { - match ptr { - | ABIDecoder(rdr) => - let prx : Proxy(sum(f, g)); +impl ABIDecode, reader>, sum> where reader: WordReader, f: ABIAttribs, g: ABIAttribs, ABIDecoder: ABIDecode, ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder, reader>, headOffset: word) returns (sum) { + match (ptr) { +case ABIDecoder(rdr) { +let prx : Proxy>; // Byte offset (relative to rdr) of this sum's own start. A static sum // is inline at headOffset; a dynamic sum's head slot holds a 32-byte // offset to it, which we follow. We then rebase a decoder onto the // sum start and read [tag][branch] inline — so the tag match (and its // inl/inr) has a single, uniform shape regardless of static/dynamic. let sumStartOff : word; - match ABIAttribs.isStatic(prx) { - | true => sumStartOff = headOffset; - | false => sumStartOff = WordReader.read(WordReader.advance(rdr, headOffset)); - } + match (ABIAttribs.isStatic(prx)) { +case true { +sumStartOff = headOffset; +} +case false { +sumStartOff = WordReader.read(WordReader.advance(rdr, headOffset)); +} +} let sumRdr = WordReader.advance(rdr, sumStartOff); let tag = WordReader.read(sumRdr); - match tag { - | 0 => - let dec_f : ABIDecoder(f, reader) = ABIDecoder(sumRdr); + match (tag) { +case 0 { +let dec_f : ABIDecoder = ABIDecoder(sumRdr); return inl(ABIDecode.decode(dec_f, 32)); - | _ => - let dec_g : ABIDecoder(g, reader) = ABIDecoder(sumRdr); +} +default { +let dec_g : ABIDecoder = ABIDecoder(sumRdr); return inr(ABIDecode.decode(dec_g, 32)); - } - } +} +} +} +} } } // ─── Default bridges: ABIAttribs and ABIEncode via Generic ─────────────── -// Any type 'a' with Generic(rep) inherits its ABI layout from rep. +// Any type `a` with `a: Generic` inherits its ABI layout from `rep`. -forall a rep . a:Generic(rep), rep:ABIAttribs => -default instance a : ABIAttribs { - function headSize(ty : Proxy(a)) -> word { - let prx : Proxy(rep); +default impl ABIAttribs where a: Generic, rep: ABIAttribs { + function headSize(ty: Proxy) returns (word) { + let prx : Proxy; return ABIAttribs.headSize(prx); } - function isStatic(ty : Proxy(a)) -> bool { - let prx : Proxy(rep); + function isStatic(ty: Proxy) returns (bool) { + let prx : Proxy; return ABIAttribs.isStatic(prx); } } -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -default instance a : ABIEncode { - function encodeInto(x : a, basePtr : word, offset : word, tail : word) -> word { +default impl ABIEncode where a: Generic, rep: ABIAttribs, rep: ABIEncode { + function encodeInto(x: a, basePtr: word, offset: word, tail: word) returns (word) { return ABIEncode.encodeInto(Generic.from(x), basePtr, offset, tail); } } // ─── Top-level generic encode function ─────────────────────────────────── -// Serialises any 'a' that has a Generic(rep) instance. -// Only the Generic instance is required — ABIEncode is resolved via the bridge. +// Serialises any `a` that has a `Generic` impl. +// Only the Generic impl is required — ABIEncode is resolved via the bridge. -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -function encode(x : a, basePtr : word, offset : word, tail : word) -> word { +function encode(x: a, basePtr: word, offset: word, tail: word) returns (word) where a: Generic, rep: ABIAttribs, rep: ABIEncode { let xrep : rep = Generic.from(x); return ABIEncode.encodeInto(xrep, basePtr, offset, tail); } // ─── Top-level generic decode function ─────────────────────────────────── -// Deserialises any 'a' that has a Generic(rep) instance. -// Only the Generic instance is required — ABIDecode is resolved via the bridge. - -forall a rep reader . - a : Generic(rep), - reader : WordReader, - ABIDecoder(rep, reader) : ABIDecode(rep) => -function decode(ptr : ABIDecoder(a, reader), headOffset : word) -> a { - match ptr { - | ABIDecoder(rdr) => - let rep_ptr : ABIDecoder(rep, reader) = ABIDecoder(rdr); +// Deserialises any `a` that has a `Generic` impl. +// Only the Generic impl is required — ABIDecode is resolved via the bridge. + +function decode(ptr: ABIDecoder, headOffset: word) returns (a) where a: Generic, reader: WordReader, ABIDecoder: ABIDecode { + match (ptr) { +case ABIDecoder(rdr) { +let rep_ptr : ABIDecoder = ABIDecoder(rdr); return Generic.to(ABIDecode.decode(rep_ptr, headOffset)); - } +} +} } From 25c5969710eb266daab7d815450351a8bb6e40ea Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 058/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std Generic.sol Co-authored-by: Codex --- crates/parser/tests/fixtures/corpus/ok/std/Generic.sol | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/Generic.sol b/crates/parser/tests/fixtures/corpus/ok/std/Generic.sol index ba30049d..46a56996 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/Generic.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/Generic.sol @@ -3,15 +3,14 @@ pragma no-bounded-variable-condition; export { Generic }; -import std.{*}; +import * from std; // MPTC: isomorphism between a user type and its SOP representation. // The representation 'rep' is built from primitive Solcore types: // sum(f, g) with constructors inl / inr // (f, g) pair (product) // () unit -forall a rep. -class a : Generic(rep) { - function from(x : a) -> rep; - function to(x : rep) -> a; +trait Generic { + function from(x: a) returns (rep) ; + function to(x: rep) returns (a) ; } From 8adde94f3e647bef06f07cf3e99a5df9b323cab0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 059/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std StorageGeneric.sol Co-authored-by: Codex --- .../fixtures/corpus/ok/std/StorageGeneric.sol | 237 ++++++++++-------- 1 file changed, 126 insertions(+), 111 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.sol b/crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.sol index 38e855c5..631b665f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/StorageGeneric.sol @@ -7,26 +7,26 @@ export { storeGeneric }; -import std.{*}; -import std.opcodes.{sload, sstore}; -import std.Generic.{*}; +import * from std; +import {sload, sstore} from std.opcodes; +import * from std.Generic; -// Marker class. Importing this module brings StorageDeriving into scope, which +// Marker trait. Importing this module brings StorageDeriving into scope, which // is the signal DeriveGeneric looks for to auto-derive StorageSize / CanStore -// instances for local data types (alongside their Generic instance). It carries +// impls for local data types (alongside their Generic impl). It carries // no methods — its mere visibility enables storage derivation. -forall self. class self : StorageDeriving {} +trait StorageDeriving {} // ─── Storage layout for algebraic data types ───────────────────────────── // // This module is the storage analogue of std.ABIGeneric: it teaches the -// StorageSize / StorageType / CanStore classes how to deal with the +// StorageSize / StorageType / CanStore traits how to deal with the // primitive SOP types that `Generic` maps user data types onto // sum(f, g) with constructors inl / inr (choice / tagged union) // (f, g) pair (product) // () unit -// and then bridges every type with a `Generic(rep)` instance to those -// layouts. `Generic` instances are auto-derived for local data types, so +// and then bridges every type with a `Generic` impl to those +// layouts. `Generic` impls are auto-derived for local data types, so // no per-type boilerplate is needed at the use site. // ─── StorageSize for the primitive sum(f, g) type ──────────────────────── @@ -34,11 +34,10 @@ forall self. class self : StorageDeriving {} // largest branch: size = 1 + max(size(f), size(g)). // (StorageSize for () and (a, b) is already provided by std.) -forall f g . f:StorageSize, g:StorageSize => -instance sum(f, g):StorageSize { - function size(x : Proxy(sum(f, g))) -> word { - let f_sz : word = StorageSize.size(Proxy : Proxy(f)); - let g_sz : word = StorageSize.size(Proxy : Proxy(g)); +impl StorageSize> where f: StorageSize, g: StorageSize { + function size(x: Proxy>) returns (word) { + let f_sz : word = StorageSize.size(@f); + let g_sz : word = StorageSize.size(@g); return 1 + maxWord(f_sz, g_sz); } } @@ -46,11 +45,11 @@ instance sum(f, g):StorageSize { // ─── StorageType for () ────────────────────────────────────────────────── // The unit type occupies no slots, so load/store are no-ops. -instance ():StorageType { - function load(ptr : word) -> () { +impl StorageType<()> { + function load(ptr: word) { return (); } - function store(ptr : word, value : ()) -> () { + function store(ptr: word, value: ()) { return (); } } @@ -59,21 +58,21 @@ instance ():StorageType { // Layout: [ptr .. ptr + size(a) - 1] : a // [ptr + size(a) .. ] : b -forall a b . a:StorageType, a:StorageSize, b:StorageType => -instance (a, b):StorageType { - function load(ptr : word) -> (a, b) { - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); +impl StorageType<(a, b)> where a: StorageType, a: StorageSize, b: StorageType { + function load(ptr: word) returns (a, b) { + let a_sz : word = StorageSize.size(@a); let x : a = StorageType.load(ptr); let y : b = StorageType.load(ptr + a_sz); return (x, y); } - function store(ptr : word, value : (a, b)) -> () { - match value { - | (x, y) => - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); + function store(ptr: word, value: (a, b)) { + match (value) { +case (x, y) { +let a_sz : word = StorageSize.size(@a); StorageType.store(ptr, x); StorageType.store(ptr + a_sz, y); - } +} +} } } @@ -82,96 +81,106 @@ instance (a, b):StorageType { // [ptr] : tag word (0 = inl, 1 = inr) // [ptr + 1 .. ] : encoded branch payload -forall f g . f:StorageType, g:StorageType => -instance sum(f, g):StorageType { - function load(ptr : word) -> sum(f, g) { +impl StorageType> where f: StorageType, g: StorageType { + function load(ptr: word) returns (sum) { let tag : word = sload(ptr); - match tag { - | 0 => - let v : f = StorageType.load(ptr + 1); + match (tag) { +case 0 { +let v : f = StorageType.load(ptr + 1); return inl(v); - | _ => - let v : g = StorageType.load(ptr + 1); +} +default { +let v : g = StorageType.load(ptr + 1); return inr(v); - } +} +} } - function store(ptr : word, value : sum(f, g)) -> () { - match value { - | inl(v) => - sstore(ptr, 0); + function store(ptr: word, value: sum) { + match (value) { +case inl(v) { +sstore(ptr, 0); StorageType.store(ptr + 1, v); - | inr(v) => - sstore(ptr, 1); +} +case inr(v) { +sstore(ptr, 1); StorageType.store(ptr + 1, v); - } +} +} } } // ─── Storage layout via CanStore ───────────────────────────────────────── // -// The structural instances above teach StorageType the fixed-slot encoding of +// The structural impls above teach StorageType the fixed-slot encoding of // the SOP primitives. But StorageType can only describe word-packed types: a -// dynamically-sized field such as memory(bytes) has a StorageSize (one slot, -// Solidity-style) and a CanStore instance (storage(bytes):CanStore(memory(bytes))) -// but NO StorageType instance. Routing an ADT's storage through StorageType +// dynamically-sized field such as memory has a StorageSize (one slot, +// Solidity-style) and a CanStore impl (`storage: CanStore>`) +// but NO StorageType impl. Routing an ADT's storage through StorageType // therefore rejects any data type carrying such a field, even though the field // is perfectly storable. // // So we give CanStore the same structural treatment, decomposing the SOP -// representation and storing each leaf through the leaf's OWN CanStore instance. -// Fixed leaves resolve to storage(word)/storage(uint256)/… (which delegate to -// StorageType); dynamic leaves resolve to storage(bytes)/storage(string). Each +// representation and storing each leaf through the leaf's OWN CanStore impl. +// Fixed leaves resolve to storage/storage/… (which delegate to +// StorageType); dynamic leaves resolve to storage/storage. Each // field occupies StorageSize-many slots, so offsets are computed exactly as in // the StorageType layout. The slot handle for a value of type `t` is uniformly -// `storage(t)`, which is why the dynamic leaves below are mirrored at that +// `storage`, which is why the dynamic leaves below are mirrored at that // handle. // The unit type occupies no slots. -instance storage(()) : CanStore(()) { - function store(r : storage(()), v : ()) -> () { +impl CanStore, ()> { + function store(r: storage<()>, v: ()) { return (); } - function load(r : storage(())) -> () { + function load(r: storage<()>) { return (); } } // Product: store `a` at the base slot, `b` size(a) slots later. -forall a b . storage(a):CanStore(a), a:StorageSize, storage(b):CanStore(b) => -instance storage((a, b)) : CanStore((a, b)) { - function store(r : storage((a, b)), v : (a, b)) -> () { - match v { - | (x, y) => - let base : word = Typedef.rep(r); - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); - CanStore.store(storage(base) : storage(a), x); - CanStore.store(storage(base + a_sz) : storage(b), y); - } - } - function load(r : storage((a, b))) -> (a, b) { +impl CanStore, (a, b)> where storage: CanStore, a: StorageSize, storage: CanStore { + function store(r: storage<(a, b)>, v: (a, b)) { + match (v) { +case (x, y) { +let base : word = Typedef.rep(r); + let a_sz : word = StorageSize.size(@a); + let xSlot : storage = storage(base); + let ySlot : storage = storage(base + a_sz); + CanStore.store(xSlot, x); + CanStore.store(ySlot, y); +} +} + } + function load(r: storage<(a, b)>) returns (a, b) { let base : word = Typedef.rep(r); - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); - let x : a = CanStore.load(storage(base) : storage(a)); - let y : b = CanStore.load(storage(base + a_sz) : storage(b)); + let a_sz : word = StorageSize.size(@a); + let xSlot : storage = storage(base); + let ySlot : storage = storage(base + a_sz); + let x : a = CanStore.load(xSlot); + let y : b = CanStore.load(ySlot); return (x, y); } } // Tagged union: slot 0 holds the tag, the branch payload follows. -forall f g . storage(f):CanStore(f), storage(g):CanStore(g) => -instance storage(sum(f, g)) : CanStore(sum(f, g)) { - function store(r : storage(sum(f, g)), v : sum(f, g)) -> () { +impl CanStore>, sum> where storage: CanStore, storage: CanStore { + function store(r: storage>, v: sum) { let base : word = Typedef.rep(r); - match v { - | inl(x) => - sstore(base, 0); - CanStore.store(storage(base + 1) : storage(f), x); - | inr(y) => - sstore(base, 1); - CanStore.store(storage(base + 1) : storage(g), y); - } - } - function load(r : storage(sum(f, g))) -> sum(f, g) { + match (v) { +case inl(x) { +sstore(base, 0); + let slot : storage = storage(base + 1); + CanStore.store(slot, x); +} +case inr(y) { +sstore(base, 1); + let slot : storage = storage(base + 1); + CanStore.store(slot, y); +} +} + } + function load(r: storage>) returns (sum) { let base : word = Typedef.rep(r); let tag : word = sload(base); // NOTE: the loaded payload is inlined directly into inl(...) / inr(...) @@ -181,63 +190,69 @@ instance storage(sum(f, g)) : CanStore(sum(f, g)) { // of the full sum(f, g), so it emits e.g. `inr(y)` and Yul codegen // rejects it (sum nesting off by one). Inlining matches the working // ABIGeneric.decode pattern, so inl/inr pick up the full sum(f, g). - match tag { - | 0 => - return inl(CanStore.load(storage(base + 1) : storage(f))); - | _ => - return inr(CanStore.load(storage(base + 1) : storage(g))); - } + match (tag) { +case 0 { +let slot : storage = storage(base + 1); +return inl(CanStore.load(slot)); +} +default { +let slot : storage = storage(base + 1); +return inr(CanStore.load(slot)); +} +} } } -// Dynamic leaves at the uniform storage(t) handle. std provides the storage(bytes) -// / storage(string) instances (data lives at keccak(slot)); these mirror them at -// the storage(memory(bytes)) / storage(memory(string)) handle the structural -// decomposition asks for, so a memory(bytes) field inside an ADT is storable. -instance storage(memory(bytes)) : CanStore(memory(bytes)) { - function store(r : storage(memory(bytes)), v : memory(bytes)) -> () { - CanStore.store(storage(Typedef.rep(r)) : storage(bytes), v); +// Dynamic leaves at the uniform storage handle. std provides the storage +// / storage impls (data lives at keccak(slot)); these mirror them at +// the storage> / storage> handle the structural +// decomposition asks for, so a memory field inside an ADT is storable. +impl CanStore>, memory> { + function store(r: storage>, v: memory) { + let slot : storage = storage(Typedef.rep(r)); + CanStore.store(slot, v); } - function load(r : storage(memory(bytes))) -> memory(bytes) { - return CanStore.load(storage(Typedef.rep(r)) : storage(bytes)); + function load(r: storage>) returns (memory) { + let slot : storage = storage(Typedef.rep(r)); + return CanStore.load(slot); } } -instance storage(memory(string)) : CanStore(memory(string)) { - function store(r : storage(memory(string)), v : memory(string)) -> () { - CanStore.store(storage(Typedef.rep(r)) : storage(string), v); +impl CanStore>, memory> { + function store(r: storage>, v: memory) { + let slot : storage = storage(Typedef.rep(r)); + CanStore.store(slot, v); } - function load(r : storage(memory(string))) -> memory(string) { - return CanStore.load(storage(Typedef.rep(r)) : storage(string)); + function load(r: storage>) returns (memory) { + let slot : storage = storage(Typedef.rep(r)); + return CanStore.load(slot); } } // StorageType / CanStore for an ADT are NOT provided here as blanket bridges. // -// A `default instance a:StorageType` would have its `load` return the head +// A `default impl StorageType` would have its `load` return the head // variable `a` via Generic.to — but the specializer cannot monomorphize a -// result-position type variable of a default instance (it is not pinned by the +// result-position type variable of a default impl (it is not pinned by the // arguments), so loads panic. Likewise a tyvar-headed `default a:CanStore(b)` // is non-functional (accepts any storable b), so contract field access cannot // infer the stored type from the slot type. // -// Instead, DeriveGeneric emits a concrete, per-type storage(T):CanStore(T) -// instance (see Solcore.Desugarer.DeriveGeneric) where the data type is fixed -// in the instance head; it delegates to the structural CanStore instances above +// Instead, DeriveGeneric emits a concrete, per-type +// `storage: CanStore` impl (see Solcore.Desugarer.DeriveGeneric) where the +// data type is fixed in the impl head; it delegates to the structural CanStore impls above // via the type's Generic representation. StorageSize is likewise derived // per-type for the field layout. // ─── Top-level helpers ─────────────────────────────────────────────────── // Convenience wrappers mirroring std.ABIGeneric's encode / decode: persist or -// read back any 'a' that has a Generic(rep) instance at a raw storage slot. +// read back any `a` that has a `Generic` impl at a raw storage slot. -forall a rep . a:Generic(rep), rep:StorageType => -function storeGeneric(slot : word, value : a) -> () { +function storeGeneric(slot: word, value: a) where a: Generic, rep: StorageType { StorageType.store(slot, Generic.from(value)); } -forall a rep . a:Generic(rep), rep:StorageType => -function loadGeneric(slot : word) -> a { +function loadGeneric(slot: word) returns (a) where a: Generic, rep: StorageType { let r : rep = StorageType.load(slot); return Generic.to(r); } From 9db60d63f246c7e69dc5f93f7364ac8e44c9aeaa Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 060/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std dispatch.sol Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/dispatch.sol | 258 ++++++++---------- 1 file changed, 118 insertions(+), 140 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/dispatch.sol b/crates/parser/tests/fixtures/corpus/ok/std/dispatch.sol index ef9672a3..408c1415 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/dispatch.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/dispatch.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.opcodes.{callvalue, calldatasize, calldataload, shr, return_}; -import std.Generic.{*}; +import * from std; +import {callvalue, calldatasize, calldataload, shr, return_} from std.opcodes; +import * from std.Generic; export { ABIString, @@ -29,38 +29,36 @@ pragma no-bounded-variable-condition ; // A contract contains a tuple of methods and a single fallback // TODO: implement receive() -data Contract(methods, fb) = Contract(methods,fb); +enum Contract { Contract(methods, fb) } // A method contains an implementation (fn) as well as it's name and type signature -data Method(name, payability, args, rets, fn) = Method(Proxy(name), Proxy(payability), Proxy(args), Proxy(rets), fn); +enum Method { Method(Proxy, Proxy, Proxy, Proxy, fn) } // Contains the implementation for the fallback (fn) as well as it's type signature -data Fallback(payability, args, rets, fn) = Fallback(Proxy(payability), Proxy(args), Proxy(rets), fn); +enum Fallback { Fallback(Proxy, Proxy, Proxy, fn) } // --- Method Selectors --- -forall ty . class ty:ABIString { // deprecated - function append(head : word, tail : word, prx : Proxy(ty)) -> word; +trait ABIString { // deprecated + function append(head: word, tail: word, prx: Proxy) returns (word) ; } -forall t.class t:SigString { function sigStr(x:Proxy(t)) -> string; } +trait SigString { function sigStr(x: Proxy) returns (string) ; } -forall t. t: SigString => -function sigStr(p:Proxy(t)) -> string { SigString.sigStr(p) } +function sigStr(p: Proxy) returns (string) where t: SigString { SigString.sigStr(p) } -instance uint256 : SigString { function sigStr(x:Proxy(uint256)) -> string { "uint256" }} -instance bytes32 : SigString { function sigStr(x:Proxy(bytes32)) -> string { "bytes32" }} -instance bytes4 : SigString { function sigStr(x:Proxy(bytes4)) -> string { "bytes4" }} -instance address : SigString { function sigStr(x:Proxy(address)) -> string { "address" }} -instance bool : SigString { function sigStr(x:Proxy(bool)) -> string { "bool" }} -instance memory(string) : SigString { function sigStr(x:Proxy(memory(string))) -> string { "string" }} -instance memory(bytes) : SigString { function sigStr(x:Proxy(memory(bytes))) -> string { "bytes" }} -instance ():SigString { function sigStr(x:Proxy(())) -> string { "" } } +impl SigString { function sigStr(x: Proxy) returns (string) { "uint256" }} +impl SigString { function sigStr(x: Proxy) returns (string) { "bytes32" }} +impl SigString { function sigStr(x: Proxy) returns (string) { "bytes4" }} +impl SigString
{ function sigStr(x: Proxy
) returns (string) { "address" }} +impl SigString { function sigStr(x: Proxy) returns (string) { "bool" }} +impl SigString> { function sigStr(x: Proxy>) returns (string) { "string" }} +impl SigString> { function sigStr(x: Proxy>) returns (string) { "bytes" }} +impl SigString<()> { function sigStr(x: Proxy<()>) returns (string) { "" } } -forall a b. a:SigString, b: SigString => -instance (a,b):SigString { - function sigStr(x:Proxy((a,b))) -> string { - SigString.sigStr( Proxy:Proxy(a) ) + "," + SigString.sigStr( Proxy:Proxy(b) ) +impl SigString<(a, b)> where a: SigString, b: SigString { + function sigStr(x: Proxy<(a, b)>) returns (string) { + SigString.sigStr( @a ) + "," + SigString.sigStr( @b ) } } @@ -71,10 +69,9 @@ instance (a,b):SigString { // `sum(uint256,uint256)` and `(uint256,uint256)` hash to distinct selectors. It // makes ADT-typed parameters produce a deterministic selector; refine here if a // specific on-the-wire sum convention is needed. -forall f g. f:SigString, g: SigString => -instance sum(f,g):SigString { - function sigStr(x:Proxy(sum(f,g))) -> string { - "sum(" + SigString.sigStr( Proxy:Proxy(f) ) + "," + SigString.sigStr( Proxy:Proxy(g) ) + ")" +impl SigString> where f: SigString, g: SigString { + function sigStr(x: Proxy>) returns (string) { + "sum(" + SigString.sigStr( @f ) + "," + SigString.sigStr( @g ) + ")" } } @@ -82,47 +79,40 @@ instance sum(f,g):SigString { // The element carries its own (structural, for ADTs) signature, so an array of a // sum type reads `sum(l,r)[]`. Location is transparent to the ABI, so this keys // on the calldata form the dispatch decodes from. -forall t. t:SigString => -instance calldata(array(t)):SigString { - function sigStr(x:Proxy(calldata(array(t)))) -> string { - SigString.sigStr( Proxy:Proxy(t) ) + "[]" +impl SigString>> where t: SigString { + function sigStr(x: Proxy>>) returns (string) { + SigString.sigStr( @t ) + "[]" } } // Any data type inherits its ABI signature from its Generic representation, the // same way ABIAttribs / ABIEncode bridge through Generic in std.ABIGeneric. This // lets the dispatch take ADT-typed parameters (e.g. a Signature) without a -// hand-written SigString instance per type. -forall a rep. a:Generic(rep), rep:SigString => -default instance a:SigString { - function sigStr(x:Proxy(a)) -> string { - SigString.sigStr( Proxy:Proxy(rep) ) +// hand-written SigString impl per type. +default impl SigString where a: Generic, rep: SigString { + function sigStr(x: Proxy) returns (string) { + SigString.sigStr( @rep ) } } -forall name f args rets payability. - f: invokable(args,rets), name:SigString, args:SigString, rets:SigString => -instance Method(name,payability,args,rets,f):SigString { - function sigStr(x:Proxy(Method(name,payability,args,rets,f))) -> string { - sigStr(Proxy:Proxy(name)) + "(" + sigStr(Proxy:Proxy(args)) + ")" +impl SigString> where f: invokable, name: SigString, args: SigString, rets: SigString { + function sigStr(x: Proxy>) returns (string) { + sigStr(@name) + "(" + sigStr(@args) + ")" } } -forall ty . class ty:Selector { - function compute(prx : Proxy(ty)) -> bytes4; +trait Selector { + function compute(prx: Proxy) returns (bytes4) ; } // Computes the selector hash for a given method -// this is a class with a single instance since it made some of the downstream definitions a bit cleaner to define +// This trait has a single impl, which keeps downstream definitions simpler. // NOTE: for efficiency purposes this leaves dirty data past the end of the free memory pointer -forall name payability args rets fn - . name:SigString - , args:SigString -=> instance Method(name,payability,args,rets,fn):Selector { - function compute(prx : Proxy(Method(name,payability,args,rets,fn))) -> bytes4 { +impl Selector> where name: SigString, args: SigString { + function compute(prx: Proxy>) returns (bytes4) { // let hash : word = keccakLit(sigStr(prx)); - let hash = keccakLit(sigStr(Proxy:Proxy(name)) + "(" + sigStr(Proxy:Proxy(args)) + ")"); + let hash = keccakLit(sigStr(@name) + "(" + sigStr(@args) + ")"); return bytes4(shr(224, hash)); } } @@ -130,81 +120,63 @@ forall name payability args rets fn // --- Method Execution --- // Describes how to execute a given method / fallback -forall ty . class ty:ExecMethod { - function exec(x: ty) -> (); +trait ExecMethod { + function exec(x: ty) ; } // If fn matches the provided args/ret types, then we can execute any non-payable method -forall name args rets fn - . fn:invokable(args,rets) - , args:ABIAttribs - , rets:ABIAttribs - , ABIDecoder(args,CalldataWordReader):ABIDecode(args) - , rets:ABIEncode -=> instance Method(name,NonPayable,args,rets,fn):ExecMethod { - function exec(m : Method(name,NonPayable,args,rets,fn)) -> () { - match m { - | Method(pnm,ppayability,pargs,prets,fn) => - // non-payable methods must reject any callvalue before running - MethodLevelCallvalueCheck.checkCallvalue(Proxy : Proxy(NonPayable)); +impl ExecMethod> where fn: invokable, args: ABIAttribs, rets: ABIAttribs, ABIDecoder: ABIDecode, rets: ABIEncode { + function exec(m: Method) { + match (m) { +case Method(pnm,ppayability,pargs,prets,fn) { +// non-payable methods must reject any callvalue before running + MethodLevelCallvalueCheck.checkCallvalue(@NonPayable); do_exec(pargs, prets, fn); - } +} +} } } // If fn matches the provided args/ret types, then we can execute any payable method // payable methods skip the callvalue check entirely -forall name args rets fn - . fn:invokable(args,rets) - , args:ABIAttribs - , rets:ABIAttribs - , ABIDecoder(args,CalldataWordReader):ABIDecode(args) - , rets:ABIEncode -=> instance Method(name,Payable,args,rets,fn):ExecMethod { - function exec(m : Method(name,Payable,args,rets,fn)) -> () { - match m { - | Method(pnm,ppayability,pargs,prets,fn) => - do_exec(pargs, prets, fn); - } +impl ExecMethod> where fn: invokable, args: ABIAttribs, rets: ABIAttribs, ABIDecoder: ABIDecode, rets: ABIEncode { + function exec(m: Method) { + match (m) { +case Method(pnm,ppayability,pargs,prets,fn) { +do_exec(pargs, prets, fn); +} +} } } -// Fallbacks have no ABI-decoded inputs or outputs, so the instance is +// Fallbacks have no ABI-decoded inputs or outputs, so the impl is // specialised to args = rets = () and bypasses the calldata length check // and ABI decode/encode entirely. -forall payability fn - . fn:invokable((),()) - , payability:MethodLevelCallvalueCheck -=> instance Fallback(payability,(),(),fn):ExecMethod { - function exec(fb : Fallback(payability,(),(),fn)) -> () { - match fb { - | Fallback(ppayability, pargs, prets, fn) => - MethodLevelCallvalueCheck.checkCallvalue(Proxy : Proxy(payability)); +impl ExecMethod> where fn: invokable<(), ()>, payability: MethodLevelCallvalueCheck { + function exec(fb: Fallback) { + match (fb) { +case Fallback(ppayability, pargs, prets, fn) { +MethodLevelCallvalueCheck.checkCallvalue(@payability); fn(()); assembly { stop() } - } +} +} } } -forall args rets fn - . fn:invokable(args,rets) - , args:ABIAttribs - , rets:ABIAttribs - , ABIDecoder(args,CalldataWordReader):ABIDecode(args) - , rets:ABIEncode -=> function do_exec(pargs : Proxy(args), prets : Proxy(rets), fn : fn) -> () { +function do_exec(pargs: Proxy, prets: Proxy, fn: fn) where fn: invokable, args: ABIAttribs, rets: ABIAttribs, ABIDecoder: ABIDecode, rets: ABIEncode { // check we have enough calldata for the head of args require(calldatasize() >= (ABIAttribs.headSize(pargs) + 4), Error(0x08638556)); // ABIInputTruncated() // TODO: calldatasize checks for dynamic types // abi decode args from calldata - let ptr : calldata(bytes) = calldata(4); + let ptr : calldata = calldata(4); // TODO: this needs entirely too many type annotations - let args : args = abi_decode(ptr, pargs, Proxy : Proxy(CalldataWordReader)); + let args : args = abi_decode(ptr, pargs, @CalldataWordReader); // call fn with args // TODO: why are type annotations needed here? @@ -218,44 +190,50 @@ forall args rets fn // --- Method Dispatch --- // For a given tuple of methods this executes the method specified by the first four bytes of calldata -forall ty . class ty:RunDispatch { - function go(methods : ty) -> (); +trait RunDispatch { + function go(methods: ty) ; } // We can dispatch to a single executable method with a known selector -forall name payability args rets fn - . Method(name,payability,args,rets,fn):ExecMethod - , Method(name,payability,args,rets,fn):Selector -=> instance Method(name,payability,args,rets,fn):RunDispatch { - function go(method : Method(name,payability,args,rets,fn)) -> () { - match selector_matches(Proxy : Proxy(Method(name,payability,args,rets,fn))) { - | true => ExecMethod.exec(method); - | false => return (); - } +impl RunDispatch> where Method: ExecMethod, Method: Selector { + function go(method: Method) { + match (selector_matches(@Method)) { +case true { +ExecMethod.exec(method); +} +case false { +return (); +} +} } } // Base case: a contract with no methods has nothing to dispatch to -instance ():RunDispatch { - function go(methods : ()) -> () { } -} - -// Recursive instance -forall n m . n:ExecMethod, n:Selector, m:RunDispatch => instance (n,m):RunDispatch { - function go(methods : (n,m)) -> () { - match methods { - | (method_n, rest) => - match selector_matches(Proxy : Proxy(n)) { - | true => ExecMethod.exec(method_n); - | false => RunDispatch.go(rest); - } - } +impl RunDispatch<()> { + function go(methods: ()) { } +} + +// Recursive impl. +impl RunDispatch<(n, m)> where n: ExecMethod, n: Selector, m: RunDispatch { + function go(methods: (n, m)) { + match (methods) { +case (method_n, rest) { +match (selector_matches(@n)) { +case true { +ExecMethod.exec(method_n); +} +case false { +RunDispatch.go(rest); +} +} +} +} } } // TODO: we only wanna do the calldataload once // Given evidence of a type with a known selector, we can check if it matches the selector in the first four bytes of calldata -forall ty . ty:Selector => function selector_matches(prx : Proxy(ty)) -> bool { +function selector_matches(prx: Proxy) returns (bool) where ty: Selector { let candidate = Typedef.rep(Selector.compute(prx)); let selector = shr(224, calldataload(0)); return selector == candidate; @@ -263,20 +241,20 @@ forall ty . ty:Selector => function selector_matches(prx : Proxy(ty)) -> bool { // --- Callvalue Checks --- -data Payable; -data NonPayable; +enum Payable {} +enum NonPayable {} -forall ty . class ty:MethodLevelCallvalueCheck { - function checkCallvalue(pty : Proxy(ty)) -> (); +trait MethodLevelCallvalueCheck { + function checkCallvalue(pty: Proxy) ; } // no callvalue check for Payable methods -instance Payable:MethodLevelCallvalueCheck { - function checkCallvalue(prx : Proxy(Payable)) -> () { } +impl MethodLevelCallvalueCheck { + function checkCallvalue(prx: Proxy) { } } // NonPayable methods revert if passed value -instance NonPayable:MethodLevelCallvalueCheck { - function checkCallvalue(prx : Proxy(NonPayable)) -> () { +impl MethodLevelCallvalueCheck { + function checkCallvalue(prx: Proxy) { let NonPayableReceivedValue = Error(0xb5988ea3); require(callvalue() == 0, NonPayableReceivedValue); } @@ -285,17 +263,16 @@ instance NonPayable:MethodLevelCallvalueCheck { // --- Contract Execution --- // Describes how to execute a given contract -forall c . class c:RunContract { - function exec(v : c) -> (); +trait RunContract { + function exec(v: c) ; } // If we have a dispatch for the contracts methods, and we know how to execute it's fallback, then we can define an entrypoint -forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(methods, fb):RunContract { - function exec(c : Contract(methods, fb)) -> () { - match c { - | Contract(ms, fb) => - - // TODO: if all methods are non payable then we should life the callvalue check here +impl RunContract> where methods: RunDispatch, fb: ExecMethod { + function exec(c: Contract) { + match (c) { +case Contract(ms, fb) { +// TODO: if all methods are non payable then we should life the callvalue check here // set free memory pointer to the output of memoryguard // https://docs.soliditylang.org/en/v0.8.30/yul.html#memoryguard @@ -311,12 +288,13 @@ forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(meth // fallthrough to fallback -- this will be reached upon short input // or no matching selector ExecMethod.exec(fb); - } +} +} } } // This is the default fallback used if none is defined. -function fallback_default_implementation() -> () { +function fallback_default_implementation() { let NoSelectorMatchedWithoutFallback = Error(0x4924aef0); revertWithError(NoSelectorMatchedWithoutFallback); } From 2e89d30a125b7a3115d145d69e5a528508dcc54f Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 061/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std eip712.sol Co-authored-by: Codex --- .../parser/tests/fixtures/corpus/ok/std/eip712.sol | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/eip712.sol b/crates/parser/tests/fixtures/corpus/ok/std/eip712.sol index 9e6f687b..7218ef29 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/eip712.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/eip712.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.opcodes.{mstore, keccak256, shl}; +import * from std; +import {mstore, keccak256, shl} from std.opcodes; export { eip712Digest, @@ -25,12 +25,7 @@ export { // keccak256 of the (dynamic) name / version strings — typically compile-time // constants produced with `keccakLit`. `chainId` / `verifyingContract` are // encoded as their left-padded 32-byte words. -function eip712DomainSeparator( - nameHash: bytes32, - versionHash: bytes32, - chainId: uint256, - verifyingContract: address -) -> bytes32 { +function eip712DomainSeparator(nameHash: bytes32, versionHash: bytes32, chainId: uint256, verifyingContract: address) returns (bytes32) { let typeHash = keccakLit("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Lay the five 32-byte words out contiguously and hash them. We borrow the // area above the free-memory pointer as scratch (as `ecrecover` does): the @@ -48,7 +43,7 @@ function eip712DomainSeparator( // Binds a domain separator to a message's struct hash, yielding the final // EIP-712 digest: keccak256(0x19 0x01 ‖ domainSeparator ‖ structHash). The // two-byte 0x1901 prefix occupies the leading bytes of the first word. -function eip712Digest(domainSeparator: bytes32, structHash: bytes32) -> bytes32 { +function eip712Digest(domainSeparator: bytes32, structHash: bytes32) returns (bytes32) { let ptr = get_free_memory(); mstore(ptr, shl(240, 0x1901)); // 0x1901 in the leading two bytes mstore(ptr + 2, Typedef.rep(domainSeparator)); From 818ba870e527ed5ff4b6806a67c7e4003a5afc25 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 062/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std eip7951.sol Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/eip7951.sol | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/eip7951.sol b/crates/parser/tests/fixtures/corpus/ok/std/eip7951.sol index 16f2ca50..a5ae3fe4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/eip7951.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/eip7951.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.opcodes.{mstore, mload, gas, staticcall}; +import * from std; +import {mstore, mload, gas, staticcall} from std.opcodes; export { p256verify }; @@ -9,7 +9,7 @@ export { p256verify }; // returns a 32-byte word equal to 1 on a valid signature and empty output on an // invalid one; we pre-clear the [0, 32) scratch slot so the failing case reads // back as 0. -function p256verify(hash: bytes32, r: bytes32, s: bytes32, qx: bytes32, qy: bytes32) -> bool { +function p256verify(hash: bytes32, r: bytes32, s: bytes32, qx: bytes32, qy: bytes32) returns (bool) { let hash_ = Typedef.rep(hash); let r_ = Typedef.rep(r); let s_ = Typedef.rep(s); @@ -27,8 +27,12 @@ function p256verify(hash: bytes32, r: bytes32, s: bytes32, qx: bytes32, qy: byte let ret = staticcall(gas(), 0x100, ptr, 160, 0, 32); require(ret != 0, Error(0x1fb6bf04)); // P256VerifyCallFailed() // NOTE: we are doing the inverse check here for safety, so not using tobool() - match mload(0) { - | 1 => return true; - | _ => return false; - } + match (mload(0)) { +case 1 { +return true; +} +default { +return false; +} +} } From 450b51093039f9a6beaeb282cae957f74fa5ea00 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 063/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std opcodes.sol Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/opcodes.sol | 162 +++++++++--------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/opcodes.sol b/crates/parser/tests/fixtures/corpus/ok/std/opcodes.sol index 991d18eb..a8193fb5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/opcodes.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/opcodes.sol @@ -84,13 +84,13 @@ export { selfdestruct }; -function stop() -> () { +function stop() { assembly { stop() } } -function add(a: word, b: word) -> word { +function add(a: word, b: word) returns (word) { let res; assembly { res := add(a, b) @@ -98,7 +98,7 @@ function add(a: word, b: word) -> word { return res; } -function mul(a: word, b: word) -> word { +function mul(a: word, b: word) returns (word) { let res; assembly { res := mul(a, b) @@ -106,7 +106,7 @@ function mul(a: word, b: word) -> word { return res; } -function sub(a: word, b: word) -> word { +function sub(a: word, b: word) returns (word) { let res; assembly { res := sub(a, b) @@ -114,7 +114,7 @@ function sub(a: word, b: word) -> word { return res; } -function div(a: word, b: word) -> word { +function div(a: word, b: word) returns (word) { let res; assembly { res := div(a, b) @@ -122,7 +122,7 @@ function div(a: word, b: word) -> word { return res; } -function sdiv(a: word, b: word) -> word { +function sdiv(a: word, b: word) returns (word) { let res; assembly { res := sdiv(a, b) @@ -130,7 +130,7 @@ function sdiv(a: word, b: word) -> word { return res; } -function mod(a: word, b: word) -> word { +function mod(a: word, b: word) returns (word) { let res; assembly { res := mod(a, b) @@ -138,7 +138,7 @@ function mod(a: word, b: word) -> word { return res; } -function smod(a: word, b: word) -> word { +function smod(a: word, b: word) returns (word) { let res; assembly { res := smod(a, b) @@ -146,7 +146,7 @@ function smod(a: word, b: word) -> word { return res; } -function addmod(a: word, b: word, c: word) -> word { +function addmod(a: word, b: word, c: word) returns (word) { let res; assembly { res := addmod(a, b, c) @@ -154,7 +154,7 @@ function addmod(a: word, b: word, c: word) -> word { return res; } -function mulmod(a: word, b: word, c: word) -> word { +function mulmod(a: word, b: word, c: word) returns (word) { let res; assembly { res := mulmod(a, b, c) @@ -162,7 +162,7 @@ function mulmod(a: word, b: word, c: word) -> word { return res; } -function exp(a: word, b: word) -> word { +function exp(a: word, b: word) returns (word) { let res; assembly { res := exp(a, b) @@ -170,7 +170,7 @@ function exp(a: word, b: word) -> word { return res; } -function signextend(a: word, b: word) -> word { +function signextend(a: word, b: word) returns (word) { let res; assembly { res := signextend(a, b) @@ -178,7 +178,7 @@ function signextend(a: word, b: word) -> word { return res; } -function lt(a: word, b: word) -> word { +function lt(a: word, b: word) returns (word) { let res; assembly { res := lt(a, b) @@ -186,7 +186,7 @@ function lt(a: word, b: word) -> word { return res; } -function gt(a: word, b: word) -> word { +function gt(a: word, b: word) returns (word) { let res; assembly { res := gt(a, b) @@ -194,7 +194,7 @@ function gt(a: word, b: word) -> word { return res; } -function slt(a: word, b: word) -> word { +function slt(a: word, b: word) returns (word) { let res; assembly { res := slt(a, b) @@ -202,7 +202,7 @@ function slt(a: word, b: word) -> word { return res; } -function sgt(a: word, b: word) -> word { +function sgt(a: word, b: word) returns (word) { let res; assembly { res := sgt(a, b) @@ -210,7 +210,7 @@ function sgt(a: word, b: word) -> word { return res; } -function eq(a: word, b: word) -> word { +function eq(a: word, b: word) returns (word) { let res; assembly { res := eq(a, b) @@ -218,7 +218,7 @@ function eq(a: word, b: word) -> word { return res; } -function iszero(a: word) -> word { +function iszero(a: word) returns (word) { let res; assembly { res := iszero(a) @@ -226,7 +226,7 @@ function iszero(a: word) -> word { return res; } -function and(a: word, b: word) -> word { +function and(a: word, b: word) returns (word) { let res; assembly { res := and(a, b) @@ -234,7 +234,7 @@ function and(a: word, b: word) -> word { return res; } -function or(a: word, b: word) -> word { +function or(a: word, b: word) returns (word) { let res; assembly { res := or(a, b) @@ -242,7 +242,7 @@ function or(a: word, b: word) -> word { return res; } -function xor(a: word, b: word) -> word { +function xor(a: word, b: word) returns (word) { let res; assembly { res := xor(a, b) @@ -250,7 +250,7 @@ function xor(a: word, b: word) -> word { return res; } -function not(a: word) -> word { +function not(a: word) returns (word) { let res; assembly { res := not(a) @@ -258,7 +258,7 @@ function not(a: word) -> word { return res; } -function byte(a: word, b: word) -> word { +function byte(a: word, b: word) returns (word) { let res; assembly { res := byte(a, b) @@ -266,7 +266,7 @@ function byte(a: word, b: word) -> word { return res; } -function shl(a: word, b: word) -> word { +function shl(a: word, b: word) returns (word) { let res; assembly { res := shl(a, b) @@ -274,7 +274,7 @@ function shl(a: word, b: word) -> word { return res; } -function shr(a: word, b: word) -> word { +function shr(a: word, b: word) returns (word) { let res; assembly { res := shr(a, b) @@ -282,7 +282,7 @@ function shr(a: word, b: word) -> word { return res; } -function sar(a: word, b: word) -> word { +function sar(a: word, b: word) returns (word) { let res; assembly { res := sar(a, b) @@ -290,7 +290,7 @@ function sar(a: word, b: word) -> word { return res; } -function clz(a: word) -> word { +function clz(a: word) returns (word) { let res; assembly { res := clz(a) @@ -298,7 +298,7 @@ function clz(a: word) -> word { return res; } -function keccak256(a: word, b: word) -> word { +function keccak256(a: word, b: word) returns (word) { let res; assembly { res := keccak256(a, b) @@ -306,7 +306,7 @@ function keccak256(a: word, b: word) -> word { return res; } -function address() -> word { +function address() returns (word) { let res; assembly { res := address() @@ -314,7 +314,7 @@ function address() -> word { return res; } -function balance(a: word) -> word { +function balance(a: word) returns (word) { let res; assembly { res := balance(a) @@ -322,7 +322,7 @@ function balance(a: word) -> word { return res; } -function origin() -> word { +function origin() returns (word) { let res; assembly { res := origin() @@ -330,7 +330,7 @@ function origin() -> word { return res; } -function caller() -> word { +function caller() returns (word) { let res; assembly { res := caller() @@ -338,7 +338,7 @@ function caller() -> word { return res; } -function callvalue() -> word { +function callvalue() returns (word) { let res; assembly { res := callvalue() @@ -346,7 +346,7 @@ function callvalue() -> word { return res; } -function calldataload(a: word) -> word { +function calldataload(a: word) returns (word) { let res; assembly { res := calldataload(a) @@ -354,7 +354,7 @@ function calldataload(a: word) -> word { return res; } -function calldatasize() -> word { +function calldatasize() returns (word) { let res; assembly { res := calldatasize() @@ -362,13 +362,13 @@ function calldatasize() -> word { return res; } -function calldatacopy(a: word, b: word, c: word) -> () { +function calldatacopy(a: word, b: word, c: word) { assembly { calldatacopy(a, b, c) } } -function codesize() -> word { +function codesize() returns (word) { let res; assembly { res := codesize() @@ -376,13 +376,13 @@ function codesize() -> word { return res; } -function codecopy(a: word, b: word, c: word) -> () { +function codecopy(a: word, b: word, c: word) { assembly { codecopy(a, b, c) } } -function gasprice() -> word { +function gasprice() returns (word) { let res; assembly { res := gasprice() @@ -390,7 +390,7 @@ function gasprice() -> word { return res; } -function extcodesize(a: word) -> word { +function extcodesize(a: word) returns (word) { let res; assembly { res := extcodesize(a) @@ -398,13 +398,13 @@ function extcodesize(a: word) -> word { return res; } -function extcodecopy(a: word, b: word, c: word, d: word) -> () { +function extcodecopy(a: word, b: word, c: word, d: word) { assembly { extcodecopy(a, b, c, d) } } -function returndatasize() -> word { +function returndatasize() returns (word) { let res; assembly { res := returndatasize() @@ -412,13 +412,13 @@ function returndatasize() -> word { return res; } -function returndatacopy(a: word, b: word, c: word) -> () { +function returndatacopy(a: word, b: word, c: word) { assembly { returndatacopy(a, b, c) } } -function extcodehash(a: word) -> word { +function extcodehash(a: word) returns (word) { let res; assembly { res := extcodehash(a) @@ -426,7 +426,7 @@ function extcodehash(a: word) -> word { return res; } -function blockhash(a: word) -> word { +function blockhash(a: word) returns (word) { let res; assembly { res := blockhash(a) @@ -434,7 +434,7 @@ function blockhash(a: word) -> word { return res; } -function coinbase() -> word { +function coinbase() returns (word) { let res; assembly { res := coinbase() @@ -442,7 +442,7 @@ function coinbase() -> word { return res; } -function timestamp() -> word { +function timestamp() returns (word) { let res; assembly { res := timestamp() @@ -450,7 +450,7 @@ function timestamp() -> word { return res; } -function number() -> word { +function number() returns (word) { let res; assembly { res := number() @@ -458,7 +458,7 @@ function number() -> word { return res; } -function prevrandao() -> word { +function prevrandao() returns (word) { let res; assembly { res := prevrandao() @@ -466,7 +466,7 @@ function prevrandao() -> word { return res; } -function gaslimit() -> word { +function gaslimit() returns (word) { let res; assembly { res := gaslimit() @@ -474,7 +474,7 @@ function gaslimit() -> word { return res; } -function chainid() -> word { +function chainid() returns (word) { let res; assembly { res := chainid() @@ -482,7 +482,7 @@ function chainid() -> word { return res; } -function selfbalance() -> word { +function selfbalance() returns (word) { let res; assembly { res := selfbalance() @@ -490,7 +490,7 @@ function selfbalance() -> word { return res; } -function basefee() -> word { +function basefee() returns (word) { let res; assembly { res := basefee() @@ -498,7 +498,7 @@ function basefee() -> word { return res; } -function blobhash(a: word) -> word { +function blobhash(a: word) returns (word) { let res; assembly { res := blobhash(a) @@ -506,7 +506,7 @@ function blobhash(a: word) -> word { return res; } -function blobbasefee() -> word { +function blobbasefee() returns (word) { let res; assembly { res := blobbasefee() @@ -514,13 +514,13 @@ function blobbasefee() -> word { return res; } -function pop(a: word) -> () { +function pop(a: word) { assembly { pop(a) } } -function mload(a: word) -> word { +function mload(a: word) returns (word) { let res; assembly { res := mload(a) @@ -528,19 +528,19 @@ function mload(a: word) -> word { return res; } -function mstore(a: word, b: word) -> () { +function mstore(a: word, b: word) { assembly { mstore(a, b) } } -function mstore8(a: word, b: word) -> () { +function mstore8(a: word, b: word) { assembly { mstore8(a, b) } } -function sload(a: word) -> word { +function sload(a: word) returns (word) { let res; assembly { res := sload(a) @@ -548,13 +548,13 @@ function sload(a: word) -> word { return res; } -function sstore(a: word, b: word) -> () { +function sstore(a: word, b: word) { assembly { sstore(a, b) } } -function msize() -> word { +function msize() returns (word) { let res; assembly { res := msize() @@ -562,7 +562,7 @@ function msize() -> word { return res; } -function gas() -> word { +function gas() returns (word) { let res; assembly { res := gas() @@ -570,7 +570,7 @@ function gas() -> word { return res; } -function tload(a: word) -> word { +function tload(a: word) returns (word) { let res; assembly { res := tload(a) @@ -578,49 +578,49 @@ function tload(a: word) -> word { return res; } -function tstore(a: word, b: word) -> () { +function tstore(a: word, b: word) { assembly { tstore(a, b) } } -function mcopy(a: word, b: word, c: word) -> () { +function mcopy(a: word, b: word, c: word) { assembly { mcopy(a, b, c) } } -function log0(a: word, b: word) -> () { +function log0(a: word, b: word) { assembly { log0(a, b) } } -function log1(a: word, b: word, c: word) -> () { +function log1(a: word, b: word, c: word) { assembly { log1(a, b, c) } } -function log2(a: word, b: word, c: word, d: word) -> () { +function log2(a: word, b: word, c: word, d: word) { assembly { log2(a, b, c, d) } } -function log3(a: word, b: word, c: word, d: word, e: word) -> () { +function log3(a: word, b: word, c: word, d: word, e: word) { assembly { log3(a, b, c, d, e) } } -function log4(a: word, b: word, c: word, d: word, e: word, f: word) -> () { +function log4(a: word, b: word, c: word, d: word, e: word, f: word) { assembly { log4(a, b, c, d, e, f) } } -function create(a: word, b: word, c: word) -> word { +function create(a: word, b: word, c: word) returns (word) { let res; assembly { res := create(a, b, c) @@ -628,7 +628,7 @@ function create(a: word, b: word, c: word) -> word { return res; } -function call(a: word, b: word, c: word, d: word, e: word, f: word, g: word) -> word { +function call(a: word, b: word, c: word, d: word, e: word, f: word, g: word) returns (word) { let res; assembly { res := call(a, b, c, d, e, f, g) @@ -636,7 +636,7 @@ function call(a: word, b: word, c: word, d: word, e: word, f: word, g: word) -> return res; } -function callcode(a: word, b: word, c: word, d: word, e: word, f: word, g: word) -> word { +function callcode(a: word, b: word, c: word, d: word, e: word, f: word, g: word) returns (word) { let res; assembly { res := callcode(a, b, c, d, e, f, g) @@ -644,13 +644,13 @@ function callcode(a: word, b: word, c: word, d: word, e: word, f: word, g: word) return res; } -function return_(a: word, b: word) -> () { +function return_(a: word, b: word) { assembly { return(a, b) } } -function delegatecall(a: word, b: word, c: word, d: word, e: word, f: word) -> word { +function delegatecall(a: word, b: word, c: word, d: word, e: word, f: word) returns (word) { let res; assembly { res := delegatecall(a, b, c, d, e, f) @@ -658,7 +658,7 @@ function delegatecall(a: word, b: word, c: word, d: word, e: word, f: word) -> w return res; } -function create2(a: word, b: word, c: word, d: word) -> word { +function create2(a: word, b: word, c: word, d: word) returns (word) { let res; assembly { res := create2(a, b, c, d) @@ -666,7 +666,7 @@ function create2(a: word, b: word, c: word, d: word) -> word { return res; } -function staticcall(a: word, b: word, c: word, d: word, e: word, f: word) -> word { +function staticcall(a: word, b: word, c: word, d: word, e: word, f: word) returns (word) { let res; assembly { res := staticcall(a, b, c, d, e, f) @@ -674,19 +674,19 @@ function staticcall(a: word, b: word, c: word, d: word, e: word, f: word) -> wor return res; } -function revert(a: word, b: word) -> () { +function revert(a: word, b: word) { assembly { revert(a, b) } } -function invalid() -> () { +function invalid() { assembly { invalid() } } -function selfdestruct(a: word) -> () { +function selfdestruct(a: word) { assembly { selfdestruct(a) } From f1eec27878cce7cc8d0a3aff9f850cd306c27bf7 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 064/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std std.sol Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/std.sol | 888 ++++++++++-------- 1 file changed, 484 insertions(+), 404 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/std.sol b/crates/parser/tests/fixtures/corpus/ok/std/std.sol index e095c148..697beb0f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/std.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/std.sol @@ -1,4 +1,4 @@ -import std.opcodes.{add, sub, mul, div, mod, addmod as addmod_, mulmod as mulmod_, and as and_, or as or_, xor as xor_, shl, shr, eq, not as not_, gt as gt_, iszero, keccak256, mstore, mload, mcopy, sstore, sload, gas, calldataload, calldatacopy, returndatasize, returndatacopy, log1 as log1_, call, staticcall, revert as revert_, invalid}; +import {add, sub, mul, div, mod, addmod as addmod_, mulmod as mulmod_, and as and_, or as or_, xor as xor_, shl, shr, eq, not as not_, gt as gt_, iszero, keccak256, mstore, mload, mcopy, sstore, sload, gas, calldataload, calldatacopy, returndatasize, returndatacopy, log1 as log1_, call, staticcall, revert as revert_, invalid} from std.opcodes; pragma no-patterson-condition ABIEncode, Num, Array, ArrayPush, Eq, Ord; pragma no-coverage-condition ABIDecode, MemoryType, Array, ArrayPush, RValueIdxAccess; @@ -175,19 +175,18 @@ export { */ -forall t.t:Typedef(word) => -function log1(v:t, topic:word) -> () { +function log1(v: t, topic: word) where t: Typedef { let w : word = Typedef.rep(v); mstore(0, w); log1_(0, 32, topic); } -function unimplemented() -> () { +function unimplemented() { let Unimplemented = Error(0x6e128399); revertWithError(Unimplemented); } -function out_of_bounds() -> () { +function out_of_bounds() { let OutOfBounds = Error(0xb4120f14); revertWithError(OutOfBounds); } @@ -197,65 +196,68 @@ function out_of_bounds() -> () { // ------------------------------------------------------------------ // EmitHull has special handling for `revertLit("...")` after MastEval has // constant-folded the argument to a string literal. -function revertLit(comptime s: string) -> () { +function revertLit(comptime s: string) { unimplemented(); // Sanity check if folding ignores it. return (); } // Empty revert. -function revertEmpty() -> () { +function revertEmpty() { revert_(0, 0); } // Bottom: a value of any type. absurd never returns, it reverts, so it can -// stand in for a result of any type. Used to derive class instances for empty +// stand in for a result of any type. Used to derive trait impls for empty // data types (which have no values, so the method bodies are unreachable). The -// recursive tail satisfies the forall a . a return type; execution never +// recursive tail satisfies the generic result type `a`; execution never // reaches it because revertEmpty() aborts first. -forall a . function absurd() -> a { +function absurd() returns (a) { // Despite looking like an infinite loop, this reverts: revertEmpty() // aborts execution on the first line, so the recursive return absurd() // is never actually run. The recursion exists only to give the body a - // value of type a, satisfying the forall a . a return type. + // value of type `a`, satisfying the generic result type. revertEmpty(); return absurd(); } // TODO: use bytes4 -data Error = Error(word) | Empty | Msg(memory(string)); +enum Error { Error(word), Empty, Msg(memory) } // A string literal can be used as an Error: `require(cond, "message")` reverts -// with the message. The literal is materialized into memory(string) here; MastEval +// with the message. The literal is materialized into memory here; MastEval // erases the comptime-only parameter by cloning this method per literal, so // the materializer sees a literal rather than a parameter. -instance Error : Str { - function fromString(s: string) -> Error { +impl Str { + function fromString(s: string) returns (Error) { return Error.Msg(Str.fromString(s)); } } // Revert with Error selector. -function revertWithError(e:Error) -> () { - match e { - | .Error(selector) => - mstore(0, selector); +function revertWithError(e: Error) { + match (e) { +case .Error(selector) { +mstore(0, selector); // We only care about the BE MSB. revert_(28, 4); - | .Empty => - revert_(0, 0); - | .Msg(msg) => - let msg_ = Typedef.rep(msg); +} +case .Empty { +revert_(0, 0); +} +case .Msg(msg) { +let msg_ = Typedef.rep(msg); revert_(msg_ + 32, mload(msg_)); - } +} +} } -function assert(cond: bool) -> () { +function assert(cond: bool) { if (!cond) { invalid(); } } -function require(cond: bool, e: Error) -> () { +function require(cond: bool, e: Error) { if (!cond) { revertWithError(e); } @@ -264,271 +266,316 @@ function require(cond: bool, e: Error) -> () { // --- booleans --- // TODO: this should short circuit. probably needs some compiler magic to do so. -function and(x: bool, y: bool) -> bool { - match x, y { - | true, y => return y; - | false, _ => return false; - } +function and(x: bool, y: bool) returns (bool) { + match (x, y) { +case (true, y) { +return y; +} +case (false, _) { +return false; +} +} } // TODO: this should short circuit. probably needs some compiler magic to do so. -function or(x: bool, y: bool) -> bool { - match x, y { - | true, _ => return true; - | false, y => return y; - } +function or(x: bool, y: bool) returns (bool) { + match (x, y) { +case (true, _) { +return true; +} +case (false, y) { +return y; +} +} } -function not(b:bool) -> bool { - match b { - | false => return true; - | true => return false; - } +function not(b: bool) returns (bool) { + match (b) { +case false { +return true; +} +case true { +return false; +} +} } -function frombool(b : bool) -> word { - match b { - | false => return 0; - | true => return 1; - } +function frombool(b: bool) returns (word) { + match (b) { +case false { +return 0; +} +case true { +return 1; +} +} } -function tobool(x: word) -> bool { - match x { - | 0 => return false; - | _ => return true; - } +function tobool(x: word) returns (bool) { + match (x) { +case 0 { +return false; +} +default { +return true; +} +} } // --- Tuple projections --- -forall a b . function fst(p: (a, b)) -> a { - match p { - | (a, _) => return a; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (a, _) { +return a; +} +} } -forall a b . function snd(p: (a, b)) -> b { - match p { - | (_, b) => return b; - } +function snd(p: (a, b)) returns (b) { + match (p) { +case (_, b) { +return b; +} +} } // --- Proxy --- // Proxy is a unit type that can be used to pass Types as paramaters at runtime -data Proxy(t) = Proxy; +enum Proxy { Proxy } // --- Type Abstraction --- -forall abs rep . class abs:Typedef(rep) { - function abs(x:rep) -> abs; - function rep(x:abs) -> rep; +trait Typedef { + function abs(x: rep) returns (abs) ; + function rep(x: abs) returns (rep) ; } -forall t. -default instance t:Typedef(t) { - function abs(x:t) -> t { return x; } - function rep(x:t) -> t { return x; } +default impl Typedef { + function abs(x: t) returns (t) { return x; } + function rep(x: t) returns (t) { return x; } } // --- Equality --- // Note: All these are used by the compiler by name. -forall a. -class a:Eq { - function eq(x:a, y:a) -> bool; +trait Eq { + function eq(x: a, y: a) returns (bool) ; } -forall a. a:Eq => -function ne(x:a, y:a) -> bool { +function ne(x: a, y: a) returns (bool) where a: Eq { return not(Eq.eq(x,y)); } // --- Ordering --- // Note: All these are used by the compiler by name. -forall a. a:Eq => -class a:Ord { - function gt(x:a, y:a) -> bool; +trait Ord where a: Eq { + function gt(x: a, y: a) returns (bool) ; } -forall a. a:Ord => -function gt(x:a, y:a) -> bool { +function gt(x: a, y: a) returns (bool) where a: Ord { return Ord.gt(x,y); } -forall a. a:Ord => -function le(x:a, y:a) -> bool { +function le(x: a, y: a) returns (bool) where a: Ord { return not(Ord.gt(x,y)); } -forall a. a:Ord => -function ge(x:a, y:a) -> bool { +function ge(x: a, y: a) returns (bool) where a: Ord { return le(y,x); } -forall a. a:Ord => -function lt(x:a, y:a) -> bool { +function lt(x: a, y: a) returns (bool) where a: Ord { return Ord.gt(y,x); } -// --- Generic deriving: structural instances over the representation universe --- +// --- Generic deriving: structural impls over the representation universe --- // These let `#[derive(Eq)]` / `#[derive(Ord)]` work for any data type through -// its Generic(rep) instance, where rep is built from (), sum(f, g) and (f, g). +// its `Generic` impl, where `rep` is built from `()`, `sum` and +// `(f, g)`. -instance () : Eq { - function eq(x : (), y : ()) -> bool { +impl Eq<()> { + function eq(x: (), y: ()) returns (bool) { return true; } } -forall f g . f:Eq, g:Eq => -instance sum(f, g) : Eq { - function eq(x : sum(f, g), y : sum(f, g)) -> bool { - match x { - | inl(a) => - match y { - | inl(b) => return Eq.eq(a, b); - | inr(b) => return false; - } - | inr(a) => - match y { - | inl(b) => return false; - | inr(b) => return Eq.eq(a, b); - } - } +impl Eq> where f: Eq, g: Eq { + function eq(x: sum, y: sum) returns (bool) { + match (x) { +case inl(a) { +match (y) { +case inl(b) { +return Eq.eq(a, b); +} +case inr(b) { +return false; +} +} +} +case inr(a) { +match (y) { +case inl(b) { +return false; +} +case inr(b) { +return Eq.eq(a, b); +} +} +} +} } } -forall f g . f:Eq, g:Eq => -instance (f, g) : Eq { - function eq(x : (f, g), y : (f, g)) -> bool { - match x { - | (a1, b1) => - match y { - | (a2, b2) => - match Eq.eq(a1, a2) { - | true => return Eq.eq(b1, b2); - | false => return false; - } - } - } +impl Eq<(f, g)> where f: Eq, g: Eq { + function eq(x: (f, g), y: (f, g)) returns (bool) { + match (x) { +case (a1, b1) { +match (y) { +case (a2, b2) { +match (Eq.eq(a1, a2)) { +case true { +return Eq.eq(b1, b2); +} +case false { +return false; +} +} +} +} +} +} } } -instance () : Ord { - function gt(x : (), y : ()) -> bool { +impl Ord<()> { + function gt(x: (), y: ()) returns (bool) { return false; } } -forall f g . f:Ord, g:Ord => -instance sum(f, g) : Ord { - function gt(x : sum(f, g), y : sum(f, g)) -> bool { - match x { - | inl(a) => - match y { - | inl(b) => return Ord.gt(a, b); - | inr(b) => return false; - } - | inr(a) => - match y { - | inl(b) => return true; - | inr(b) => return Ord.gt(a, b); - } - } +impl Ord> where f: Ord, g: Ord { + function gt(x: sum, y: sum) returns (bool) { + match (x) { +case inl(a) { +match (y) { +case inl(b) { +return Ord.gt(a, b); +} +case inr(b) { +return false; +} +} +} +case inr(a) { +match (y) { +case inl(b) { +return true; +} +case inr(b) { +return Ord.gt(a, b); +} +} +} +} } } -forall f g . f:Ord, g:Ord => -instance (f, g) : Ord { - function gt(x : (f, g), y : (f, g)) -> bool { - match x { - | (a1, b1) => - match y { - | (a2, b2) => - match Ord.gt(a1, a2) { - | true => return true; - | false => - match Eq.eq(a1, a2) { - | true => return Ord.gt(b1, b2); - | false => return false; - } - } - } - } +impl Ord<(f, g)> where f: Ord, g: Ord { + function gt(x: (f, g), y: (f, g)) returns (bool) { + match (x) { +case (a1, b1) { +match (y) { +case (a2, b2) { +match (Ord.gt(a1, a2)) { +case true { +return true; +} +case false { +match (Eq.eq(a1, a2)) { +case true { +return Ord.gt(b1, b2); +} +case false { +return false; +} +} +} +} +} +} +} +} } } // --- Arithmetic --- // Note: All these are used by the compiler by name. -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Sub { - function sub(l: t, r: t) -> t; +trait Sub { + function sub(l: t, r: t) returns (t) ; } -forall t . class t:Mul { - function mul(l: t, r: t) -> t; +trait Mul { + function mul(l: t, r: t) returns (t) ; } -forall t . class t:Div { - function div(l: t, r: t) -> t; +trait Div { + function div(l: t, r: t) returns (t) ; } -forall t . class t:Mod { - function mod(l: t, r: t) -> t; +trait Mod { + function mod(l: t, r: t) returns (t) ; } -forall t . class t:BitAnd { - function band(l: t, r: t) -> t; +trait BitAnd { + function band(l: t, r: t) returns (t) ; } -forall t . class t:BitOr { - function bor(l: t, r: t) -> t; +trait BitOr { + function bor(l: t, r: t) returns (t) ; } -forall t . class t:BitXor { - function bxor(l: t, r: t) -> t; +trait BitXor { + function bxor(l: t, r: t) returns (t) ; } -forall t . class t:BitNot { - function bnot(x: t) -> t; +trait BitNot { + function bnot(x: t) returns (t) ; } -forall t . class t:Bounded { - function minVal() -> t; - function maxVal() -> t; +trait Bounded { + function minVal() returns (t) ; + function maxVal() returns (t) ; } -forall t . t:Bounded => -function maxVal() -> t { return Bounded.maxVal(); } +function maxVal() returns (t) where t: Bounded { return Bounded.maxVal(); } -// umbrella class -forall a. a:Add, a:Sub, a:Bounded, a:Eq, a:Ord, a:Typedef(word) => -class a:Num { - function maxVal() -> a; - function toWord(x:a) -> word; - function fromWord(x:word) -> a; - function fromInteger(comptime x:integer) -> comptime a; - function add(x:a, y:a) -> a; - function sub(x:a, y:a) -> a; - function gt(x:a, y:a) -> bool; +// Umbrella trait. +trait Num where a: Add, a: Sub, a: Bounded, a: Eq, a: Ord, a: Typedef { + function maxVal() returns (a) ; + function toWord(x: a) returns (word) ; + function fromWord(x: word) returns (a) ; + function fromInteger(comptime x: integer) returns (comptime) ; + function add(x: a, y: a) returns (a) ; + function sub(x: a, y: a) returns (a) ; + function gt(x: a, y: a) returns (bool) ; } -forall a. a:Add, a:Sub, a:Bounded, a:Eq, a:Ord, a:Typedef(word) => -default instance a:Num { - function maxVal() -> a { return Bounded.maxVal(); } - function toWord(x:a) -> word { return Typedef.rep(x); } - function fromWord(x:word) -> a { return Typedef.abs(x); } - function fromInteger(comptime x:integer) -> comptime a { return Typedef.abs(wordFromInteger(x)); } - function add(x:a, y:a) -> a { return Add.add(x,y); } - function sub(x:a, y:a) -> a { return Sub.sub(x,y); } - function gt(x: a, y: a) -> bool { return Ord.gt(x, y); } +default impl Num where a: Add, a: Sub, a: Bounded, a: Eq, a: Ord, a: Typedef { + function maxVal() returns (a) { return Bounded.maxVal(); } + function toWord(x: a) returns (word) { return Typedef.rep(x); } + function fromWord(x: word) returns (a) { return Typedef.abs(x); } + function fromInteger(comptime x: integer) returns (comptime) { return Typedef.abs(wordFromInteger(x)); } + function add(x: a, y: a) returns (a) { return Add.add(x,y); } + function sub(x: a, y: a) returns (a) { return Sub.sub(x,y); } + function gt(x: a, y: a) returns (bool) { return Ord.gt(x, y); } } // --- Word Arithmetic & Logic --- @@ -536,181 +583,189 @@ default instance a:Num { // These are intended to be folded by MastEval when their arguments are // statically known word values. -function eqWord(x:word, y:word) -> bool { +function eqWord(x: word, y: word) returns (bool) { return tobool(eq(x, y)); } -function gtWord(x:word, y:word) -> bool { +function gtWord(x: word, y: word) returns (bool) { return tobool(gt_(x, y)); } -function maxWord(a : word, b : word) -> word { - match gtWord(a, b) { - | true => return a; - | false => return b; - } +function maxWord(a: word, b: word) returns (word) { + match (gtWord(a, b)) { +case true { +return a; +} +case false { +return b; +} +} } -function minWord(a : word, b : word) -> word { - match gtWord(a, b) { - | true => return b; - | false => return a; - } +function minWord(a: word, b: word) returns (word) { + match (gtWord(a, b)) { +case true { +return b; +} +case false { +return a; +} +} } -function addWord(l: word, r: word) -> word { +function addWord(l: word, r: word) returns (word) { return add(l, r); } -function subWord(l: word, r: word) -> word { +function subWord(l: word, r: word) returns (word) { return sub(l, r); } // Bitwise AND -function bandWord(x: word, y: word) -> word { +function bandWord(x: word, y: word) returns (word) { return and_(x, y); } // Bitwise OR -function borWord(x: word, y: word) -> word { +function borWord(x: word, y: word) returns (word) { return or_(x, y); } // Bitwise XOR -function bxorWord(x: word, y: word) -> word { +function bxorWord(x: word, y: word) returns (word) { return xor_(x, y); } // Bitwise NOT -function bnotWord(x: word) -> word { +function bnotWord(x: word) returns (word) { return not_(x); } // Bitwise SHL -function bshlWord(x: word, y: word) -> word { +function bshlWord(x: word, y: word) returns (word) { return shl(x, y); } // Bitwise SHR -function bshrWord(x: word, y: word) -> word { +function bshrWord(x: word, y: word) returns (word) { return shr(x, y); } -instance word:Eq { - function eq(x:word, y:word) -> bool { +impl Eq { + function eq(x: word, y: word) returns (bool) { return eqWord(x, y); } } -instance word:Ord { - function gt(x:word, y:word) -> bool { +impl Ord { + function gt(x: word, y: word) returns (bool) { return gtWord(x, y); } } -instance word:Add { - function add(l: word, r: word) -> word { +impl Add { + function add(l: word, r: word) returns (word) { return addWord(l, r); } } -instance word:Sub { - function sub(l: word, r: word) -> word { +impl Sub { + function sub(l: word, r: word) returns (word) { return subWord(l, r); } } -function mulWord(l: word, r: word) -> word { +function mulWord(l: word, r: word) returns (word) { return mul(l, r); } -instance word:Mul { - function mul(l: word, r: word) -> word { +impl Mul { + function mul(l: word, r: word) returns (word) { return mulWord(l, r); } } -instance word:Div { - function div(l: word, r: word) -> word { +impl Div { + function div(l: word, r: word) returns (word) { return div(l, r); } } -instance word:Mod { - function mod (l : word, r : word) -> word { +impl Mod { + function mod(l: word, r: word) returns (word) { return mod(l, r); } } -instance word:BitAnd { - function band(l: word, r: word) -> word { +impl BitAnd { + function band(l: word, r: word) returns (word) { return bandWord(l, r); } } -instance word:BitOr { - function bor(l: word, r: word) -> word { +impl BitOr { + function bor(l: word, r: word) returns (word) { return borWord(l, r); } } -instance word:BitXor { - function bxor(l: word, r: word) -> word { +impl BitXor { + function bxor(l: word, r: word) returns (word) { return bxorWord(l, r); } } -instance word:BitNot { - function bnot(x: word) -> word { +impl BitNot { + function bnot(x: word) returns (word) { return bnotWord(x); } } -instance integer : Eq { - function eq(x : integer, y : integer) -> bool { +impl Eq { + function eq(x: integer, y: integer) returns (bool) { return integerEq(x, y); } } -instance integer : Ord { - function gt(x : integer, y : integer) -> bool { +impl Ord { + function gt(x: integer, y: integer) returns (bool) { return integerLt(y, x); } } -instance integer : Add { - function add(l : integer, r : integer) -> integer { +impl Add { + function add(l: integer, r: integer) returns (integer) { return integerAdd(l, r); } } -instance integer : Sub { - function sub(l : integer, r : integer) -> integer { +impl Sub { + function sub(l: integer, r: integer) returns (integer) { return integerSub(l, r); } } -instance integer : Mul { - function mul(l : integer, r : integer) -> integer { +impl Mul { + function mul(l: integer, r: integer) returns (integer) { return integerMul(l, r); } } -instance word:Bounded { - function maxVal() -> word { +impl Bounded { + function maxVal() returns (word) { return 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; } - function minVal () -> word { + function minVal() returns (word) { return 0; } } -function hash1(x: word) -> word { +function hash1(x: word) returns (word) { mstore(0, x); return keccak256(0, 32); } -function hash2(x: word, y: word) -> word { +function hash2(x: word, y: word) returns (word) { mstore(0, x); mstore(32, y); return keccak256(0, 64); @@ -718,249 +773,270 @@ function hash2(x: word, y: word) -> word { // --- Value Types --- -forall t. t:Typedef(word) => -function toWord(x:t) -> word { return Typedef.rep(x); } +function toWord(x: t) returns (word) where t: Typedef { return Typedef.rep(x); } -data uint256 = uint256(word); -instance uint256:Typedef(word) { - function abs(w: word) -> uint256 { +enum uint256 { uint256(word) } +impl Typedef { + function abs(w: word) returns (uint256) { return uint256(w); } - function rep(x: uint256) -> word { - match x { - | uint256(w) => return w; - } + function rep(x: uint256) returns (word) { + match (x) { +case uint256(w) { +return w; +} +} } } -instance uint256:Add { - function add(x : uint256, y : uint256) -> uint256 { +impl Add { + function add(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Add.add(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Sub { - function sub(x : uint256, y : uint256) -> uint256 { +impl Sub { + function sub(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Sub.sub(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Mul { - function mul(x : uint256, y : uint256) -> uint256 { +impl Mul { + function mul(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Mul.mul(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Div { - function div(x : uint256, y : uint256) -> uint256 { +impl Div { + function div(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Div.div(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Mod { - function mod(x : uint256, y : uint256) -> uint256 { +impl Mod { + function mod(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Mod.mod(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitAnd { - function band(x : uint256, y : uint256) -> uint256 { +impl BitAnd { + function band(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(BitAnd.band(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitOr { - function bor(x : uint256, y : uint256) -> uint256 { +impl BitOr { + function bor(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(BitOr.bor(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitXor { - function bxor(x : uint256, y : uint256) -> uint256 { +impl BitXor { + function bxor(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(BitXor.bxor(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitNot { - function bnot(x : uint256) -> uint256 { +impl BitNot { + function bnot(x: uint256) returns (uint256) { return Typedef.abs(BitNot.bnot(Typedef.rep(x))); } } -instance uint256:Eq { - function eq(x : uint256, y : uint256) -> bool { +impl Eq { + function eq(x: uint256, y: uint256) returns (bool) { return Eq.eq(Typedef.rep(x), Typedef.rep(y)); } } -instance uint256:Ord { - function gt(x : uint256, y : uint256) -> bool { +impl Ord { + function gt(x: uint256, y: uint256) returns (bool) { return Ord.gt(Typedef.rep(x), Typedef.rep(y)); } } -instance uint256:Bounded { - function maxVal() -> uint256 { +impl Bounded { + function maxVal() returns (uint256) { return uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); } - function minVal () -> uint256 { + function minVal() returns (uint256) { return uint256(0); } } -instance uint256:Int { - function fromInteger(x:integer) -> uint256 { +impl Int { + function fromInteger(x: integer) returns (uint256) { return uint256(wordFromInteger(x)); } } -function addmod(x: uint256, y: uint256, k: uint256) -> uint256 { +function addmod(x: uint256, y: uint256, k: uint256) returns (uint256) { require(k != uint256(0), Error(0x7125cbb9)); // AddModWithZero() return Typedef.abs(addmod_(Typedef.rep(x), Typedef.rep(y), Typedef.rep(k))); } -function mulmod(x: uint256, y: uint256, k: uint256) -> uint256 { +function mulmod(x: uint256, y: uint256, k: uint256) returns (uint256) { require(k != uint256(0), Error(0xdaea23b9)); // MulModWithZero() return Typedef.abs(mulmod_(Typedef.rep(x), Typedef.rep(y), Typedef.rep(k))); } -data byte = byte(word); -instance byte:Typedef(word) { - function abs(w: word) -> byte { +enum byte { byte(word) } +impl Typedef { + function abs(w: word) returns (byte) { return byte(w); } - function rep(x: byte) -> word { - match x { - | byte(w) => return w; - } + function rep(x: byte) returns (word) { + match (x) { +case byte(w) { +return w; +} +} } } // --- Address --- -data address = address(word); +enum address { address(word) } -instance address:Typedef(word) { - function rep(x:address) -> word { - match x { - | address(y) => return y; - } +impl Typedef { + function rep(x: address) returns (word) { + match (x) { +case address(y) { +return y; +} +} } - function abs(x:word) -> address { + function abs(x: word) returns (address) { return address(x); } } -instance address:Eq { - function eq(x : address , y : address) -> bool { +impl Eq
{ + function eq(x: address, y: address) returns (bool) { return Eq.eq(Typedef.rep(x), Typedef.rep(y)); } } // --- Bytes4 --- -data bytes4 = bytes4(word); +enum bytes4 { bytes4(word) } -instance bytes4:Typedef(word) { - function rep(b : bytes4) -> word { - match b { - | bytes4(w) => return w; - } +impl Typedef { + function rep(b: bytes4) returns (word) { + match (b) { +case bytes4(w) { +return w; +} +} } - function abs(w : word) -> bytes4 { + function abs(w: word) returns (bytes4) { return bytes4(w); } } // --- Bytes32 --- -data bytes32 = bytes32(word); +enum bytes32 { bytes32(word) } -instance bytes32:Typedef(word) { - function rep(b : bytes32) -> word { - match b { - | bytes32(w) => return w; - } +impl Typedef { + function rep(b: bytes32) returns (word) { + match (b) { +case bytes32(w) { +return w; +} +} } - function abs(w : word) -> bytes32 { + function abs(w: word) returns (bytes32) { return bytes32(w); } } -instance bytes32:Eq { - function eq(x : bytes32, y : bytes32) -> bool { +impl Eq { + function eq(x: bytes32, y: bytes32) returns (bool) { return Eq.eq(Typedef.rep(x), Typedef.rep(y)); } } -instance bytes32:Ord { - function gt(x : bytes32, y : bytes32) -> bool { +impl Ord { + function gt(x: bytes32, y: bytes32) returns (bool) { return Ord.gt(Typedef.rep(x), Typedef.rep(y)); } } // --- Pointers --- -data memory(t) = memory(word); -forall t . instance memory(t) : Typedef(word) { - function abs(x: word) -> memory(t) { +enum memory { memory(word) } +impl Typedef, word> { + function abs(x: word) returns (memory) { return memory(x); } - function rep(x: memory(t)) -> word { - match x { - | memory(w) => return w; - } + function rep(x: memory) returns (word) { + match (x) { +case memory(w) { +return w; +} +} } } -data storage(t) = storage(word); -forall t . instance storage(t) : Typedef(word) { - function abs(x: word) -> storage(t) { +enum storage { storage(word) } +impl Typedef, word> { + function abs(x: word) returns (storage) { return storage(x); } - function rep(x: storage(t)) -> word { - match x { - | storage(w) => return w; - } + function rep(x: storage) returns (word) { + match (x) { +case storage(w) { +return w; +} +} } } -data calldata(t) = calldata(word); -forall t . instance calldata(t) : Typedef(word) { - function abs(x: word) -> calldata(t) { +enum calldata { calldata(word) } +impl Typedef, word> { + function abs(x: word) returns (calldata) { return calldata(x); } - function rep(x: calldata(t)) -> word { - match x { - | calldata(w) => return w; - } + function rep(x: calldata) returns (word) { + match (x) { +case calldata(w) { +return w; +} +} } } -data returndata(t) = returndata(word); -forall t . instance returndata(t) : Typedef(word) { - function abs(x: word) -> returndata(t) { +enum returndata { returndata(word) } +impl Typedef, word> { + function abs(x: word) returns (returndata) { return returndata(x); } - function rep(x: returndata(t)) -> word { - match x { - | returndata(w) => return w; - } + function rep(x: returndata) returns (word) { + match (x) { +case returndata(w) { +return w; +} +} } } -data mapping(member, index) = mapping(word) ; +enum mapping { mapping(word) } -data array(member) = array(word) ; +enum array { array(word) } // --- Low-level memory ops -function strlen(s:memory(string)) -> word { - match s { | memory(a) => return mload(a); } +function strlen(s: memory) returns (word) { + match (s) { +case memory(a) { +return mload(a); +} +} } // --- Memory Utilities --- @@ -969,35 +1045,35 @@ function strlen(s:memory(string)) -> word { // The word stored in memory at index 0x40 is used to store the start of the currently unused memory region // returns the value stored in memory(0x40) -function get_free_memory() -> word { +function get_free_memory() returns (word) { return mload(0x40); } // set the value stored in memory(0x40) -function set_free_memory(loc : word) -> () { +function set_free_memory(loc: word) { mstore(0x40, loc); } // Allocate memory and update the memory pointer. -function allocate_memory(size : word) -> word { +function allocate_memory(size: word) returns (word) { let ptr = get_free_memory(); set_free_memory(ptr + size); return ptr; } -function allocate_zeroed_memory(size: word) -> word { +function allocate_zeroed_memory(size: word) returns (word) { let ptr = allocate_memory(size); zeroize_memory(ptr, size); return ptr; } // Clears a memory area. -function zeroize_memory(ptr: word, len: word) -> () { +function zeroize_memory(ptr: word, len: word) { let end_ptr = ptr + len; // Zero out 32-byte words. for (let i = 0; i < len / 32; i += 1, ptr += 32) { - mstore(ptr, 0) + mstore(ptr, 0); } // Zero out trailing bytes. We rely on the zero-slot (0x60-0x7f). @@ -1008,9 +1084,9 @@ function zeroize_memory(ptr: word, len: word) -> () { // types that can be written to and read from at a uint256 index // TODO: this needs to be split into LValue / RValue variants for `=` desugaring -forall t val . class t:IndexAccess(val) { - function get(c: t, i: uint256) -> val; - function set(c: t, i: uint256, v: val) -> (); +trait IndexAccess { + function get(c: t, i: uint256) returns (val) ; + function set(c: t, i: uint256, v: val) ; } // --- DynArray --- @@ -1018,18 +1094,18 @@ forall t val . class t:IndexAccess(val) { // Word arrays with a size known only at runtime // types with a size smaller than `word` will not be packed, so a `DynArray(byte)` will waste a lot of space // TODO: storage representation -data DynArray(t); +enum DynArray {} // Layout: the length lives at `loc`, so element i lives at `loc + 32 + i*32`. // An index is in bounds when i < length. -forall t . t:Typedef(word) => instance memory(DynArray(t)):IndexAccess(t) { - function get(ptr : memory(DynArray(t)), i : uint256) -> t { +impl IndexAccess>, t> where t: Typedef { + function get(ptr: memory>, i: uint256) returns (t) { let i_: word = Typedef.rep(i); let loc : word = Typedef.rep(ptr); if (i_ >= mload(loc)) { out_of_bounds(); } return Typedef.abs(mload(loc + 32 + (i_ * 32))); } - function set(arr : memory(DynArray(t)), i : uint256, val : t) -> () { + function set(arr: memory>, i: uint256, val: t) { let i_ : word = Typedef.rep(i); let loc : word = Typedef.rep(arr); if (i_ >= mload(loc)) { out_of_bounds(); } @@ -1043,19 +1119,17 @@ forall t . t:Typedef(word) => instance memory(DynArray(t)):IndexAccess(t) { // arrayLitInit(... arrayLitInit(arrayLitNew(n), 0, e1) ..., n-1, en) // The chain is a plain expression: each step returns the array it wrote to. -forall t . t:Typedef(word) => -function arrayLitNew(n : uint256) -> memory(DynArray(t)) { - let prx : Proxy(t); +function arrayLitNew(n: uint256) returns (memory>) where t: Typedef { + let prx : Proxy; return allocateDynamicArray(prx, Typedef.rep(n)); } -forall t . t:Typedef(word) => -function arrayLitInit(arr : memory(DynArray(t)), i : uint256, v : t) -> memory(DynArray(t)) { +function arrayLitInit(arr: memory>, i: uint256, v: t) returns (memory>) where t: Typedef { IndexAccess.set(arr, i, v); return arr; } -forall t . function allocateDynamicArray(prx : Proxy(t), length : word) -> memory(DynArray(t)) { +function allocateDynamicArray(prx: Proxy, length: word) returns (memory>) { // size of allocation in bytes let sz : word = (length + 1) * 32; @@ -1065,7 +1139,7 @@ forall t . function allocateDynamicArray(prx : Proxy(t), length : word) -> memor // write array length and return mstore(free, length); - let res : memory(DynArray(t)) = Typedef.abs(free); + let res : memory> = Typedef.abs(free); return res; } @@ -1074,18 +1148,18 @@ forall t . function allocateDynamicArray(prx : Proxy(t), length : word) -> memor // tightly packed byte arrays // bytes does not have a runtime representation since it can only ever exist in // memory / calldata / storage and serves only as a type tag for pointer types -// TODO: IndexAccess for memory(bytes) -// TODO: IndexAccess for calldata(bytes) -// TODO: IndexAccess for storage(bytes) -data bytes; +// TODO: IndexAccess for memory +// TODO: IndexAccess for calldata +// TODO: IndexAccess for storage +enum bytes {} // --- strings --- // TODO: should this be a typedef over `bytes`? -data string; +enum string {} -instance string:Add { - function add(l: string, r: string) -> string { +impl Add { + function add(l: string, r: string) returns (string) { return concatLit(l, r); } } @@ -1096,25 +1170,25 @@ instance string:Add { // These are intended to be folded by MastEval when their arguments are // statically known string literals. -function concatLit(comptime a: string, comptime b: string) -> string { +function concatLit(comptime a: string, comptime b: string) returns (string) { unimplemented(); // Sanity check if folding ignores it. return ""; } -function strlenLit(comptime a: string) -> word { +function strlenLit(comptime a: string) returns (word) { unimplemented(); // Sanity check if folding ignores it. return 0; } // Keccak-256 hash of the string-literal as UTF-8 bytes. -function keccakLit(comptime a: string) -> word { +function keccakLit(comptime a: string) returns (word) { unimplemented(); // Sanity check if folding ignores it. return 0; } // Keccak-256 hash of a word's 32-byte big-endian representation. // NOTE: this could be deprecated if we have comptime `to_bytes`. -function keccakWordLit(comptime a: word) -> word { +function keccakWordLit(comptime a: word) returns (word) { unimplemented(); // Sanity check if folding ignores it. return 0; } @@ -1123,43 +1197,49 @@ function keccakWordLit(comptime a: word) -> word { // A slice is a wrapper around an existing pointer type that extends the // underlying type with information about the size of the data pointed to by `t` -data slice(ptr) = slice(ptr, word); +enum slice { slice(ptr, word) } // --- Word Reader --- // A WordReader is an abstraction over byte indexed structure that can be read in word sized chunks (e.g. calldata / memory) // These let us use the same abi decoding routines for calldata / memory -forall ty . class ty:WordReader { +trait WordReader { // returns the word currently pointed to by the WordReader - function read(reader:ty) -> word; + function read(reader: ty) returns (word) ; // returns a new WordReader that points to a location `offset` bytes further into the array - function advance(reader:ty, offset:word) -> ty; + function advance(reader: ty, offset: word) returns (ty) ; // copies a block from the underlying source to memory - function copyToMem(reader:ty, dst: word, cnt: word) -> (); + function copyToMem(reader: ty, dst: word, cnt: word) ; } // WordReader for memory -data MemoryWordReader = MemoryWordReader(word); -instance MemoryWordReader:WordReader { - function read(reader:MemoryWordReader) -> word { - match reader { - | MemoryWordReader(ptr) => return mload(ptr); - } +enum MemoryWordReader { MemoryWordReader(word) } +impl WordReader { + function read(reader: MemoryWordReader) returns (word) { + match (reader) { +case MemoryWordReader(ptr) { +return mload(ptr); +} +} } - function advance(reader:MemoryWordReader, offset:word) -> MemoryWordReader { - match reader { - | MemoryWordReader(ptr) => return MemoryWordReader(ptr + offset); - } + function advance(reader: MemoryWordReader, offset: word) returns (MemoryWordReader) { + match (reader) { +case MemoryWordReader(ptr) { +return MemoryWordReader(ptr + offset); +} +} } - function copyToMem(reader:MemoryWordReader, dst:word, cnt: word) -> () { - match reader { - | MemoryWordReader(ptr) => mcopy(dst, ptr, cnt); - } + function copyToMem(reader: MemoryWordReader, dst: word, cnt: word) { + match (reader) { +case MemoryWordReader(ptr) { +mcopy(dst, ptr, cnt); +} +} } } // WordReader for calldata -data CalldataWordReader = CalldataWordReader(word); +enum CalldataWordReader { CalldataWordReader(word) } instance CalldataWordReader : Typedef(word) { function abs(a:word) -> CalldataWordReader { return CalldataWordReader(a); } From d44d142e12a0888c6365ece634212b839eb9d8b0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 065/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std std.sol Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/std.sol | 903 +++++++++--------- 1 file changed, 449 insertions(+), 454 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/std.sol b/crates/parser/tests/fixtures/corpus/ok/std/std.sol index 697beb0f..30da458b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/std.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/std.sol @@ -1241,218 +1241,233 @@ mcopy(dst, ptr, cnt); // WordReader for calldata enum CalldataWordReader { CalldataWordReader(word) } -instance CalldataWordReader : Typedef(word) { - function abs(a:word) -> CalldataWordReader { return CalldataWordReader(a); } - function rep(r:CalldataWordReader) -> word { - match r { - | CalldataWordReader(a) => return a; - } +impl Typedef { + function abs(a: word) returns (CalldataWordReader) { return CalldataWordReader(a); } + function rep(r: CalldataWordReader) returns (word) { + match (r) { +case CalldataWordReader(a) { +return a; +} +} } } -instance CalldataWordReader:WordReader { - function read(reader:CalldataWordReader) -> word { - match reader { - | CalldataWordReader(ptr) => return calldataload(ptr); - } +impl WordReader { + function read(reader: CalldataWordReader) returns (word) { + match (reader) { +case CalldataWordReader(ptr) { +return calldataload(ptr); +} +} } - function advance(reader:CalldataWordReader, offset:word) -> CalldataWordReader { - match reader { - | CalldataWordReader(ptr) => return CalldataWordReader(ptr + offset); - } + function advance(reader: CalldataWordReader, offset: word) returns (CalldataWordReader) { + match (reader) { +case CalldataWordReader(ptr) { +return CalldataWordReader(ptr + offset); +} +} } - function copyToMem(reader:CalldataWordReader, dst:word, cnt: word) -> () { - match reader { - | CalldataWordReader(ptr) => calldatacopy(dst, ptr, cnt); - } + function copyToMem(reader: CalldataWordReader, dst: word, cnt: word) { + match (reader) { +case CalldataWordReader(ptr) { +calldatacopy(dst, ptr, cnt); +} +} } } // --- HasWordReader --- -// The HasWordReader class defines the types for which a WordReader can be produced -// We define instances for memory(bytes) and calldata(bytes) -forall self reader . class self:HasWordReader(reader) { - function getWordReader(x:self) -> reader; +// The HasWordReader trait defines the types for which a WordReader can be produced. +// We define impls for memory and calldata. +trait HasWordReader { + function getWordReader(x: self) returns (reader) ; } -instance memory(bytes):HasWordReader(MemoryWordReader) { - function getWordReader(x:memory(bytes)) -> MemoryWordReader { +impl HasWordReader, MemoryWordReader> { + function getWordReader(x: memory) returns (MemoryWordReader) { return MemoryWordReader(Typedef.rep(x)); } } -instance calldata(bytes):HasWordReader(CalldataWordReader) { - function getWordReader(x:calldata(bytes)) -> CalldataWordReader { +impl HasWordReader, CalldataWordReader> { + function getWordReader(x: calldata) returns (CalldataWordReader) { return CalldataWordReader(Typedef.rep(x)); } } // --- MemoryType --- -// A MemoryType instance abstracts over type specific logic related to memory -// layout, allowing us to write code that is generic over which type is held in memory -forall self loadedType. class self:MemoryType(loadedType) { - // Proxy needed becaused class methods must mention strong type params - // loads an instance of `loadedType` from an instance of `self` located at `loc` in memory - function loadFromMemory(p:Proxy(self), loc:word) -> loadedType; +// A MemoryType impl abstracts over type-specific memory layout, allowing us to +// write code that is generic over the type held in memory. +trait MemoryType { + // Proxy is needed because trait methods must mention strong type parameters. + // Loads a `loadedType` value from a `self` value located at `loc` in memory. + function loadFromMemory(p: Proxy, loc: word) returns (loadedType) ; } // A uint256 can be loaded from memory and pushed straight onto the stack -instance uint256:MemoryType(uint256) { - function loadFromMemory(p:Proxy(uint256), loc:word) -> uint256 { +impl MemoryType { + function loadFromMemory(p: Proxy, loc: word) returns (uint256) { return uint256(mload(loc)); } } // We load a DynArray into a sized pointer to the first element /* -forall ty ret . ty:MemoryType(ret) => instance DynArray(ty):MemoryType(slice(memory(ret))) { - function loadFromMemory(p : Proxy (DynArray(ty)), loc:word) -> slice(memory(ret)) { +impl MemoryType, slice>> where ty: MemoryType { + function loadFromMemory(p: Proxy>, loc: word) returns (slice>) { let length = mload(loc); - return slice(Typedef.abs(loc) : memory(ret), length); + let ptr: memory = memory(Typedef.abs(loc)); + return slice(ptr, length); } } */ // FAIL: patterson // FAIL: bound variable -// if we ty is a MemoryType that returns deref and deref is ABIEncode, then we can encode a memory(ty) +// If `ty: MemoryType` and `deref: ABIEncode`, then memory can be +// encoded by loading and encoding its dereferenced value. // by loading it and then running the ABI encoding for the loaded value /* -forall ty deref . ty:MemoryType(deref), deref:ABIEncode => instance memory(ty):ABIEncode { - function encodeInto(x:memory(ty), basePtr:word, offset:word, tail:word) -> word { - let prx : Proxy(ty); // FIXED: before was Proxy(deref) - return ABIEncode.encodeInto(MemoryType.loadFromMemory(prx, Typedef.rep(x)) : deref, basePtr, offset, tail); +impl ABIEncode> where ty: MemoryType, deref: ABIEncode { + function encodeInto(x: memory, basePtr: word, offset: word, tail: word) returns (word) { + let prx: Proxy; // FIXED: before was Proxy + return ABIEncode.encodeInto(MemoryType.loadFromMemory(prx, Typedef.rep(x)): deref, basePtr, offset, tail); } } */ // --- ABI Tuples --- // Tuples in Solidity are always desugared to nested pairs (to allow for -// inductive typeclass instance constructions) . +// inductive trait-impl constructions). // This is an issue for the ABI routines since the ABI spec differentiates // between `(1,1,1)` and `(1,(1,1))`, but the language treats both identically. // The ABITuple type lets us reiintroduce this distinction: // `ABITuple((1,(1,1))` should be treated as `(1,1,1)` for the purposes of ABI // encoding / decoding. -data ABITuple(tuple) = ABITuple(tuple); +enum ABITuple { ABITuple(tuple) } -forall t . instance ABITuple(t):Typedef(t) { - function abs(t: t) -> ABITuple(t) { +impl Typedef, t> { + function abs(t: t) returns (ABITuple) { return ABITuple(t); } - function rep(x: ABITuple(t)) -> t { - match x { - | ABITuple(v) => return v; - } + function rep(x: ABITuple) returns (t) { + match (x) { +case ABITuple(v) { +return v; +} +} } } // --- ABI Metadata --- // Statically knowable ABI related metadata about `self` -forall self . class self:ABIAttribs { +trait ABIAttribs { // how many bytes should be used for the head portion of the abi encoding of `self` - function headSize(ty:Proxy(self)) -> word; + function headSize(ty: Proxy) returns (word) ; // whether or not `self` is a fully static type - function isStatic(ty:Proxy(self)) -> bool; + function isStatic(ty: Proxy) returns (bool) ; } -forall t. -default instance t:ABIAttribs { - function headSize(ty : Proxy(t)) -> word { return 32; } - function isStatic(ty : Proxy(t)) -> bool { return true; } +default impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return true; } } -instance ():ABIAttribs { - function headSize(ty : Proxy(())) -> word { return 0; } - function isStatic(ty : Proxy(())) -> bool { return true; } +impl ABIAttribs<()> { + function headSize(ty: Proxy<()>) returns (word) { return 0; } + function isStatic(ty: Proxy<()>) returns (bool) { return true; } } -instance uint256:ABIAttribs { - function headSize(ty : Proxy(uint256)) -> word { return 32; } - function isStatic(ty : Proxy(uint256)) -> bool { return true; } +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return true; } } -instance address:ABIAttribs { - function headSize(ty : Proxy(address)) -> word { return 32; } - function isStatic(ty : Proxy(address)) -> bool { return true; } +impl ABIAttribs
{ + function headSize(ty: Proxy
) returns (word) { return 32; } + function isStatic(ty: Proxy
) returns (bool) { return true; } } -forall t . instance DynArray(t):ABIAttribs { - function headSize(ty : Proxy(DynArray(t))) -> word { return 32; } - function isStatic(ty : Proxy(DynArray(t))) -> bool { return false; } +impl ABIAttribs> { + function headSize(ty: Proxy>) returns (word) { return 32; } + function isStatic(ty: Proxy>) returns (bool) { return false; } } // A dynamic array is encoded head-first as a 32-byte offset into the tail, so // its head is one word and it is never static (matching DynArray above). This -// covers `array(t)` under any location qualifier via the `calldata(ty)` / -// `memory(ty)` ABIAttribs bridges. -forall t . instance array(t):ABIAttribs { - function headSize(ty : Proxy(array(t))) -> word { return 32; } - function isStatic(ty : Proxy(array(t))) -> bool { return false; } -} -instance string:ABIAttribs { - function headSize(ty: Proxy(string)) -> word { return 32; } - function isStatic(ty : Proxy(string)) -> bool { return false; } -} -// bytes is dynamic, exactly like string — without this instance it falls to the -// default (isStatic = true), which wrongly marks memory(bytes) (and any ADT +// covers `array` under any location qualifier via the `calldata` / +// `memory` ABIAttribs bridges. +impl ABIAttribs> { + function headSize(ty: Proxy>) returns (word) { return 32; } + function isStatic(ty: Proxy>) returns (bool) { return false; } +} +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return false; } +} +// bytes is dynamic, exactly like string — without this impl it falls to the +// default (isStatic = true), which wrongly marks memory (and any ADT // carrying it) static, so calldata arrays/sums take the inline decode path over // what is really an offset-referenced value. -instance bytes:ABIAttribs { - function headSize(ty: Proxy(bytes)) -> word { return 32; } - function isStatic(ty : Proxy(bytes)) -> bool { return false; } +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return false; } } // computes the attribs for a pair of two types that implement attribs -forall a b . a:ABIAttribs, b:ABIAttribs => instance (a,b):ABIAttribs { - function headSize(ty : Proxy((a,b))) -> word { - let pa : Proxy(a); - let pb : Proxy(b); +impl ABIAttribs<(a, b)> where a: ABIAttribs, b: ABIAttribs { + function headSize(ty: Proxy<(a, b)>) returns (word) { + let pa : Proxy; + let pb : Proxy; let sza = ABIAttribs.headSize(pa); let szb = ABIAttribs.headSize(pb); return sza + szb; } - function isStatic(ty : Proxy((a,b))) -> bool { - let pa : Proxy(a); - let pb : Proxy(b); + function isStatic(ty: Proxy<(a, b)>) returns (bool) { + let pa : Proxy; + let pb : Proxy; return and(ABIAttribs.isStatic(pa), ABIAttribs.isStatic(pb)); } } // if an abi tuple contains dynamic elems we store it in the tail, otherwise we // treat it the same as a series of nested pairs -forall tuple . tuple:ABIAttribs => instance ABITuple(tuple):ABIAttribs { - function headSize(ty : Proxy(ABITuple(tuple))) -> word { - let px : Proxy(tuple); - match ABIAttribs.isStatic(px) { - | true => return ABIAttribs.headSize(px); - | false => return 32; - } +impl ABIAttribs> where tuple: ABIAttribs { + function headSize(ty: Proxy>) returns (word) { + let px : Proxy; + match (ABIAttribs.isStatic(px)) { +case true { +return ABIAttribs.headSize(px); +} +case false { +return 32; +} +} } - function isStatic(ty : Proxy(ABITuple(tuple))) -> bool { - let px : Proxy(tuple); + function isStatic(ty: Proxy>) returns (bool) { + let px : Proxy; return ABIAttribs.isStatic(px); } } // for pointer types we fetch the attribs of the pointed to type, not the pointer itself -forall ty . ty:ABIAttribs => instance memory(ty):ABIAttribs { - function headSize(p : Proxy(memory(ty))) -> word { - let px : Proxy(ty); +impl ABIAttribs> where ty: ABIAttribs { + function headSize(p: Proxy>) returns (word) { + let px : Proxy; return ABIAttribs.headSize(px); } - function isStatic(p : Proxy(memory(ty))) -> bool { - let px : Proxy(ty); + function isStatic(p: Proxy>) returns (bool) { + let px : Proxy; return ABIAttribs.isStatic(px); } } -forall ty . ty:ABIAttribs => instance calldata(ty):ABIAttribs { - function headSize(p : Proxy(calldata(ty))) -> word { - let px : Proxy(ty); +impl ABIAttribs> where ty: ABIAttribs { + function headSize(p: Proxy>) returns (word) { + let px : Proxy; return ABIAttribs.headSize(px); } - function isStatic(ty : Proxy(calldata(ty))) -> bool { - let px : Proxy(ty); + function isStatic(ty: Proxy>) returns (bool) { + let px : Proxy; return ABIAttribs.isStatic(px); } } @@ -1461,74 +1476,74 @@ forall ty . ty:ABIAttribs => instance calldata(ty):ABIAttribs { // TODO: make these generic over the location being written to (i.e. memory or returndata) // top level encoding function. -// abi encodes an instance of `ty` and returns a pointer to the result -forall ty . ty:ABIAttribs, ty:ABIEncode => function abi_encode(val : ty) -> memory(bytes) { +// ABI-encodes a `ty` value and returns a pointer to the result. +function abi_encode(val: ty) returns (memory) where ty: ABIAttribs, ty: ABIEncode { let ret = get_free_memory(); let start = ret + 32; - let tail = ABIEncode.encodeInto(val, start, 0, start + ABIAttribs.headSize(Proxy : Proxy(ty))); + let tail = ABIEncode.encodeInto(val, start, 0, start + ABIAttribs.headSize(@ty)); mstore(ret, tail - start); set_free_memory(tail); return memory(ret); } // types that can be abi encoded -forall self . class self:ABIEncode { - // abi encodes an instance of self into a memory region starting at basePtr +trait ABIEncode { + // ABI-encodes a `self` value into a memory region starting at basePtr. // offset gives the offset in memory from basePtr to the first empty byte of the head // tail gives the index in memory of the first empty byte of the tail - function encodeInto(x:self, basePtr:word, offset:word, tail:word) -> word /* newTail */; + function encodeInto(x: self, basePtr: word, offset: word, tail: word) returns (word) ; } -instance uint256:ABIEncode { +impl ABIEncode { // a unit256 is written directly into the head - function encodeInto(x:uint256, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: uint256, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance address:ABIEncode { +impl ABIEncode
{ // an address is written directly into the head (into a full 32-byte slot) - function encodeInto(x:address, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: address, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance bytes32:ABIEncode { +impl ABIEncode { // a bytes32 is written directly into the head - function encodeInto(x:bytes32, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: bytes32, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance bytes4:ABIEncode { +impl ABIEncode { // bytes4's word rep is right-aligned (e.g. `bytes4(shr(224, h))`), // so it is written directly into the head like bytes32 - function encodeInto(x:bytes4, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: bytes4, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance bool:ABIEncode { - function encodeInto(x:bool, basePtr:word, offset:word, tail:word) -> word { +impl ABIEncode { + function encodeInto(x: bool, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = frombool(x); mstore(basePtr + offset, repx); return tail; } } -function round_up_to_mul_of_32(value:word) -> word { +function round_up_to_mul_of_32(value: word) returns (word) { return (value + 31) & ~31; } -function encodeIntoFromBytesLike(srcPtr:word, basePtr:word, offset:word, tail:word) -> word { +function encodeIntoFromBytesLike(srcPtr: word, basePtr: word, offset: word, tail: word) returns (word) { let length = mload(srcPtr); let total = length + 32; mstore(basePtr + offset, tail - basePtr); @@ -1538,14 +1553,14 @@ function encodeIntoFromBytesLike(srcPtr:word, basePtr:word, offset:word, tail:wo return tail + rounded; } -instance memory(string):ABIEncode { - function encodeInto(x:memory(string), basePtr:word, offset:word, tail:word) -> word { +impl ABIEncode> { + function encodeInto(x: memory, basePtr: word, offset: word, tail: word) returns (word) { return encodeIntoFromBytesLike(Typedef.rep(x), basePtr, offset, tail); } } -instance memory(bytes):ABIEncode { - function encodeInto(x:memory(bytes), basePtr:word, offset:word, tail:word) -> word { +impl ABIEncode> { + function encodeInto(x: memory, basePtr: word, offset: word, tail: word) returns (word) { return encodeIntoFromBytesLike(Typedef.rep(x), basePtr, offset, tail); } } @@ -1553,11 +1568,10 @@ instance memory(bytes):ABIEncode { // ABI encoding for a memory dynamic array whose elements fit in a single word. // Assumes memory layout `[ length | elem_0 | elem_1 | ... ]`, which matches the // on-the-wire tail of `t[]` so the body can be `mcopy`d verbatim. -// `memory(DynArray(t)):ABIAttribs` is already derivable from the generic -// `memory(ty):ABIAttribs` + `DynArray(t):ABIAttribs` instances above. -forall t . t:Typedef(word) => -instance memory(DynArray(t)):ABIEncode { - function encodeInto(x:memory(DynArray(t)), basePtr:word, offset:word, tail:word) -> word { +// `memory>: ABIAttribs` is already derivable from the generic +// `memory: ABIAttribs` + `DynArray: ABIAttribs` impls above. +impl ABIEncode>> where t: Typedef { + function encodeInto(x: memory>, basePtr: word, offset: word, tail: word) returns (word) { let srcPtr : word = Typedef.rep(x); let len : word = mload(srcPtr); let totalBytes : word = (len + 1) * 32; @@ -1574,114 +1588,123 @@ instance memory(DynArray(t)):ABIEncode { } } -instance ():ABIEncode { +impl ABIEncode<()> { // a unit256 is written directly into the head - function encodeInto(x:(), basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: (), basePtr: word, offset: word, tail: word) returns (word) { return tail; } } // abi encoding for a pair of two encodable types -forall a b . a:ABIAttribs, a:ABIEncode, b:ABIEncode => instance (a,b):ABIEncode { - function encodeInto(x: (a,b), basePtr: word, offset: word, tail: word) -> word { - match x { - | (l,r) => - let newTail = ABIEncode.encodeInto(l, basePtr, offset, tail); - let pa : Proxy(a); +impl ABIEncode<(a, b)> where a: ABIAttribs, a: ABIEncode, b: ABIEncode { + function encodeInto(x: (a, b), basePtr: word, offset: word, tail: word) returns (word) { + match (x) { +case (l,r) { +let newTail = ABIEncode.encodeInto(l, basePtr, offset, tail); + let pa : Proxy; let a_sz = ABIAttribs.headSize(pa); return ABIEncode.encodeInto(r, basePtr, offset + a_sz, newTail); - } +} +} } } // abi encoding for an ABITuple of encodable types // TODO: is this correct? -forall tuple . tuple:ABIEncode, tuple:ABIAttribs => instance ABITuple(tuple):ABIEncode { - function encodeInto(x:ABITuple(tuple), basePtr:word, offset:word, tail:word) -> word { - let prx : Proxy(tuple); - match ABIAttribs.isStatic(prx) { - // if the tuple contains only static elements then we encode it in the head - | true => return ABIEncode.encodeInto(Typedef.rep(x), basePtr, offset, tail); +impl ABIEncode> where tuple: ABIEncode, tuple: ABIAttribs { + function encodeInto(x: ABITuple, basePtr: word, offset: word, tail: word) returns (word) { + let prx : Proxy; + match (ABIAttribs.isStatic(prx)) { +// if the tuple contains only static elements then we encode it in the head +case true { +return ABIEncode.encodeInto(Typedef.rep(x), basePtr, offset, tail); // if the tuple contains dynamically sized elements then we store a // pointer in the head, and encode the tuple into the tail - | false => - // store the length of the head in basePtr +} +case false { +// store the length of the head in basePtr mstore(basePtr, tail - basePtr); // encode the underlying tuple into the tail - let headSize = ABIAttribs.headSize(Proxy : Proxy(tuple)); + let headSize = ABIAttribs.headSize(@tuple); basePtr = tail; tail += headSize; return ABIEncode.encodeInto(Typedef.rep(x), basePtr, 0, tail); - } +} +} } } // --- ABI Decoding --- // Top level decoding function. -// abi decodes an instance of `decodable` into a `ty` -forall decodable reader ty decoded . decodable:HasWordReader(reader), ABIDecoder(ty, reader):ABIDecode(decoded) => -function abi_decode(decodable:decodable, pty:Proxy(ty), prdr:Proxy(reader)) -> decoded { - let decoder : ABIDecoder(ty, reader) = ABIDecoder(HasWordReader.getWordReader(decodable)); +// ABI-decodes a `decodable` value into a `ty` value. +function abi_decode(decodable: decodable, pty: Proxy, prdr: Proxy) returns (decoded) where decodable: HasWordReader, ABIDecoder: ABIDecode { + let decoder : ABIDecoder = ABIDecoder(HasWordReader.getWordReader(decodable)); return ABIDecode.decode(decoder, 0); } -forall decoder decoded . class decoder:ABIDecode(decoded) { - function decode(ptr:decoder, currentHeadOffset:word) -> decoded; +trait ABIDecode { + function decode(ptr: decoder, currentHeadOffset: word) returns (decoded) ; } // An ABI Decoder for `ty` from `reader` // This lets us abstract over memory and calldata when decoding -data ABIDecoder(ty, reader) = ABIDecoder(reader); +enum ABIDecoder { ABIDecoder(reader) } // If `reader` is a `WordReader` then so is our `ABIDecoder` -forall ty reader . reader:WordReader => instance ABIDecoder(ty, reader):WordReader { - function read(decoder:ABIDecoder(ty, reader)) -> word { - match decoder { - | ABIDecoder(ptr) => return WordReader.read(ptr); - } +impl WordReader> where reader: WordReader { + function read(decoder: ABIDecoder) returns (word) { + match (decoder) { +case ABIDecoder(ptr) { +return WordReader.read(ptr); +} +} } - function advance(decoder:ABIDecoder(ty, reader), offset:word) -> ABIDecoder(ty, reader) { - match decoder { - | ABIDecoder(ptr) => return ABIDecoder(WordReader.advance(ptr, offset)); - } + function advance(decoder: ABIDecoder, offset: word) returns (ABIDecoder) { + match (decoder) { +case ABIDecoder(ptr) { +return ABIDecoder(WordReader.advance(ptr, offset)); +} +} } - function copyToMem(decoder:ABIDecoder(ty, reader), dst:word, cnt: word) -> () { - match decoder { - | ABIDecoder(ptr) => WordReader.copyToMem(ptr, dst, cnt); - } + function copyToMem(decoder: ABIDecoder, dst: word, cnt: word) { + match (decoder) { +case ABIDecoder(ptr) { +WordReader.copyToMem(ptr, dst, cnt); +} +} } } // ABI Decoding for uint256 -forall reader . reader:WordReader => instance ABIDecoder(uint256, reader):ABIDecode(uint256) { - function decode(ptr:ABIDecoder(uint256, reader), currentHeadOffset:word) -> uint256 { - return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) : uint256; +impl ABIDecode, uint256> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (uint256) { + return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) ; } } // ABI Decoding for bytes32 -forall reader . reader:WordReader => instance ABIDecoder(bytes32, reader):ABIDecode(bytes32) { - function decode(ptr:ABIDecoder(bytes32, reader), currentHeadOffset:word) -> bytes32 { - return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) : bytes32; +impl ABIDecode, bytes32> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (bytes32) { + return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) ; } } // ABI Decoding for bytes4 -forall reader . reader:WordReader => instance ABIDecoder(bytes4, reader):ABIDecode(bytes4) { - function decode(ptr:ABIDecoder(bytes4, reader), currentHeadOffset:word) -> bytes4 { - return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) : bytes4; +impl ABIDecode, bytes4> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (bytes4) { + return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) ; } } // ABI Decoding for bool // bool is a builtin (not a Typedef(word)), so it round-trips through word via -// tobool, mirroring the bool:ABIEncode instance which uses frombool. -forall reader . reader:WordReader => instance ABIDecoder(bool, reader):ABIDecode(bool) { - function decode(ptr:ABIDecoder(bool, reader), currentHeadOffset:word) -> bool { +// tobool, mirroring the `bool: ABIEncode` impl which uses frombool. +impl ABIDecode, bool> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (bool) { let v = WordReader.read(WordReader.advance(ptr, currentHeadOffset)); require(v <= 1, Error(0x0557dbbf)); // DirtyHigherBitsForBool() return tobool(v); @@ -1689,23 +1712,22 @@ forall reader . reader:WordReader => instance ABIDecoder(bool, reader):ABIDecode } // ABI Decoding for address -forall reader . reader:WordReader => instance ABIDecoder(address, reader):ABIDecode(address) { - function decode(ptr:ABIDecoder(address, reader), currentHeadOffset:word) -> address { +impl ABIDecode, address> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (address) { let raw = WordReader.read(WordReader.advance(ptr, currentHeadOffset)); require(shr(160, raw) == 0, Error(0x7cc04fa7)); // DirtyHigherBitsForAddress() - return Typedef.abs(raw) : address; + return Typedef.abs(raw) ; } } -forall reader . reader:WordReader => instance ABIDecoder((), reader):ABIDecode(()) { - function decode(ptr:ABIDecoder((), reader), currentHeadOffset:word) -> () { +impl ABIDecode, ()> where reader: WordReader { + function decode(ptr: ABIDecoder<(), reader>, currentHeadOffset: word) { return (); } } // ABI decoding for bytes/strings (only in memory) -forall a ptrtype reader. reader:WordReader => -function decodeBytesLike(ptr:ABIDecoder(memory(a), reader), currentHeadOffset:word) -> memory(a) { +function decodeBytesLike(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (memory) where reader: WordReader { let tmp:word; let headRdr = WordReader.advance(ptr, currentHeadOffset); let tailPtr : word = WordReader.read(headRdr); @@ -1721,82 +1743,78 @@ function decodeBytesLike(ptr:ABIDecoder(memory(a), reader), currentHeadOffset:wo } // ABI decoding for strings (only in memory) -forall reader. reader : WordReader => -instance ABIDecoder(memory(string), reader):ABIDecode(memory(string)) -{ - function decode(ptr:ABIDecoder(memory(string), reader), currentHeadOffset:word) -> memory(string) { +impl ABIDecode, reader>, memory> where reader: WordReader { + function decode(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (memory) { return decodeBytesLike(ptr, currentHeadOffset); } } // ABI decoding for bytes (only in memory) -forall reader. reader : WordReader => -instance ABIDecoder(memory(bytes), reader):ABIDecode(memory(bytes)) -{ - function decode(ptr:ABIDecoder(memory(bytes), reader), currentHeadOffset:word) -> memory(bytes) { +impl ABIDecode, reader>, memory> where reader: WordReader { + function decode(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (memory) { return decodeBytesLike(ptr, currentHeadOffset); } } // ABI decoding for a pair of decodable values // FAIL: Coverage -forall a b a_decoded b_decoded reader . reader:WordReader, ABIDecoder(b,reader):ABIDecode(b_decoded), ABIDecoder(a,reader):ABIDecode(a_decoded), a:ABIAttribs => instance ABIDecoder((a,b), reader):ABIDecode((a_decoded,b_decoded)) -{ - function decode(ptr:ABIDecoder((a,b), reader), currentHeadOffset:word) -> (a_decoded, b_decoded) { - match ptr { - | ABIDecoder(rdr) => - let prx : Proxy(a); - let decoder_a : ABIDecoder(a, reader) = ABIDecoder(rdr); - let decoder_b : ABIDecoder(b, reader) = ABIDecoder(rdr); +impl ABIDecode, (a_decoded, b_decoded)> where reader: WordReader, ABIDecoder: ABIDecode, ABIDecoder: ABIDecode, a: ABIAttribs { + function decode(ptr: ABIDecoder<(a, b), reader>, currentHeadOffset: word) returns (a_decoded, b_decoded) { + match (ptr) { +case ABIDecoder(rdr) { +let prx : Proxy; + let decoder_a : ABIDecoder = ABIDecoder(rdr); + let decoder_b : ABIDecoder = ABIDecoder(rdr); let a_val : a_decoded = ABIDecode.decode(decoder_a, currentHeadOffset); let b_val : b_decoded = ABIDecode.decode(decoder_b, currentHeadOffset + ABIAttribs.headSize(prx)); return (a_val, b_val); - } +} +} } } -forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_decoded), tuple:ABIAttribs => - instance ABIDecoder(ABITuple(tuple), reader):ABIDecode(tuple_decoded) -{ - function decode(ptr:ABIDecoder(ABITuple(tuple), reader), currentHeadOffset:word) -> tuple_decoded { - let prx : Proxy(tuple); - match ABIAttribs.isStatic(prx) { - | true => return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); - | false => - let tailPtr = WordReader.read(ptr); +impl ABIDecode, reader>, tuple_decoded> where reader: WordReader, tuple: ABIDecode, tuple: ABIAttribs { + function decode(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (tuple_decoded) { + let prx : Proxy; + match (ABIAttribs.isStatic(prx)) { +case true { +return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); +} +case false { +let tailPtr = WordReader.read(ptr); return ABIDecode.decode(WordReader.advance(ptr, tailPtr), 0); - } +} +} } } -forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_decoded), tuple:ABIAttribs => - instance ABIDecoder(memory(ABITuple(tuple)), reader):ABIDecode(memory(tuple_decoded)) -{ - function decode(ptr:ABIDecoder(memory(ABITuple(tuple)), reader), currentHeadOffset:word) -> memory(tuple_decoded) { - let prx : Proxy(tuple); - match ABIAttribs.isStatic(prx) { - | true => return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); - | false => - let tailPtr = WordReader.read(ptr); +impl ABIDecode>, reader>, memory> where reader: WordReader, tuple: ABIDecode, tuple: ABIAttribs { + function decode(ptr: ABIDecoder>, reader>, currentHeadOffset: word) returns (memory) { + let prx : Proxy; + match (ABIAttribs.isStatic(prx)) { +case true { +return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); +} +case false { +let tailPtr = WordReader.read(ptr); return ABIDecode.decode(WordReader.advance(ptr, tailPtr), 0); - } +} +} } } -forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReader, ABIDecoder(baseType, reader):ABIDecode(baseType_decoded) => - instance ABIDecoder(memory(DynArray(baseType)), reader):ABIDecode(memory(DynArray(baseType_decoded))) -{ - function decode(ptr:ABIDecoder(memory(DynArray(baseType)), reader), currentHeadOffset:word) -> memory(DynArray(baseType_decoded)) { +impl ABIDecode>, reader>, memory>> where baseType: ABIAttribs, reader: WordReader, ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder>, reader>, currentHeadOffset: word) returns (memory>) { let arrayPtr = WordReader.advance(ptr, currentHeadOffset); let length = WordReader.read(arrayPtr); // this trigger a missing typedef constraint // let elementPtr:ABIDecoder(baseType, reader) = Typedef.abs(WordReader.advance(arrayPtr, 32)); arrayPtr = WordReader.advance(arrayPtr, 32); - let prx : Proxy(baseType_decoded); - let result : memory(DynArray(baseType_decoded)) = allocateDynamicArray(prx, length); + let prx : Proxy; + let result : memory> = allocateDynamicArray(prx, length); let offset : word = 0; - let prx : Proxy(baseType); + let prx : Proxy; let elementHeadSize : word = ABIAttribs.headSize(prx); // TODO: surface level loops @@ -1810,18 +1828,16 @@ forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReade } } -forall ty reader. -function getReader(d:ABIDecoder(ty, reader)) -> reader { - match d { - | ABIDecoder(rdr) => return rdr; - } +function getReader(d: ABIDecoder) returns (reader) { + match (d) { +case ABIDecoder(rdr) { +return rdr; +} +} } -forall baseType baseType_decoded . ABIDecoder(baseType, CalldataWordReader):ABIDecode(baseType_decoded), - baseType : WordReader => - instance ABIDecoder(calldata(DynArray(baseType)), CalldataWordReader):ABIDecode(calldata(DynArray(baseType_decoded))) - { - function decode(ptr:ABIDecoder(calldata(DynArray(baseType)), CalldataWordReader), currentHeadOffset:word) -> calldata(DynArray(baseType_decoded)) { +impl ABIDecode>, CalldataWordReader>, calldata>> where ABIDecoder: ABIDecode, baseType: WordReader { + function decode(ptr: ABIDecoder>, CalldataWordReader>, currentHeadOffset: word) returns (calldata>) { let newptr = WordReader.advance(ptr, currentHeadOffset); let reader: CalldataWordReader = getReader(newptr); let addr: word = Typedef.rep(reader); @@ -1835,12 +1851,9 @@ forall baseType baseType_decoded . ABIDecoder(baseType, CalldataWordReader):ABID // to that length word, so the elements are left in calldata and decoded on // demand (abiArrayLength / abiArrayGet). Because nothing is materialised here, // this works for any decodable element type — including multi-word ADTs such as -// a sum(...) — which the word-per-slot memory(DynArray(...)) path cannot hold. -forall baseType baseType_decoded . - ABIDecoder(baseType, CalldataWordReader):ABIDecode(baseType_decoded) => - instance ABIDecoder(calldata(array(baseType)), CalldataWordReader):ABIDecode(calldata(array(baseType_decoded))) - { - function decode(ptr:ABIDecoder(calldata(array(baseType)), CalldataWordReader), currentHeadOffset:word) -> calldata(array(baseType_decoded)) { +// a `sum<...>` — which the word-per-slot `memory>` path cannot hold. +impl ABIDecode>, CalldataWordReader>, calldata>> where ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder>, CalldataWordReader>, currentHeadOffset: word) returns (calldata>) { let headRdr = WordReader.advance(ptr, currentHeadOffset); let dataOffset : word = WordReader.read(headRdr); let dataRdr = WordReader.advance(ptr, dataOffset); @@ -1851,7 +1864,7 @@ forall baseType baseType_decoded . } // Length of a decoded calldata array: the handle points at the length word. -forall t . function abiArrayLength(a : calldata(array(t))) -> uint256 { +function abiArrayLength(a: calldata>) returns (uint256) { let rdr : CalldataWordReader = CalldataWordReader(Typedef.rep(a)); return uint256(WordReader.read(rdr)); } @@ -1871,32 +1884,31 @@ forall t . function abiArrayLength(a : calldata(array(t))) -> uint256 { // head offset; the element's own dynamic decoder follows that offset. This // is uniform across element kinds: a dynamic sum follows it and rebases to // the element start, a bare bytes/string leaf follows it to its length word. -forall t t_decoded . - t : ABIAttribs, - ABIDecoder(t, CalldataWordReader):ABIDecode(t_decoded) => -function abiArrayGet(a : calldata(array(t)), i : uint256) -> t_decoded { +function abiArrayGet(a: calldata>, i: uint256) returns (t_decoded) where t: ABIAttribs, ABIDecoder: ABIDecode { // Bounds check: valid indices are [0, length); i == length is already past // the last element, so reject i >= length (mirrors the storage-array guard). require(i < abiArrayLength(a), Error(0x7f52b2bf)); // ArrayOutOfBounds() let base : word = Typedef.rep(a); let elemRegion : word = base + 32; - let prx : Proxy(t); + let prx : Proxy; let idx : word = Typedef.rep(i); - match ABIAttribs.isStatic(prx) { - | true => - let elemRdr : CalldataWordReader = CalldataWordReader(elemRegion); - let dec : ABIDecoder(t, CalldataWordReader) = ABIDecoder(elemRdr); + match (ABIAttribs.isStatic(prx)) { +case true { +let elemRdr : CalldataWordReader = CalldataWordReader(elemRegion); + let dec : ABIDecoder = ABIDecoder(elemRdr); return ABIDecode.decode(dec, idx * ABIAttribs.headSize(prx)); - | false => - // Dynamic elements: the region is a table of 32-byte offsets (relative +} +case false { +// Dynamic elements: the region is a table of 32-byte offsets (relative // to the region base), one per element. Hand the element decoder the // region base and element i's slot as its head offset; the element's own // (dynamic) decoder follows that offset — uniformly for a dynamic sum - // element or a bare bytes/string element (calldata(array(bytes))). + // element or a bare bytes/string element (`calldata>`). let elemRdr : CalldataWordReader = CalldataWordReader(elemRegion); - let dec : ABIDecoder(t, CalldataWordReader) = ABIDecoder(elemRdr); + let dec : ABIDecoder = ABIDecoder(elemRdr); return ABIDecode.decode(dec, idx * 32); - } +} +} } @@ -1919,149 +1931,145 @@ pragma no-bounded-variable-condition LVA, RVA; // Zeroes the storage slots in [start, endSlot). Mirrors solc's // clear_storage_range, used when a dynamic array shrinks so that regrowing it // cannot resurrect the old elements. -function clearStorageRange(start: word, endSlot: word) -> () { +function clearStorageRange(start: word, endSlot: word) { for (; start < endSlot; start += 1) { sstore(start, 0); } } -forall self. -class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -forall self. -default instance self:StorageSize { - function size(x:Proxy(self)) -> word { +default impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance ():StorageSize { - function size(x:Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } /* -instance uint:StorageSize { - function size(x:Proxy(uint)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } */ -instance uint256:StorageSize { - function size(x:Proxy(uint256)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance bytes32:StorageSize { - function size(x:Proxy(bytes32)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance address:StorageSize { - function size(x:Proxy(address)) -> word { +impl StorageSize
{ + function size(x: Proxy
) returns (word) { return 1; } } -instance string:StorageSize { - function size(x:Proxy(string)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance memory(string):StorageSize { - function size(x:Proxy(memory(string))) -> word { +impl StorageSize> { + function size(x: Proxy>) returns (word) { return 1; } } -instance bytes:StorageSize { - function size(x:Proxy(bytes)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance memory(bytes):StorageSize { - function size(x:Proxy(memory(bytes))) -> word { +impl StorageSize> { + function size(x: Proxy>) returns (word) { return 1; } } -forall a b. a:StorageSize, b:StorageSize => instance (a,b):StorageSize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = StorageSize.size(Proxy:Proxy(a)); - let b_sz:word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = StorageSize.size(@a); + let b_sz:word = StorageSize.size(@b); return a_sz + b_sz; } } -forall self. -class self:StorageType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait StorageType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } // How to copy one element of type self from one storage slot to another. -// Whole-array assignment (a = b) copies element by element through this class, +// Whole-array assignment (a = b) copies element by element through this trait, // the way solc's copy_array_to_storage calls the element's own copy routine. // The constraint lives on the *element* type, so it can gate CanStore.store for -// storage(array(self)) without also gating CanStore.load, which must stay +// storage> without also gating CanStore.load, which must stay // unconstrained, a field read has to yield the array's storage reference. -// Instances live below, next to the CanStore instances the dynamic ones rely on. -forall self. -class self:StorageCopy { - function copySlot(dst:storage(self), src:storage(self)) -> (); +// Impls live below, next to the CanStore impls the dynamic ones rely on. +trait StorageCopy { + function copySlot(dst: storage, src: storage) ; } -instance word:StorageType { - function load(ptr:word) -> word { +impl StorageType { + function load(ptr: word) returns (word) { return sload(ptr); } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { sstore(ptr, value); } } -instance uint256:StorageType { - function load(ptr:word) -> uint256 { return uint256(StorageType.load(ptr):word); } - function store(ptr:word, value:uint256) -> () { StorageType.store(ptr, Typedef.rep(value):word); } +impl StorageType { + function load(ptr: word) returns (uint256) { return uint256(StorageType.load(ptr)); } + function store(ptr: word, value: uint256) { StorageType.store(ptr, Typedef.rep(value)); } } -instance bytes32:StorageType { - function load(ptr:word) -> bytes32 { return bytes32(StorageType.load(ptr):word); } - function store(ptr:word, value:bytes32) -> () { StorageType.store(ptr, Typedef.rep(value):word); } +impl StorageType { + function load(ptr: word) returns (bytes32) { return bytes32(StorageType.load(ptr)); } + function store(ptr: word, value: bytes32) { StorageType.store(ptr, Typedef.rep(value)); } } -instance address:StorageType { - function load(ptr:word) -> address { return address(StorageType.load(ptr):word); } - function store(ptr:word, value:address) -> () { StorageType.store(ptr, Typedef.rep(value):word); } +impl StorageType
{ + function load(ptr: word) returns (address) { return address(StorageType.load(ptr)); } + function store(ptr: word, value: address) { StorageType.store(ptr, Typedef.rep(value)); } } // -- structure fields (including contract fields) -forall self fieldType offsetType. -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, fieldtype, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field fieldType storageType offset . -function memberAccessBase(x:MemberAccessProxy(a, field, fieldType, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessBase(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } @@ -2069,141 +2077,135 @@ function memberAccessBase(x:MemberAccessProxy(a, field, fieldType, offset)) -> // Contract field access // ------------------------------------------------------------------ -forall cxt fieldSelector loadType offsetType storageType -. StructField(ContractStorage(cxt), fieldSelector) :CStructField(storage(storageType), offsetType) -, offsetType : StorageSize -, storage(storageType): CanStore(loadType) -=> instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType) : LVA (storage(storageType)) { - function acc (x : MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType)) -> storage(storageType) { - let offset : word = StorageSize.size(Proxy : Proxy(offsetType)) ; - return storage(offset):storage(storageType); +impl LVA, fieldSelector, loadType, offsetType>, storage> where StructField, fieldSelector>: CStructField, offsetType>, offsetType: StorageSize, storage: CanStore { + function acc(x: MemberAccessProxy, fieldSelector, loadType, offsetType>) returns (storage) { + let offset : word = StorageSize.size(@offsetType) ; + let result : storage = storage(offset); + return result; } } -forall cxt fieldSelector loadType offsetType storageType - . StructField(ContractStorage(cxt), fieldSelector):CStructField(storage(storageType), offsetType) - , storage(storageType):CanStore(loadType) - , offsetType:StorageSize - => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType):RVA(loadType) { - function acc(x:MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType)) -> loadType { - let offset:word = StorageSize.size(Proxy:Proxy(offsetType)); - return CanStore.load(storage(offset):storage(storageType)):loadType; +impl RVA, fieldSelector, loadType, offsetType>, loadType> where StructField, fieldSelector>: CStructField, offsetType>, storage: CanStore, offsetType: StorageSize { + function acc(x: MemberAccessProxy, fieldSelector, loadType, offsetType>) returns (loadType) { + let offset:word = StorageSize.size(@offsetType); + let slot : storage = storage(offset); + return CanStore.load(slot); } } // TODO: structures other than contract context /* -forall structType fieldSelector fieldType storageType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType):LVA(storage(fieldType)) { - function acc(x:MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType)) -> storage(fieldType) { +impl + LVA, fieldSelector, fieldType, offsetType>, storage> + where StructField: CStructField, + offsetType: StorageSize { + function acc(x: MemberAccessProxy, fieldSelector, fieldType, offsetType>) returns (storage) { let ptr:word = Typedef.rep(memberAccessBase(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); + let size:word = StorageSize.size(@offsetType); return storage(ptr + size); } } -forall structType fieldSelector fieldType storageType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - , fieldType:StorageType - => instance MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType):RVA(fieldType) { - function acc(x:MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType)) -> fieldType { +impl + RVA, fieldSelector, fieldType, offsetType>, fieldType> + where StructField: CStructField, + offsetType: StorageSize, + fieldType: StorageType { + function acc(x: MemberAccessProxy, fieldSelector, fieldType, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessBase(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); - return CanStore.load(ptr + size); + let size:word = StorageSize.size(@offsetType); + let field: storage = storage(ptr + size); + return CanStore.load(field); } } */ -data ContractStorage(cxt) = ContractStorage(cxt); +enum ContractStorage { ContractStorage(cxt) } -forall member index . instance mapping(index, member):Typedef(word) { - function rep(x:mapping(index, member)) -> word { - match x { - | mapping(y) => return y; - } +impl Typedef member), word> { + function rep(x: mapping(index => member)) returns (word) { + match (x) { +case mapping(y) { +return y; +} +} } - function abs(x:word) -> mapping(index,member) { + function abs(x: word) returns (mapping(index => member)) { return mapping(x); } } // cf https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays -forall index member . -instance mapping(index, member):StorageSize { - function size(x:Proxy(mapping(index, member))) -> word { +impl StorageSize member)> { + function size(x: Proxy member)>) returns (word) { return 1; } } -forall member . instance array(member):Typedef(word) { - function rep(x:array(member)) -> word { - match x { - | array(y) => return y; - } +impl Typedef, word> { + function rep(x: array) returns (word) { + match (x) { +case array(y) { +return y; +} +} } - function abs(x:word) -> array(member) { + function abs(x: word) returns (array) { return array(x); } } // cf https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays // the slot itself stores the array length; elements live at keccak256(slot) + i -forall member . -instance array(member):StorageSize { - function size(x:Proxy(array(member))) -> word { +impl StorageSize> { + function size(x: Proxy>) returns (word) { return 1; } } -forall self . class self:Length { - function length(arr:self) -> uint256; +trait Length { + function length(arr: self) returns (uint256) ; } // Dynamic storage arrays carry their length at the slot itself (matching the // Solidity convention) while elements live at keccak256(slot) + i. -forall self . class self:Array { - function setLength(arr:self, n:uint256) -> (); - function pop(arr:self) -> (); +trait Array { + function setLength(arr: self, n: uint256) ; + function pop(arr: self) ; } // push is split into its own MPTC so its element type only shows up where it // actually matters (the value being appended), without forcing `length`/ // `setLength`/`pop` to drag along an unconstrained `elem` parameter. -forall self elem . class self:ArrayPush(elem) { - function push(arr:self, val:elem) -> (); +trait ArrayPush { + function push(arr: self, val: elem) ; } -forall t . -instance storage(array(t)):Length { - function length(arr:storage(array(t))) -> uint256 { +impl Length>> { + function length(arr: storage>) returns (uint256) { return uint256(sload(Typedef.rep(arr))); } } // A lazily-decoded calldata array reports its length from the head length-word // of its handle (see abiArrayLength), so `arr.length()` resolves through the -// same Length class / UFCS as storage arrays. -forall t . -instance calldata(array(t)):Length { - function length(arr:calldata(array(t))) -> uint256 { +// same Length trait / UFCS as storage arrays. +impl Length>> { + function length(arr: calldata>) returns (uint256) { return abiArrayLength(arr); } } -forall t . -instance storage(array(t)):Array { +impl Array>> { // Shrinking clears the abandoned slots, matching solc's resize_array. // For string/bytes elements this zeroes the inline slot, which makes any // keccak-derived tail unreachable (reads are governed by the length word) but // does not reclaim it. - function setLength(arr:storage(array(t)), n:uint256) -> () { + function setLength(arr: storage>, n: uint256) { let slot : word = Typedef.rep(arr); let oldLen : word = sload(slot); let newLen : word = Typedef.rep(n); @@ -2214,7 +2216,7 @@ instance storage(array(t)):Array { sstore(slot, newLen); } // Zeroes the removed element before decrementing, as solc's array_pop does. - function pop(arr:storage(array(t))) -> () { + function pop(arr: storage>) { let slot : word = Typedef.rep(arr); let n : word = sload(slot); if (n == 0) { out_of_bounds(); } @@ -2224,138 +2226,129 @@ instance storage(array(t)):Array { } // The value pushed is whatever the element's storage reference can store, rather -// than the element tag type itself. That is what lets array(string) accept a -// memory(string), via storage(string):CanStore(memory(string)). For word-sized +// than the element tag type itself. That is what lets array accept a +// memory, via `storage: CanStore>`. For word-sized // elements v collapses to the element type and CanStore.store delegates to // StorageType.store, so the generated code is unchanged. -forall t v . storage(t):CanStore(v) => -instance storage(array(t)):ArrayPush(v) { - function push(arr:storage(array(t)), val:v) -> () { +impl ArrayPush>, v> where storage: CanStore { + function push(arr: storage>, val: v) { let slot : word = Typedef.rep(arr); let n : word = sload(slot); - CanStore.store(storage(hash1(slot) + n):storage(t), val); + let element : storage = storage(hash1(slot) + n); + CanStore.store(element, val); sstore(slot, n + 1); } } -forall self memberRefType. -class self:LVA(memberRefType) { - function acc(x:self) -> memberRefType; +trait LVA { + function acc(x: self) returns (memberRefType) ; } -forall self member. -class self:RVA(member) { - function acc(x:self) -> member; +trait RVA { + function acc(x: self) returns (member) ; } -forall a b. a:RVA(b) => -function rval(x:a) -> b { +function rval(x: a) returns (b) where a: RVA { return RVA.acc(x); } // TODO: consider merging CanStore and Assign -forall lhs rhs. -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -// a can store b; e.g. storage(string) : memory(string) -forall a b. -class a:CanStore(b) { - function store(r:a, v:b) -> (); - function load(r:a) -> b; +// `a` can store `b`; e.g. `storage: CanStore>`. +trait CanStore { + function store(r: a, v: b) ; + function load(r: a) returns (b) ; } -forall a b. a:CanStore(b) => -instance a:Assign(b) { - function assign(l:a, r:b) -> () { +impl Assign where a: CanStore { + function assign(l: a, r: b) { CanStore.store(l, r); } } /* -forall a. a:StorageType => -default instance a:CanStore(a) { - function store(l:storage(a), r:a) -> () { +default impl CanStore, a> where a: StorageType { + function store(l: storage, r: a) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(a)) -> a { + function load(l: storage) returns (a) { return StorageType.load(Typedef.rep(l)); } } */ - instance storage(word):CanStore(word) { - function store(l:storage(word), r:word) -> () { + impl CanStore, word> { + function store(l: storage, r: word) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(word)) -> word { + function load(l: storage) returns (word) { return StorageType.load(Typedef.rep(l)); } } - instance storage(uint256):CanStore(uint256) { - function store(l:storage(uint256), r:uint256) -> () { + impl CanStore, uint256> { + function store(l: storage, r: uint256) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(uint256)) -> uint256 { + function load(l: storage) returns (uint256) { return StorageType.load(Typedef.rep(l)); } } - instance storage(bytes32):CanStore(bytes32) { - function store(l:storage(bytes32), r:bytes32) -> () { + impl CanStore, bytes32> { + function store(l: storage, r: bytes32) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(bytes32)) -> bytes32 { + function load(l: storage) returns (bytes32) { return StorageType.load(Typedef.rep(l)); } } - instance storage(address):CanStore(address) { - function store(l:storage(address), r:address) -> () { + impl CanStore, address> { + function store(l: storage
, r: address) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(address)) -> address { + function load(l: storage
) returns (address) { return StorageType.load(Typedef.rep(l)); } } -// bool has no StorageType instance (it is a builtin, not a Typedef(word)), but it +// bool has no StorageType impl (it is a builtin, not a Typedef), but it // round-trips through word via frombool / tobool, so it can still be stored. -instance storage(bool):CanStore(bool) { - function store(l:storage(bool), r:bool) -> () { +impl CanStore, bool> { + function store(l: storage, r: bool) { StorageType.store(Typedef.rep(l), frombool(r)); } - function load(l:storage(bool)) -> bool { + function load(l: storage) returns (bool) { return tobool(StorageType.load(Typedef.rep(l))); } } -forall k v. - instance storage(mapping(k,v)):CanStore(storage(mapping(k,v))) { - function store(l:storage(mapping(k,v)), r:storage(mapping(k,v))) -> () { +impl CanStore v)>, storage v)>> { + function store(l: storage v)>, r: storage v)>) { // StorageType.store(Typedef.rep(l), r); unimplemented(); } - function load(l:storage(mapping(k,v))) -> storage(mapping(k,v)) { + function load(l: storage v)>) returns (storage v)>) { // "Loading" a storage mapping field yields its storage reference (the // slot); indexed access / method calls consume that reference directly. return l; } } -forall v. v:StorageCopy => - instance storage(array(v)):CanStore(storage(array(v))) { +impl CanStore>, storage>> where v: StorageCopy { // Whole-array assignment is a deep copy, as in Solidity: a = b resizes a // to b's length and then copies every // element. Assigning an array to itself is a no-op. A *local* bound to an // array field stays an alias, because a let is not an Assign.assign. - function store(l:storage(array(v)), r:storage(array(v))) -> () { + function store(l: storage>, r: storage>) { let dst : word = Typedef.rep(l); let src : word = Typedef.rep(r); if (dst != src) { @@ -2368,11 +2361,13 @@ forall v. v:StorageCopy => sstore(dst, newLen); let srcBase : word = hash1(src); for (let i = 0; i < newLen; i += 1) { - StorageCopy.copySlot(storage(dstBase + i):storage(v), storage(srcBase + i):storage(v)); + let dstSlot : storage = storage(dstBase + i); + let srcSlot : storage = storage(srcBase + i); + StorageCopy.copySlot(dstSlot, srcSlot); } } } - function load(l:storage(array(v))) -> storage(array(v)) { + function load(l: storage>) returns (storage>) { // "Loading" a storage array field yields its storage reference (the // slot). push / pop / length / arr[i] all consume that reference, so a // field read like `ArrayPush.push(members, x)` must return the slot, From ab3fd1d71b493e884cea7204916b85fb660bbbd6 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 066/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok std std.sol Co-authored-by: Codex --- .../tests/fixtures/corpus/ok/std/std.sol | 298 +++++++++--------- 1 file changed, 151 insertions(+), 147 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/std/std.sol b/crates/parser/tests/fixtures/corpus/ok/std/std.sol index 30da458b..dc16c75e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/std/std.sol +++ b/crates/parser/tests/fixtures/corpus/ok/std/std.sol @@ -2379,34 +2379,34 @@ impl CanStore>, storage>> where v: StorageCopy { // Assigning an array literal to a storage array field: `xs = [1,2,3]`. // // This is Solidity's memory -> storage array copy. It is a plain function, not -// a CanStore instance, on purpose: instance overlap is decided by the main type -// alone, so a second CanStore instance for storage(array(t)) would clash with +// a CanStore impl, on purpose: impl overlap is decided by the main type alone, +// so a second CanStore impl for storage> would clash with // the deep-copy one above. FieldAccess routes `field = ` here // instead of through Assign.assign. // // Array.setLength resizes and clears the abandoned tail, so old elements never // resurrect. The element types differ: `t` is the storage element tag and `v` // what a value of it looks like in memory (they coincide for word-sized -// elements; for array(string), t = string and v = memory(string)). -forall t v . storage(t):CanStore(v), v:Typedef(word) => -function storeArrayLit(dst : storage(array(t)), src : memory(DynArray(v))) -> () { +// elements; for array, t = string and v = memory). +function storeArrayLit(dst: storage>, src: memory>) where storage: CanStore, v: Typedef { let n : word = mload(Typedef.rep(src)); Array.setLength(dst, uint256(n)); let base : word = hash1(Typedef.rep(dst)); let i : word = 0; for (; i < n; i += 1) { - CanStore.store(storage(base + i) : storage(t), IndexAccess.get(src, uint256(i))); + let element : storage = storage(base + i); + CanStore.store(element, IndexAccess.get(src, uint256(i))); } } -instance storage(string):CanStore(memory(string)) { - function store(dst:storage(string), src:memory(string)) -> () { +impl CanStore, memory> { + function store(dst: storage, src: memory) { let srcPtr : word = Typedef.rep(src); let slot = Typedef.rep(dst); storeBytesFromMemory(slot, srcPtr); } - function load(src:storage(string)) -> memory(string) { + function load(src: storage) returns (memory) { let srcPtr : word = Typedef.rep(src); let dstPtr : word = get_free_memory(); let endPtr = loadBytesFromStorage(srcPtr, dstPtr); @@ -2417,14 +2417,14 @@ instance storage(string):CanStore(memory(string)) { // bytes share the same storage layout as string, so the same // storeBytesFromMemory / loadBytesFromStorage helpers apply. -instance storage(bytes):CanStore(memory(bytes)) { - function store(dst:storage(bytes), src:memory(bytes)) -> () { +impl CanStore, memory> { + function store(dst: storage, src: memory) { let srcPtr : word = Typedef.rep(src); let slot = Typedef.rep(dst); storeBytesFromMemory(slot, srcPtr); } - function load(src:storage(bytes)) -> memory(bytes) { + function load(src: storage) returns (memory) { let srcPtr : word = Typedef.rep(src); let dstPtr : word = get_free_memory(); let endPtr = loadBytesFromStorage(srcPtr, dstPtr); @@ -2436,23 +2436,23 @@ instance storage(bytes):CanStore(memory(bytes)) { // --- StorageCopy: per-element copy used by whole-array assignment --- // Word-sized elements are self-contained: the slot is the value. -instance word:StorageCopy { - function copySlot(dst:storage(word), src:storage(word)) -> () { +impl StorageCopy { + function copySlot(dst: storage, src: storage) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } -instance uint256:StorageCopy { - function copySlot(dst:storage(uint256), src:storage(uint256)) -> () { +impl StorageCopy { + function copySlot(dst: storage, src: storage) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } -instance bytes32:StorageCopy { - function copySlot(dst:storage(bytes32), src:storage(bytes32)) -> () { +impl StorageCopy { + function copySlot(dst: storage, src: storage) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } -instance address:StorageCopy { - function copySlot(dst:storage(address), src:storage(address)) -> () { +impl StorageCopy
{ + function copySlot(dst: storage
, src: storage
) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } @@ -2460,29 +2460,30 @@ instance address:StorageCopy { // Dynamic elements keep their payload at keccak256(elementSlot), so copying the // inline slot alone would leave the destination pointing at the *source's* tail. // Round-tripping through memory copies the payload too. -instance string:StorageCopy { - function copySlot(dst:storage(string), src:storage(string)) -> () { - CanStore.store(dst, CanStore.load(src):memory(string)); +impl StorageCopy { + function copySlot(dst: storage, src: storage) { + let value : memory = CanStore.load(src); + CanStore.store(dst, value); } } -instance bytes:StorageCopy { - function copySlot(dst:storage(bytes), src:storage(bytes)) -> () { - CanStore.store(dst, CanStore.load(src):memory(bytes)); +impl StorageCopy { + function copySlot(dst: storage, src: storage) { + let value : memory = CanStore.load(src); + CanStore.store(dst, value); } } -// Nested arrays recurse into the array CanStore instance above. The recursion is +// Nested arrays recurse into the array CanStore impl above. The recursion is // on the element type, so it terminates with the type's structure. -forall t . t:StorageCopy => -instance array(t):StorageCopy { - function copySlot(dst:storage(array(t)), src:storage(array(t))) -> () { +impl StorageCopy> where t: StorageCopy { + function copySlot(dst: storage>, src: storage>) { CanStore.store(dst, src); } } // Shamelessly stolen from function copy_byte_array_to_storage_from_t_bytes_memory_ptr_to_t_bytes_storage // TODO: consider wrapping behaviour at end of storage -function storeBytesFromMemory(slot: word, src: word) -> () { +function storeBytesFromMemory(slot: word, src: word) { assembly { let newLen := mload(src) // TODO: check old len, cleanup etc @@ -2522,7 +2523,7 @@ function storeBytesFromMemory(slot: word, src: word) -> () { // shamelessly stolen from abi_encode_t_string_storage_to_t_string_memory_ptr -function loadBytesFromStorage(slot:word, memPtr:word) -> word { +function loadBytesFromStorage(slot: word, memPtr: word) returns (word) { let pos = memPtr; let slotValue = sload(slot); let length = slotValue / 2; @@ -2532,47 +2533,49 @@ function loadBytesFromStorage(slot:word, memPtr:word) -> word { } mstore(pos, length); pos += 32; - match outOfPlaceEncoding { - | false => - // Short byte array + match (outOfPlaceEncoding) { +case false { +// Short byte array mstore(pos, slotValue & ~0xff); let empty = iszero(length); let notzero = iszero(empty); return pos + (notzero * 32); - | true => - // Long byte array +} +case true { +// Long byte array let dataPos = hash1(slot); let i = 0; for (; i < length; i += 32, dataPos += 1) { mstore(pos + i, sload(dataPos)); } return pos + i; - } +} +} } // -- Tuple-based indexed access: -forall col_idx val . class col_idx:RValueIdxAccess(val) { - function lookup(ci : col_idx) -> val; +trait RValueIdxAccess { + function lookup(ci: col_idx) returns (val) ; } -forall col_idx ref . class col_idx:LValueIdxAccess(ref) { - function lookup(ci : col_idx) -> ref; +trait LValueIdxAccess { + function lookup(ci: col_idx) returns (ref) ; } -forall i a . i:Typedef(word) => -instance (storage(mapping(i,a)), i): LValueIdxAccess(storage(a)) { - function lookup(xi : (storage(mapping(i,a)), i)) -> storage(a) { - match(xi) { - | (x, i) => return storage(hash2(Typedef.rep(x), Typedef.rep(i))); - } +impl LValueIdxAccess<(storage a)>, i), storage> where i: Typedef { + function lookup(xi: (storage a)>, i)) returns (storage) { + match (xi) { +case (x, i) { +return storage(hash2(Typedef.rep(x), Typedef.rep(i))); +} +} } } -forall i a . storage(a):CanStore(a), i:Typedef(word) => -instance (storage(mapping(i,a)), i): RValueIdxAccess(a) { - function lookup(xi : (storage(mapping(i,a)), i)) -> a { +impl RValueIdxAccess<(storage a)>, i), a> where storage: CanStore, i: Typedef { + function lookup(xi: (storage a)>, i)) returns (a) { /* match(xi) { | (x, i) => return StorageType.load(hash2(Typedef.rep(x), Typedef.rep(i))); @@ -2582,114 +2585,107 @@ instance (storage(mapping(i,a)), i): RValueIdxAccess(a) { } } -forall a i . i:Typedef(word) => -instance (storage(array(a)), i): LValueIdxAccess(storage(a)) { - function lookup(xi : (storage(array(a)), i)) -> storage(a) { - match(xi) { - | (x, i) => - let slot : word = Typedef.rep(x); +impl LValueIdxAccess<(storage>, i), storage> where i: Typedef { + function lookup(xi: (storage>, i)) returns (storage) { + match (xi) { +case (x, i) { +let slot : word = Typedef.rep(x); let idx : word = Typedef.rep(i); // Bounds check: idx must be in [0, length). Length lives at the // slot itself; inlined to avoid an Array(t) dispatch here. if (idx >= sload(slot)) { out_of_bounds(); } return storage(hash1(slot) + idx); - } +} +} } } // Reading arr[i] yields whatever the element's storage reference loads, rather // than the element tag type. For word-sized elements that is the element itself; -// for array(string) it is a memory(string); for a nested array(array(t)) it +// for array it is a memory; for a nested array> it // is the inner array's handle, which push/pop/length then consume. -forall a v i . storage(a):CanStore(v), i:Typedef(word) => -instance (storage(array(a)), i): RValueIdxAccess(v) { - function lookup(xi : (storage(array(a)), i)) -> v { +impl RValueIdxAccess<(storage>, i), v> where storage: CanStore, i: Typedef { + function lookup(xi: (storage>, i)) returns (v) { return CanStore.load(LValueIdxAccess.lookup(xi)); } } // Indexed read of a lazily-decoded calldata array: `arr[i]` desugars to // ridx(arr, i), which dispatches here and decodes element i on demand via -// abiArrayGet. There is deliberately no LValueIdxAccess instance — calldata is +// abiArrayGet. There is deliberately no LValueIdxAccess impl — calldata is // immutable, so `arr[i] = …` is (correctly) rejected at compile time. -forall t t_decoded i . - t : ABIAttribs, - ABIDecoder(t, CalldataWordReader):ABIDecode(t_decoded), - i : Typedef(word) => -instance (calldata(array(t)), i): RValueIdxAccess(t_decoded) { - function lookup(xi : (calldata(array(t)), i)) -> t_decoded { - match(xi) { - | (a, idx) => return abiArrayGet(a, uint256(Typedef.rep(idx))); - } +impl RValueIdxAccess<(calldata>, i), t_decoded> where t: ABIAttribs, ABIDecoder: ABIDecode, i: Typedef { + function lookup(xi: (calldata>, i)) returns (t_decoded) { + match (xi) { +case (a, idx) { +return abiArrayGet(a, uint256(Typedef.rep(idx))); +} +} } } // Memory arrays are read-only through `m[i]`: there is no memory cell reference -// type, so they get an RValue instance but no LValue one. -forall t i . t:Typedef(word), i:Typedef(word) => -instance (memory(DynArray(t)), i): RValueIdxAccess(t) { - function lookup(xi : (memory(DynArray(t)), i)) -> t { - match xi { - | (x, j) => return IndexAccess.get(x, uint256(Typedef.rep(j))); - } +// type, so they get an RValue impl but no LValue one. +impl RValueIdxAccess<(memory>, i), t> where t: Typedef, i: Typedef { + function lookup(xi: (memory>, i)) returns (t) { + match (xi) { +case (x, j) { +return IndexAccess.get(x, uint256(Typedef.rep(j))); +} +} } } // Mapping reads go through CanStore, matching the write side (Assign -> CanStore.store). -// This lets a mapping hold any value with a CanStore instance — including ADTs whose -// fields are dynamic (memory(bytes)) — not just the fixed-slot StorageType primitives. -forall a. storage(a):CanStore(a) => -function readStorage(x:storage(a)) -> a { +// This lets a mapping hold any value with a CanStore impl — including ADTs whose +// fields are dynamic (memory) — not just the fixed-slot StorageType primitives. +function readStorage(x: storage) returns (a) where storage: CanStore { return CanStore.load(x); } /* -forall r a. a:StorageType, r: RValueIdxAccess(a) => -function rval(x:r) -> a { +function rval(x: r) returns (a) where a: StorageType, r: RValueIdxAccess { return RValueIdxAccess.lookup(x); } -forall r a. r: LValueIdxAccess(a) => -function lval(x:r) -> a { +function lval(x: r) returns (a) where r: LValueIdxAccess { return LValueIdxAccess.lookup(x); } */ // lidx/ridx are the generic indexed-access helpers used by the `arr[i]` // desugaring. They dispatch through LValueIdxAccess / RValueIdxAccess, so any -// collection (mapping, array, ...) that provides those instances supports the +// collection (mapping, array, ...) that provides those impls supports the // `arr[i]` syntax. -forall col idx ref . (col, idx):LValueIdxAccess(ref) => -function lidx(c: col, i: idx) -> ref { +function lidx(c: col, i: idx) returns (ref) where (col, idx): LValueIdxAccess { return LValueIdxAccess.lookup((c, i)); } -forall col idx val . (col, idx):RValueIdxAccess(val) => -function ridx(c: col, i: idx) -> val { +function ridx(c: col, i: idx) returns (val) where (col, idx): RValueIdxAccess { return RValueIdxAccess.lookup((c, i)); } // --- Memory Encoding --- -forall t . class t:MemorySize { +trait MemorySize { // The size needed for the value. - function len(v: t) -> word; + function len(v: t) returns (word) ; } // NOTE: this is not implemented for value types. -forall t . class t:MemoryPointer { +trait MemoryPointer { // In-memory location of the given value. - function ptr(v: t) -> word; + function ptr(v: t) returns (word) ; } -forall t . class t:MemoryEncode { +trait MemoryEncode { // Serialize the entire contents at a provided memory area. - function encodeInto(v: t, target: word) -> (); + function encodeInto(v: t, target: word) ; } // TODO: support variadic arguments // Allocates new memory and concatenates the inputs into it. -forall a b . a:MemorySize, a:MemoryEncode, b:MemorySize, b:MemoryEncode => function concat(x: a, y: b) -> memory(bytes) { +function concat(x: a, y: b) returns (memory) where a: MemorySize, a: MemoryEncode, b: MemorySize, b: MemoryEncode { let x_len = MemorySize.len(x); let y_len = MemorySize.len(y); let res: word = allocate_memory(32 + x_len + y_len); @@ -2700,7 +2696,7 @@ forall a b . a:MemorySize, a:MemoryEncode, b:MemorySize, b:MemoryEncode => funct } // This is a specialized 1-input version of concat. -forall a . a:MemorySize, a:MemoryEncode => function to_bytes(x: a) -> memory(bytes) { +function to_bytes(x: a) returns (memory) where a: MemorySize, a: MemoryEncode { let len = MemorySize.len(x); let res = allocate_memory(32 + len); mstore(res, len); @@ -2708,32 +2704,32 @@ forall a . a:MemorySize, a:MemoryEncode => function to_bytes(x: a) -> memory(byt return memory(res); } -instance bytes32:MemorySize { - function len(v: bytes32) -> word { +impl MemorySize { + function len(v: bytes32) returns (word) { return 32; } } -instance bytes32:MemoryEncode { - function encodeInto(v: bytes32, target: word) -> () { +impl MemoryEncode { + function encodeInto(v: bytes32, target: word) { mstore(target, Typedef.rep(v)); } } -instance memory(bytes):MemorySize { - function len(v: memory(bytes)) -> word { +impl MemorySize> { + function len(v: memory) returns (word) { return mload(Typedef.rep(v)); } } -instance memory(bytes):MemoryPointer { - function ptr(v: memory(bytes)) -> word { +impl MemoryPointer> { + function ptr(v: memory) returns (word) { return Typedef.rep(v) + 32; } } -instance memory(bytes):MemoryEncode { - function encodeInto(v: memory(bytes), target: word) -> () { +impl MemoryEncode> { + function encodeInto(v: memory, target: word) { let v_ = Typedef.rep(v); mcopy(target, v_ + 32, mload(v_)); } @@ -2742,22 +2738,26 @@ instance memory(bytes):MemoryEncode { // Placeholder for an empty memory area. // The value is the size of the area in bytes. The area will be zeroed upon serialization. // NOTE: not implementing Typedef by design. -data empty = empty(word); +enum empty { empty(word) } -instance empty:MemorySize { - function len(v: empty) -> word { - match v { - | empty(size) => return size; - } +impl MemorySize { + function len(v: empty) returns (word) { + match (v) { +case empty(size) { +return size; +} +} } } -instance empty:MemoryEncode { - function encodeInto(v: empty, target: word) -> () { +impl MemoryEncode { + function encodeInto(v: empty, target: word) { let size; - match v { - | empty(size_) => size = size_; - } + match (v) { +case empty(size_) { +size = size_; +} +} zeroize_memory(target, size); } } @@ -2766,42 +2766,46 @@ instance empty:MemoryEncode { // This is a very cheap abstraction over a memory area of [ptr, ptr+len) // No type information is preserved. -data memory_ref = memory_ref(word, word); +enum memory_ref { memory_ref(word, word) } -instance memory_ref:MemorySize { - function len(v: memory_ref) -> word { - match v { - | memory_ref(ptr, len) => return len; - } +impl MemorySize { + function len(v: memory_ref) returns (word) { + match (v) { +case memory_ref(ptr, len) { +return len; +} +} } } -instance memory_ref:MemoryPointer { - function ptr(v: memory_ref) -> word { - match v { - | memory_ref(ptr, len) => return ptr; - } +impl MemoryPointer { + function ptr(v: memory_ref) returns (word) { + match (v) { +case memory_ref(ptr, len) { +return ptr; +} +} } } -instance memory_ref:MemoryEncode { - function encodeInto(v: memory_ref, target: word) -> () { - match v { - | memory_ref(ptr, len) => mcopy(target, ptr, len); - } +impl MemoryEncode { + function encodeInto(v: memory_ref, target: word) { + match (v) { +case memory_ref(ptr, len) { +mcopy(target, ptr, len); +} +} } } -forall a . a:MemorySize, a:MemoryPointer => -function slice_(input: a, start: word) -> memory_ref { +function slice_(input: a, start: word) returns (memory_ref) where a: MemorySize, a: MemoryPointer { let len = MemorySize.len(input); // TODO: should this allow (it does now) a zero-length slice? require(len >= start, Error(0xb4120f14)); // OutOfBounds() return memory_ref(MemoryPointer.ptr(input) + start, len - start); } -forall a . a:MemorySize, a:MemoryPointer => -function truncate(input: a, end: word) -> memory_ref { +function truncate(input: a, end: word) returns (memory_ref) where a: MemorySize, a: MemoryPointer { let len = MemorySize.len(input); // TODO: should this allow (it does now) a zero-length slice? require(len >= end, Error(0xb4120f14)); // OutOfBounds() @@ -2811,13 +2815,13 @@ function truncate(input: a, end: word) -> memory_ref { // --- Hashing --- // NOTE: keccak256 name conflicts with assembly namespace -forall a . a:MemorySize, a:MemoryPointer => function keccak256_(input: a) -> bytes32 { +function keccak256_(input: a) returns (bytes32) where a: MemorySize, a: MemoryPointer { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); return bytes32(keccak256(ptr, len)); } -forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 { +function sha256(input: a) returns (bytes32) where a: MemorySize, a: MemoryPointer { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); // We assume the [0, 32] scratch space is reserved. @@ -2826,7 +2830,7 @@ forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 return bytes32(mload(0)); } -forall a . a:MemorySize, a:MemoryPointer => function ripemd160(input: a) -> bytes32 { +function ripemd160(input: a) returns (bytes32) where a: MemorySize, a: MemoryPointer { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); // We assume the [0, 32] scratch space is reserved. @@ -2842,7 +2846,7 @@ forall a . a:MemorySize, a:MemoryPointer => function ripemd160(input: a) -> byte // were updated to ban this, but the precompile wasn't. If a user relies on that // feature they can call the precompile via assembly. // TODO: use uint8 -function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) -> address { +function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) returns (address) { // MalleableSignatureRejected() require( Typedef.rep(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, @@ -2875,11 +2879,11 @@ function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) -> address // ERC-7201 namespaced storage slot, computed entirely at compile time from a // string-literal namespace `id`: // keccak256(abi.encode(uint256(keccak256(bytes(id))) - 1)) & ~bytes32(uint256(0xff)) -function erc7201(comptime id: string) -> comptime bytes32 { +function erc7201(comptime id: string) returns (comptime) { return bytes32(keccakWordLit(keccakLit(id) - 1) & ~0xff); } -forall a . a:MemorySize, a:MemoryPointer => function raw_call(target: address, value: uint256, payload: a) -> (bool, memory(bytes)) { +function raw_call(target: address, value: uint256, payload: a) returns (bool, memory) where a: MemorySize, a: MemoryPointer { let ret = call( gas(), Typedef.rep(target), From 44f9f3ccfbf6bf10145c0dae5294d2ac4da9e682 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 067/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../ok/test/examples/cases/Ackermann.sol | 20 ++-- .../corpus/ok/test/examples/cases/Add1.sol | 2 +- .../corpus/ok/test/examples/cases/BoolNot.sol | 16 ++- .../corpus/ok/test/examples/cases/Compose.sol | 4 +- .../ok/test/examples/cases/Compose3.sol | 8 +- .../corpus/ok/test/examples/cases/CondExp.sol | 8 +- .../ok/test/examples/cases/DuplicateFun.sol | 16 +-- .../ok/test/examples/cases/EitherModule.sol | 31 +++-- .../corpus/ok/test/examples/cases/EqQual.sol | 30 ++--- .../corpus/ok/test/examples/cases/EvenOdd.sol | 34 +++--- .../corpus/ok/test/examples/cases/Foo.sol | 4 +- .../corpus/ok/test/examples/cases/Id.sol | 4 +- .../ok/test/examples/cases/ListModule.sol | 40 ++++--- .../corpus/ok/test/examples/cases/Logic.sol | 68 +++++++---- .../ok/test/examples/cases/MatchCall.sol | 18 +-- .../corpus/ok/test/examples/cases/Memory1.sol | 8 +- .../corpus/ok/test/examples/cases/Memory2.sol | 6 +- .../corpus/ok/test/examples/cases/Mutuals.sol | 4 +- .../corpus/ok/test/examples/cases/NegPair.sol | 76 ++++++++----- .../corpus/ok/test/examples/cases/Option.sol | 22 ++-- .../corpus/ok/test/examples/cases/Pair.sol | 42 ++++--- .../corpus/ok/test/examples/cases/Peano.sol | 18 +-- .../ok/test/examples/cases/PeanoMatch.sol | 20 ++-- .../ok/test/examples/cases/RefDeref.sol | 12 +- .../ok/test/examples/cases/SimpleLambda.sol | 6 +- .../ok/test/examples/cases/SingleFun.sol | 2 +- .../corpus/ok/test/examples/cases/Uncurry.sol | 10 +- .../ok/test/examples/cases/abigeneric.sol | 106 ++++++++---------- .../ok/test/examples/cases/another-subst.sol | 14 ++- .../corpus/ok/test/examples/cases/app.sol | 12 +- .../corpus/ok/test/examples/cases/array.sol | 87 +++++++------- .../test/examples/cases/asm-let-bool-lit.sol | 2 +- .../ok/test/examples/cases/asm-let-uninit.sol | 2 +- .../examples/cases/asm-match-tuple-read.sol | 12 +- .../cases/asm-match-tuple-write-read.sol | 12 +- .../ok/test/examples/cases/assembly.sol | 10 +- .../corpus/ok/test/examples/cases/bal.sol | 33 +++--- .../corpus/ok/test/examples/cases/bar.sol | 14 +-- .../corpus/ok/test/examples/cases/bitwise.sol | 10 +- .../ok/test/examples/cases/bool-elim.sol | 18 +-- .../test/examples/cases/bound-merge-case.sol | 2 +- .../test/examples/cases/bound-with-pragma.sol | 8 +- .../bug-call-expected-nontail-return.sol | 25 +++-- .../cases/bug-import-default-inst-shadow.sol | 4 +- 44 files changed, 501 insertions(+), 399 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.sol index c2181cc0..94279f63 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Ackermann.sol @@ -1,10 +1,16 @@ -data Nat = Zero | Succ(Nat) ; +enum Nat { Zero, Succ(Nat) } -function foo (x : Nat, y : Nat) -> word { - match y, x { - | y1, Nat.Zero => return 1 ; - | Nat.Zero, Nat.Succ(x2) => return 2; - | Nat.Succ(y3), Nat.Succ(x3) => return 3; - } +function foo(x: Nat, y: Nat) returns (word) { + match (y, x) { +case (y1, Nat.Zero) { +return 1 ; +} +case (Nat.Zero, Nat.Succ(x2)) { +return 2; +} +case (Nat.Succ(y3), Nat.Succ(x3)) { +return 3; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol index 8c47763d..72baa53a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol @@ -1,5 +1,5 @@ contract Add1 { - public function main() -> word { + function main() public returns (word) { let res: word; assembly { res := add(40, 2) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.sol index 37969845..a4de0a14 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/BoolNot.sol @@ -1,8 +1,12 @@ -data Bool = False | True; +enum Bool { False, True } -function not (b : Bool) -> Bool { - match b { - | Bool.False => return Bool.True ; - | Bool.True => return Bool.False ; - } +function not(b: Bool) returns (Bool) { + match (b) { +case Bool.False { +return Bool.True ; +} +case Bool.True { +return Bool.False ; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.sol index 8b25bc25..4d465a89 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose.sol @@ -1,7 +1,7 @@ contract Compose { - public function id(x : word) -> word { return x; } + function id(x: word) public returns (word) { return x; } - public function main() -> word { + function main() public returns (word) { return id(id(42)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol index d04847e8..4da95232 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Compose3.sol @@ -1,11 +1,11 @@ contract Compose { - forall a . public function id(x : a) -> a { return x; } + function id(x: a) public returns (a) { return x; } - public function apply1(f : (word) -> word, a : word) -> word { return f(a); } + function apply1(f: function(word) returns (word), a: word) public returns (word) { return f(a); } - public function idThenId(x : word) -> word { return id(id(x)); } + function idThenId(x: word) public returns (word) { return id(id(x)); } - public function main() -> word { + function main() public returns (word) { return apply1(idThenId, 42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.sol index 4c5a236d..8eb68845 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/CondExp.sol @@ -1,8 +1,8 @@ contract CondExp { - public function main() -> word { + function main() public returns (word) { return - if if true then false else true - then if false then 1 else 2 - else if true then 42 else 56; + ( true ? false : true + ) ? false ? 1 : 2 + : true ? 42 : 56; } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.sol index 5ef3bb2c..e6e9202b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/DuplicateFun.sol @@ -1,21 +1,21 @@ -forall self . class self:A { - function foo(p : self) -> word; +trait A { + function foo(p: self) returns (word) ; } -forall self . class self:B { - function foo(p : self) -> word; +trait B { + function foo(p: self) returns (word) ; } -instance word:B { - function foo(x : word) -> word { +impl B { + function foo(x: word) returns (word) { return x; } } // error: Constraint for A not found in type of foo -instance word:A { - function foo(x : word) -> word { +impl A { + function foo(x: word) returns (word) { return x; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.sol index abf8b393..93da7d7e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EitherModule.sol @@ -1,17 +1,24 @@ contract EitherModule { - data Either(a,b) = Left(a) | Right(b); - data List(a) = Nil | Cons(a,List(a)); + enum Either { Left(a), Right(b) } + enum List { Nil, Cons(a, List) } - public function lefts(xs : List(Either(word,word))) -> List(word) { - match xs { - | List.Nil => return List.Nil ; - | List.Cons(y,ys) => - match y { - | Either.Left(z) => return List.Cons(z,lefts(ys)) ; - | Either.Right(z) => return lefts(ys) ; - } - } + function lefts(xs: List>) public returns (List) { + match (xs) { +case List.Nil { +return List.Nil ; +} +case List.Cons(y,ys) { +match (y) { +case Either.Left(z) { +return List.Cons(z,lefts(ys)) ; +} +case Either.Right(z) { +return lefts(ys) ; +} +} +} +} } - public function main() -> word { return 0; } + function main() public returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.sol index 874acf93..51141ecc 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EqQual.sol @@ -1,24 +1,26 @@ -data Bool = True | False; +enum Bool { True, False } -forall a . class a : Eq { - function eq (x : a, y : a) -> Bool; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } -forall a . a : Eq => class a : Ord { - function lt (x : a, y : a) -> Bool ; +trait Ord where a: Eq { + function lt(x: a, y: a) returns (Bool) ; } -instance word : Eq { - function eq (x : word, y : word) -> Bool { - match primEqWord(x,y) { - | 0 => - return Bool.False; - | _ => - return Bool.True ; - } +impl Eq { + function eq(x: word, y: word) returns (Bool) { + match (primEqWord(x,y)) { +case 0 { +return Bool.False; +} +default { +return Bool.True ; +} +} } } -function foo (x : word) -> Bool { +function foo(x: word) returns (Bool) { return Eq.eq (x, 0); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.sol index 96da4173..8d8e1663 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/EvenOdd.sol @@ -1,20 +1,28 @@ contract EvenOdd { - data Nat = Zero | Succ(Nat); - data Bool = False | True; + enum Nat { Zero, Succ(Nat) } + enum Bool { False, True } - public function even (n : Nat) -> Bool { - match n { - | Nat.Zero => return Bool.True; - | Nat.Succ(m) => return odd(m); - } + function even(n: Nat) public returns (Bool) { + match (n) { +case Nat.Zero { +return Bool.True; +} +case Nat.Succ(m) { +return odd(m); +} +} } - public function odd(n : Nat) -> Bool { - match n { - | Nat.Zero => return Bool.False; - | Nat.Succ(m) => return even(m); - } + function odd(n: Nat) public returns (Bool) { + match (n) { +case Nat.Zero { +return Bool.False; +} +case Nat.Succ(m) { +return even(m); +} +} } - public function main() -> word { return 0; } + function main() public returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.sol index c416cd9f..5adbcda0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Foo.sol @@ -1,8 +1,8 @@ - function one() -> word { + function one() returns (word) { return primAddWord(1, zero()) ; } - function zero () -> word { + function zero() returns (word) { return 0; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.sol index 1594f7cb..d00cde77 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Id.sol @@ -1,9 +1,9 @@ -function id (x : word) -> word { +function id(x: word) returns (word) { return x; } contract Id { - public function main () -> word { + function main() public returns (word) { return id(0); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.sol index ec5343fa..e2e06e14 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ListModule.sol @@ -1,26 +1,34 @@ contract ListModule { - data List(a) = Nil | Cons(a,List(a)); - data Bool = True | False; + enum List { Nil, Cons(a, List) } + enum Bool { True, False } - forall a b c . public function zipWith (f : (a,b) -> c,xs : List(a),ys : List(b)) -> List(c) { - match xs, ys { - | List.Nil, List.Nil => return List.Nil ; - | List.Cons(x1,xs1), List.Cons(y1,ys1) => - return List.Cons(f(x1,y1), zipWith(f,xs1,ys1)) ; - | _, _ => return List.Nil; - } + function zipWith(f: function(a, b) returns (c), xs: List, ys: List) public returns (List) { + match (xs, ys) { +case (List.Nil, List.Nil) { +return List.Nil ; +} +case (List.Cons(x1,xs1), List.Cons(y1,ys1)) { +return List.Cons(f(x1,y1), zipWith(f,xs1,ys1)) ; +} +default { +return List.Nil; +} +} } - forall a b . public function foldr(f : (a,b) -> b, v : b, xs : List(a)) -> b { - match xs { - | List.Nil => return v; - | List.Cons(y,ys) => - return f(y, foldr(f,v,ys)) ; - } + function foldr(f: function(a, b) returns (b), v: b, xs: List) public returns (b) { + match (xs) { +case List.Nil { +return v; +} +case List.Cons(y,ys) { +return f(y, foldr(f,v,ys)) ; +} +} } - public function main () -> word { + function main() public returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.sol index e5463613..3cea62b4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Logic.sol @@ -1,35 +1,55 @@ contract Logic { - data Bool = True | False; + enum Bool { True, False } - public function not (x : Bool) -> Bool { - match x { - | Bool.True => return Bool.False ; - | Bool.False => return Bool.True ; - } + function not(x: Bool) public returns (Bool) { + match (x) { +case Bool.True { +return Bool.False ; +} +case Bool.False { +return Bool.True ; +} +} } - public function and(x : Bool, y : Bool) -> Bool { - match x, y { - | Bool.False, _ => return Bool.False ; - | Bool.True , _ => return y ; - } + function and(x: Bool, y: Bool) public returns (Bool) { + match (x, y) { +case (Bool.False, _) { +return Bool.False ; +} +case (Bool.True , _) { +return y ; +} +} } - public function and1 (x : Bool, y : Bool) -> Bool { - match x, y { - | Bool.False, Bool.False => return Bool.False ; - | Bool.True , Bool.False => return Bool.False; - | Bool.False ,Bool.True => return Bool.False; - | Bool.True, Bool.True => return Bool.True; - } + function and1(x: Bool, y: Bool) public returns (Bool) { + match (x, y) { +case (Bool.False, Bool.False) { +return Bool.False ; +} +case (Bool.True , Bool.False) { +return Bool.False; +} +case (Bool.False ,Bool.True) { +return Bool.False; +} +case (Bool.True, Bool.True) { +return Bool.True; +} +} } - public function elim (f : word, g : word, x : Bool) -> word { - match x { - | Bool.True => return f; - | Bool.False => return g; - } + function elim(f: word, g: word, x: Bool) public returns (word) { + match (x) { +case Bool.True { +return f; +} +case Bool.False { +return g; +} +} } - public function main() -> word { return 0; } + function main() public returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.sol index c4c4be10..aa5cbdac 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/MatchCall.sol @@ -1,14 +1,18 @@ -data Bool = False | True; +enum Bool { False, True } contract MatchCall { - public function f() -> Bool { + function f() public returns (Bool) { return Bool.True; } - public function main() -> word { - match f() { - | Bool.True => return 42; - | Bool.False => return 0; - } + function main() public returns (word) { + match (f()) { +case Bool.True { +return 42; +} +case Bool.False { +return 0; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.sol index af3a5ecd..eed86675 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory1.sol @@ -1,7 +1,7 @@ -data memory(a) = memory(word); +enum memory { memory(word) } -function g() -> () { - let x : memory(memory(word)); - let y : memory(word) = memory(1); +function g() { + let x : memory>; + let y : memory = memory(1); x = memory(0); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.sol index 64fb9d95..b7083cf8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Memory2.sol @@ -1,5 +1,5 @@ -data Memory(a) = Memory(word); +enum Memory { Memory(word) } -function g() -> () { - let x : Memory(Memory(word)) = Memory(0); +function g() { + let x : Memory> = Memory(0); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.sol index aa2d70e4..09ac8593 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Mutuals.sol @@ -1,8 +1,8 @@ contract Mutual { - public function main () -> word { + function main() public returns (word) { return f(); } - public function f () -> word { + function f() public returns (word) { return 42; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.sol index d3d9da62..895624bb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/NegPair.sol @@ -1,53 +1,69 @@ -forall a . class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } -forall a b . function fst (p : (a,b)) -> a { - match p { - | (x,y) => return x; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (x,y) { +return x; +} +} } -forall a b . function snd(p : (a,b)) -> b { - match p { - | (x,y) => return y; - } +function snd(p: (a, b)) returns (b) { + match (p) { +case (x,y) { +return y; +} +} } -forall a b . a : Neg, b : Neg => instance (a,b):Neg { - function neg(p : (a,b)) -> (a,b) { +impl Neg<(a, b)> where a: Neg, b: Neg { + function neg(p: (a, b)) returns (a, b) { return (Neg.neg (fst(p)), Neg.neg(snd (p))); } } contract NegPair { - public function bnot(x : B) -> B { - match x { - | B.T => return B.F; - | B.F => return B.T; - } + function bnot(x: B) public returns (B) { + match (x) { +case B.T { +return B.F; +} +case B.F { +return B.T; +} +} } - public function fromB(b : B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) public returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } - public function main() -> word { return fromB(fst(Neg.neg((B.F,B.T)))); } + function main() public returns (word) { return fromB(fst(Neg.neg((B.F,B.T)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.sol index 5176d111..e84e01f2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Option.sol @@ -1,13 +1,19 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function join(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.None => return Option.None; - | Option.Some(Option.Some(x)) => return Option.Some(x); - | Option.Some(Option.None) => return Option.None; - } + function join(mmx: Option>) public returns (Option) { + match (mmx) { +case Option.None { +return Option.None; +} +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +case Option.Some(Option.None) { +return Option.None; +} +} } - public function main() -> word { return 0; } + function main() public returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.sol index 5e698e45..8ad2e11d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Pair.sol @@ -1,27 +1,35 @@ - forall a b . function fst (x : (a,b)) -> a { - match x { - | (a,_) => return a; - } + function fst(x: (a, b)) returns (a) { + match (x) { +case (a,_) { +return a; +} +} } - forall a b . function snd(x : (a,b)) -> b { - match x { - | (_,b) => return b; - } + function snd(x: (a, b)) returns (b) { + match (x) { +case (_,b) { +return b; +} +} } - function uncurry(f : (word, word) -> word, x : (word,word)) -> word { - match x { - | (a,b) => return f(a,b); - } + function uncurry(f: function(word, word) returns (word), x: (word, word)) returns (word) { + match (x) { +case (a,b) { +return f(a,b); +} +} } - function snds (p1 : (word,word), p2 : (word,word)) -> (word,word) { - match p1, p2 { - | (a,b) , (c,d) => return (b,d); - } + function snds(p1: (word, word), p2: (word, word)) returns (word, word) { + match (p1, p2) { +case ((a,b) , (c,d)) { +return (b,d); +} +} } - function curry(f : ((word,word)) -> word, x : word, y : word) -> word { + function curry(f: function((word, word)) returns (word), x: word, y: word) returns (word) { return f((x,y)) ; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.sol index 4deac861..1bcfc428 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Peano.sol @@ -1,12 +1,16 @@ -data Nat = Zero | Succ(Nat); +enum Nat { Zero, Succ(Nat) } -function natInd (step : (Nat, Nat) -> Nat, v : Nat, n : Nat) -> Nat { - match n { - | Nat.Zero => return v ; - | Nat.Succ(m) => return step(m, natInd(step,v,m)); - } +function natInd(step: function(Nat, Nat) returns (Nat), v: Nat, n: Nat) returns (Nat) { + match (n) { +case Nat.Zero { +return v ; +} +case Nat.Succ(m) { +return step(m, natInd(step,v,m)); +} +} } -function add(n : Nat, m : Nat) -> Nat { +function add(n: Nat, m: Nat) returns (Nat) { return natInd (lam (x, acc) {return Nat.Succ(acc) ; }, m, n); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.sol index 696c5136..252e91ad 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/PeanoMatch.sol @@ -1,9 +1,15 @@ -data Nat = Zero | Succ(Nat); +enum Nat { Zero, Succ(Nat) } -function foo(n : Nat) -> Nat { - match n { - | Nat.Zero => return Nat.Succ(Nat.Zero) ; - | Nat.Succ(Nat.Succ(x)) => return x; - | x => return Nat.Zero; - } +function foo(n: Nat) returns (Nat) { + match (n) { +case Nat.Zero { +return Nat.Succ(Nat.Zero) ; +} +case Nat.Succ(Nat.Succ(x)) { +return x; +} +case x { +return Nat.Zero; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.sol index f096ffb5..2f2be66c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/RefDeref.sol @@ -1,12 +1,10 @@ -forall ref deref . class ref:Loadable (deref) { - function load (r : ref) -> deref; +trait Loadable { + function load(r: ref) returns (deref) ; } -forall ref deref . class ref:Storable (deref) { - function store (r : ref, d : deref) -> (); +trait Storable { + function store(r: ref, d: deref) ; } // haskell style class constraints -forall ref deref . - ref : Loadable(deref) - , ref : Storable(ref) => class ref:Ref (deref) {} +trait Ref where ref: Loadable, ref: Storable {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol index 1a68797e..b1bc3033 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol @@ -1,4 +1,4 @@ -function addWord(x : word, y : word) -> word { +function addWord(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -7,7 +7,7 @@ function addWord(x : word, y : word) -> word { } contract SimpleLambda{ - public function f (z : word) -> word { + function f(z: word) public returns (word) { let n = lam (x : word, y : word) { return addWord(x,addWord(y,1)); } ; @@ -16,7 +16,7 @@ contract SimpleLambda{ } ; return m(n(1,0)); } - public function main() -> word { + function main() public returns (word) { return f(40); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol index 0f93d869..e922f202 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol @@ -1,3 +1,3 @@ -function id (x : word) -> word { +function id(x: word) returns (word) { return x ; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.sol index bde18537..ba9be2f9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Uncurry.sol @@ -1,5 +1,7 @@ -function uncurry (f : word, p : (word, word)) -> word { - match p { - | (x,y) => return f(x,y); - } +function uncurry(f: word, p: (word, word)) returns (word) { + match (p) { +case (x,y) { +return f(x,y); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.sol index d357a803..ddd5893e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/abigeneric.sol @@ -7,23 +7,22 @@ export { decode }; -import std.{*}; -import std.opcodes.{mstore}; -import std.Generic.{*}; +import * from std; +import {mstore} from std.opcodes; +import * from std.Generic; // ─── ABIAttribs for the primitive sum(f, g) type ───────────────────────── // headSize = 32 (tag word) + max(headSize(f), headSize(g)) -forall f g . f:ABIAttribs, g:ABIAttribs => -instance sum(f, g) : ABIAttribs { - function headSize(ty : Proxy(sum(f, g))) -> word { - let pf : Proxy(f); - let pg : Proxy(g); +impl ABIAttribs> where f: ABIAttribs, g: ABIAttribs { + function headSize(ty: Proxy>) returns (word) { + let pf : Proxy; + let pg : Proxy; return 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); } - function isStatic(ty : Proxy(sum(f, g))) -> bool { - let pf : Proxy(f); - let pg : Proxy(g); + function isStatic(ty: Proxy>) returns (bool) { + let pf : Proxy; + let pg : Proxy; return and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg)); } } @@ -33,63 +32,60 @@ instance sum(f, g) : ABIAttribs { // [offset + 0 .. offset + 31] : tag word (0 = inl, 1 = inr) // [offset + 32 .. ] : encoded branch payload -forall f g . f:ABIAttribs, f:ABIEncode, g:ABIAttribs, g:ABIEncode => -instance sum(f, g) : ABIEncode { - function encodeInto(x : sum(f, g), basePtr : word, offset : word, tail : word) -> word { - match x { - | inl(v) => - mstore(basePtr + offset, 0); +impl ABIEncode> where f: ABIAttribs, f: ABIEncode, g: ABIAttribs, g: ABIEncode { + function encodeInto(x: sum, basePtr: word, offset: word, tail: word) returns (word) { + match (x) { +case inl(v) { +mstore(basePtr + offset, 0); return ABIEncode.encodeInto(v, basePtr, offset + 32, tail); - | inr(v) => - mstore(basePtr + offset, 1); +} +case inr(v) { +mstore(basePtr + offset, 1); return ABIEncode.encodeInto(v, basePtr, offset + 32, tail); - } +} +} } } // ─── ABIDecode for sum(f, g) ───────────────────────────────────────────── // Reads the tag word at headOffset; dispatches to f or g decoder at headOffset + 32. -forall f g reader . - reader : WordReader, - f : ABIAttribs, - ABIDecoder(f, reader) : ABIDecode(f), - ABIDecoder(g, reader) : ABIDecode(g) => -instance ABIDecoder(sum(f, g), reader) : ABIDecode(sum(f, g)) { - function decode(ptr : ABIDecoder(sum(f, g), reader), headOffset : word) -> sum(f, g) { - match ptr { - | ABIDecoder(rdr) => - let tag = WordReader.read(WordReader.advance(rdr, headOffset)); - match tag { - | 0 => - let dec_f : ABIDecoder(f, reader) = ABIDecoder(rdr); +impl ABIDecode, reader>, sum> where reader: WordReader, f: ABIAttribs, ABIDecoder: ABIDecode, ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder, reader>, headOffset: word) returns (sum) { + match (ptr) { +case ABIDecoder(rdr) { +let tag = WordReader.read(WordReader.advance(rdr, headOffset)); + match (tag) { +case 0 { +let dec_f : ABIDecoder = ABIDecoder(rdr); return inl(ABIDecode.decode(dec_f, headOffset + 32)); - | _ => - let dec_g : ABIDecoder(g, reader) = ABIDecoder(rdr); +} +default { +let dec_g : ABIDecoder = ABIDecoder(rdr); return inr(ABIDecode.decode(dec_g, headOffset + 32)); - } - } +} +} +} +} } } // ─── Default bridges: ABIAttribs and ABIEncode via Generic ─────────────── // Any type 'a' with Generic(rep) inherits its ABI layout from rep. -forall a rep . a:Generic(rep), rep:ABIAttribs => -default instance a : ABIAttribs { - function headSize(ty : Proxy(a)) -> word { - let prx : Proxy(rep); +default impl ABIAttribs where a: Generic, rep: ABIAttribs { + function headSize(ty: Proxy) returns (word) { + let prx : Proxy; return ABIAttribs.headSize(prx); } - function isStatic(ty : Proxy(a)) -> bool { - let prx : Proxy(rep); + function isStatic(ty: Proxy) returns (bool) { + let prx : Proxy; return ABIAttribs.isStatic(prx); } } -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -default instance a : ABIEncode { - function encodeInto(x : a, basePtr : word, offset : word, tail : word) -> word { +default impl ABIEncode where a: Generic, rep: ABIAttribs, rep: ABIEncode { + function encodeInto(x: a, basePtr: word, offset: word, tail: word) returns (word) { return ABIEncode.encodeInto(Generic.from(x), basePtr, offset, tail); } } @@ -98,8 +94,7 @@ default instance a : ABIEncode { // Serialises any 'a' that has a Generic(rep) instance. // Only the Generic instance is required — ABIEncode is resolved via the bridge. -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -function encode(x : a, basePtr : word, offset : word, tail : word) -> word { +function encode(x: a, basePtr: word, offset: word, tail: word) returns (word) where a: Generic, rep: ABIAttribs, rep: ABIEncode { let xrep : rep = Generic.from(x); return ABIEncode.encodeInto(xrep, basePtr, offset, tail); } @@ -108,14 +103,11 @@ function encode(x : a, basePtr : word, offset : word, tail : word) -> word { // Deserialises any 'a' that has a Generic(rep) instance. // Only the Generic instance is required — ABIDecode is resolved via the bridge. -forall a rep reader . - a : Generic(rep), - reader : WordReader, - ABIDecoder(rep, reader) : ABIDecode(rep) => -function decode(ptr : ABIDecoder(a, reader), headOffset : word) -> a { - match ptr { - | ABIDecoder(rdr) => - let rep_ptr : ABIDecoder(rep, reader) = ABIDecoder(rdr); +function decode(ptr: ABIDecoder, headOffset: word) returns (a) where a: Generic, reader: WordReader, ABIDecoder: ABIDecode { + match (ptr) { +case ABIDecoder(rdr) { +let rep_ptr : ABIDecoder = ABIDecoder(rdr); return Generic.to(ABIDecode.decode(rep_ptr, headOffset)); - } +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.sol index 37840ccd..82ec0e03 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/another-subst.sol @@ -1,9 +1,11 @@ -forall a . class a: Foo {function foo(x:a) -> (); } +trait Foo {function foo(x: a) ; } -forall a b . a : Foo, b : Foo => instance (a,b) : Foo { - function foo( p : (a,b) ) -> () { - match p { - | (pa, pb) => Foo.foo(pa); Foo.foo(pb); - } +impl Foo<(a, b)> where a: Foo, b: Foo { + function foo(p: (a, b)) { + match (p) { +case (pa, pb) { +Foo.foo(pa); Foo.foo(pb); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.sol index 60f4b573..53bed945 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/app.sol @@ -1,21 +1,21 @@ -forall a b c . c : invokable(a, b) => function app (f : c, x : a) -> b { +function app(f: c, x: a) returns (b) where c: invokable { return invokable.invoke(f, x); } -data t_id = t_id; +enum t_id { t_id } -instance t_id : invokable(word, word) { - function invoke(self : t_id, x : word) -> word { +impl invokable { + function invoke(self: t_id, x: word) returns (word) { return x; } } -function foo() -> word { +function foo() returns (word) { return app(t_id, 0); } contract C { - public function main () -> word { + function main() public returns (word) { return foo(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.sol index b587bb4b..d5b659e9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/array.sol @@ -1,14 +1,14 @@ pragma no-coverage-condition TAdd; -data Zero; -data Succ(a); +enum Zero {} +enum Succ {} -forall self res . class self:TAdd(res) {} -forall a . instance (Zero, a):TAdd(a) {} -forall a b c . (b, a):TAdd(c) => instance (Succ(b), a):TAdd(Succ(c)) {} +trait TAdd {} +impl TAdd<(Zero, a), a> {} +impl TAdd<(Succ, a), Succ> where (b, a): TAdd {} -forall lhs rhs . class lhs:Eq(rhs) {} -forall a . instance a:Eq(a) {} +trait Eq {} +impl Eq {} // this should work but doesnt: forall sizel sizer elem sizeout . (sizel, sizer):TAdd(sizeout) // TODO: this panics during specialization @@ -17,27 +17,28 @@ forall sizel sizer elem sizeout pairSizelSizer . pairSizelSizer:Eq((sizel, sizer return memory(0) : memory(array(sizeout, elem)); // :D } */ -data Itself(a) = ItselfRuntimeTag; +enum Itself { ItselfRuntimeTag } -data array(size, elem) = array; -data memory(a) = memory(word); +enum array { array } +enum memory { memory(word) } -forall self indexType elementType . class self:IndexAccessible (indexType, elementType){ - function set(self:self, ix:indexType, val:elementType) -> (); - function at(self:self, ix:indexType) -> elementType; +trait IndexAccessible { + function set(self: self, ix: indexType, val: elementType) ; + function at(self: self, ix: indexType) returns (elementType) ; } -forall self . class self:ToWord{ - function toWord(self:Itself(self)) -> word; +trait ToWord { + function toWord(self: Itself) returns (word) ; } -instance Zero : ToWord { - function toWord(zero : Itself(Zero)) -> word { return 0; } +impl ToWord { + function toWord(zero: Itself) returns (word) { return 0; } } -forall prev . prev:ToWord => instance Succ(prev) : ToWord { - function toWord(self: Itself(Succ(prev))) -> word { - let returnVal : word = ToWord.toWord(Itself.ItselfRuntimeTag:Itself(prev)); +impl ToWord> where prev: ToWord { + function toWord(self: Itself>) returns (word) { + let prevTag : Itself = Itself.ItselfRuntimeTag; + let returnVal : word = ToWord.toWord(prevTag); assembly { returnVal := add(1, returnVal) } @@ -45,25 +46,26 @@ forall prev . prev:ToWord => instance Succ(prev) : ToWord { } } -forall self . class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let val : word; assembly { val := mload(ptr) } return val; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, elem)) : IndexAccessible(word, elem) { - function at(self : memory(array(size,elem)), index : word) -> elem { - let sizeValue = ToWord.toWord(Itself.ItselfRuntimeTag:Itself(size)); +impl IndexAccessible>, word, elem> where size: ToWord, elem: MemoryType { + function at(self: memory>, index: word) returns (elem) { + let sizeTag : Itself = Itself.ItselfRuntimeTag; + let sizeValue = ToWord.toWord(sizeTag); assembly { if iszero(lt(index, sizeValue)) { @@ -71,18 +73,20 @@ forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, } } - match self { - | memory(offset) => - let x = offset; // can't use this inside the assembly block :-( + match (self) { +case memory(offset) { +let x = offset; // can't use this inside the assembly block :-( assembly { index := add(x, mul(32, index)) } return MemoryType.load(index); - } +} +} } - function set(self : memory(array(size,elem)), index : word, val : elem) -> () { - let sizeValue = ToWord.toWord(Itself.ItselfRuntimeTag:Itself(size)); + function set(self: memory>, index: word, val: elem) { + let sizeTag : Itself = Itself.ItselfRuntimeTag; + let sizeValue = ToWord.toWord(sizeTag); assembly { if iszero(lt(index, sizeValue)) { @@ -90,14 +94,15 @@ forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, } } - match self { - | memory(offset) => - let x = offset; // can't use this inside the assembly block :-( + match (self) { +case memory(offset) { +let x = offset; // can't use this inside the assembly block :-( assembly { index := add(x, mul(32, index)) } MemoryType.store(index, val); - } +} +} } } @@ -105,8 +110,8 @@ forall size elem . size : ToWord, elem:MemoryType => instance memory(array(size, contract Array { - public function main() -> word { - let arr : memory(array(Succ(Succ(Succ(Succ(Zero)))), word)) = memory(42); // = (1,2,3,4,5,6,7,8,9,10); + function main() public returns (word) { + let arr : memory>>>, word>> = memory(42); // = (1,2,3,4,5,6,7,8,9,10); IndexAccessible.set(arr, 3, 33); return IndexAccessible.at(arr, 3); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.sol index 4af0a717..8cb30c46 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-bool-lit.sol @@ -2,7 +2,7 @@ // `true` in an assembly block must type-check as `word`. Before the fix // `tcYLit YulTrue/YulFalse` called `notImplemented`, crashing the compiler. contract Test { - public function main() -> word { + function main() public returns (word) { let r : word = 0; assembly { let x := true diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.sol index 0229db02..8f35b9ac 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-let-uninit.sol @@ -3,7 +3,7 @@ // Before the fix `tcYulStmt` dropped `YLet ns Nothing`, so `x` never entered // the env and the read `r := x` failed to resolve. contract Test { - public function main() -> word { + function main() public returns (word) { let r : word = 0; assembly { let x diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.sol index 359a0249..ca2f92f6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-read.sol @@ -1,10 +1,12 @@ contract C { - function main() -> word { + function main() returns (word) { let res : word; - let foo : (word,word) = (1, 42); - match foo { - | (v0, v1) => assembly { res := v1 } - } + let foo : (word, word) = (1, 42); + match (foo) { +case (v0, v1) { +assembly { res := v1 } +} +} return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.sol index 1816e0fb..230911c2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/asm-match-tuple-write-read.sol @@ -3,16 +3,18 @@ // Runtime correctness of the write->read depends on ecSubst being updated after // the assembly block (EmitHull.hs: emitStmt MastAsm, modify ecSubst). contract C { - function main() -> word { + function main() returns (word) { let res : word; - let foo : (word,word) = (0, 0); - match foo { - | (v0, v1) => { + let foo : (word, word) = (0, 0); + match (foo) { +case (v0, v1) { +{ assembly { v1 := 42 } let x : word = v1; assembly { res := x } } - } +} +} return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.sol index 5850f0ca..5ed3d22c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/assembly.sol @@ -1,14 +1,14 @@ -forall a . class a : Mem { - function size(x : a) -> word; +trait Mem { + function size(x: a) returns (word) ; } -instance word : Mem { - function size(x : word) -> word { +impl Mem { + function size(x: word) returns (word) { return 32; } } -function foo () -> () { +function foo() { let ptr : word; let arg : word = 0; let size = Mem.size(arg); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.sol index c2f51f0c..1becf7a2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bal.sol @@ -1,12 +1,12 @@ -data Proxy (a) = Proxy ; -data dict(member, index) = dict(word, Proxy(member), Proxy(index)) ; -data address = address(word) ; -data storage(a) = storage(word) ; +enum Proxy { Proxy } +enum dict { dict(word, Proxy, Proxy) } +enum address { address(word) } +enum storage { storage(word) } -data IndexAP (m, idx, member) = IndexAP(m, idx, Proxy(member)) ; +enum IndexAP { IndexAP(m, idx, Proxy) } -function wal(ref: storage(dict(address, word)) , src : address, amt: word) -> () { - let ip = IndexAP(ref, src, Proxy : Proxy(word)); +function wal(ref: storage>, src: address, amt: word) { + let ip = IndexAP(ref, src, @word); Assign.assign(LVA.acc(ip), amt); } @@ -38,23 +38,20 @@ instance IndexAP(storage(dict(index,member)), index, member):LVA(storage(member) b5 +-> e4 should really be b5 ~ e4 */ -forall self memberRefType. -class self:LVA(memberRefType) { - function acc(x:self) -> memberRefType; +trait LVA { + function acc(x: self) returns (memberRefType) ; } -forall index member. - instance IndexAP(storage(dict(index,member)), index, member):LVA(storage(member)) { - function acc(x:IndexAP(storage(dict(index,member)), index, member)) -> storage(member) { +impl LVA>, index, member>, storage> { + function acc(x: IndexAP>, index, member>) returns (storage) { return storage(30); } } -forall lhs rhs. -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -forall a . instance storage(a):Assign(a) { - function assign(l:storage(a), y:a) -> () {} +impl Assign, a> { + function assign(l: storage, y: a) {} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.sol index 24e215e1..c522a5cd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bar.sol @@ -1,20 +1,18 @@ pragma no-coverage-condition Bar; -data Wrap(a) = Wrap(a); +enum Wrap { Wrap(a) } -forall self rep . class self : Foo(rep) {} +trait Foo {} -forall self rep . class self : Bar(rep) {} +trait Bar {} -forall a b . a : Foo(b) => instance Wrap(a) : Bar(b) {} +impl Bar, b> where a: Foo {} -forall a rep . Wrap(a) : Bar(rep) => -function need_bar(x : Wrap(a)) -> () { +function need_bar(x: Wrap) where Wrap: Bar { return (); } -forall a . a : Foo(word) => -function use_bar(x : Wrap(a)) -> () { +function use_bar(x: Wrap) where a: Foo { need_bar(x); return (); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.sol index a68ad730..480b72df 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bitwise.sol @@ -1,4 +1,4 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -7,13 +7,13 @@ pragma no-bounded-variable-condition ; // `^=` / `&=` / `|=` compound assignments and the unary `~=` in-place // complement, plus the bxorWord / bandWord / borWord / bnotWord constant // folding (mirrors gtWord). -function fxor(x: word, y: word) -> word { +function fxor(x: word, y: word) returns (word) { let acc : word = x ^ y; acc ^= x; // acc = (x ^ y) ^ x == y return acc ^ 0; // identity: a ^ 0 == a } -function fbitwise(x: word, y: word) -> word { +function fbitwise(x: word, y: word) returns (word) { let acc : word = x & y; acc |= x; // acc = (x & y) | x == x acc &= y; // acc = x & y @@ -22,7 +22,7 @@ function fbitwise(x: word, y: word) -> word { // `~x` complements every bit, so `~(~x) == x` and `x & ~0 == x` (`~0` is // all ones, the AND identity). -function fnot(x: word) -> word { +function fnot(x: word) returns (word) { let acc : word = ~x; // acc = ~x acc ~=; // acc = ~(~x) == x (in-place `~=`) return acc & ~0; // identity: a & ~0 == a @@ -31,5 +31,5 @@ function fnot(x: word) -> word { contract Bitwise { // fxor(5, 3) == 3, fbitwise(6, 3) == 2, fnot(4) == 4; // 3 ^ 2 ^ 4 == 5 — folded at compile time. - public function main() -> word { return fxor(5, 3) ^ fbitwise(6, 3) ^ fnot(4); } + function main() public returns (word) { return fxor(5, 3) ^ fbitwise(6, 3) ^ fnot(4); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.sol index c1236689..5332ab74 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bool-elim.sol @@ -1,14 +1,18 @@ -data Bool = False | True; +enum Bool { False, True } - function second(x : Bool, y : word) -> word { - match x, y { - | Bool.True, z => return z; - | Bool.False, z => return z; - } + function second(x: Bool, y: word) returns (word) { + match (x, y) { +case (Bool.True, z) { +return z; +} +case (Bool.False, z) { +return z; +} +} } contract Second { - public function main() -> word { + function main() public returns (word) { second(Bool.True, 42) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.sol index 661e8588..9b491034 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-merge-case.sol @@ -2,4 +2,4 @@ //pragma no-bounded-variable-condition TestClassB1; // === Test Classes === -forall a . class a:TestClassP1 {} +trait TestClassP1 {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.sol index 3f668786..0ff81f0d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bound-with-pragma.sol @@ -4,11 +4,11 @@ pragma no-bounded-variable-condition TestBound; pragma no-patterson-condition TestBound; // Also disable Patterson to avoid that error -forall a . class a:TestBound {} -forall a b . class a:TestHelper(b) {} +trait TestBound {} +trait TestHelper {} -data TestType(x) = TestType; +enum TestType { TestType } // Variable 'bad' appears in context but not in instance head // But pragma disables the check, so should pass -forall x bad . bad:TestHelper(x) => instance TestType(x):TestBound {} +impl TestBound> where bad: TestHelper {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.sol index f6736f77..ef8d7fce 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-call-expected-nontail-return.sol @@ -7,32 +7,33 @@ // type is discarded, so the expected type has to reach the call itself. // Without that, `pick` fails to compile with an ambiguous `a:FromWord`. -data Box(a) = Box(a); +enum Box { Box(a) } -forall a. -class a:FromWord { - function fromWord(x: word) -> a; +trait FromWord { + function fromWord(x: word) returns (a) ; } -instance Box(word):FromWord { - function fromWord(x: word) -> Box(word) { +impl FromWord> { + function fromWord(x: word) returns (Box) { return Box(x); } } -function pick(cond: bool, w: word) -> Box(word) { +function pick(cond: bool, w: word) returns (Box) { if (cond) { return FromWord.fromWord(w); } return Box(w); } -function unbox(b: Box(word)) -> word { - match b { - | Box(x) => return x; - } +function unbox(b: Box) returns (word) { + match (b) { +case Box(x) { +return x; +} +} } contract CallExpectedNonTailReturn { - function main() -> word { + function main() returns (word) { return unbox(pick(true, 42)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol index 8425be2d..3048b4e2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol @@ -1,8 +1,8 @@ pragma no-patterson-condition ABIAttribs, ABIEncode; pragma no-bounded-variable-condition ABIAttribs, ABIEncode; -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; // Minimal reproducer for the "imported-default-instance-stub mis-tagged" bug. // From 871e27c30ca71ee1046d8cf807c873719db04459 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 068/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../cases/bug-import-default-inst-shadow.sol | 7 +-- .../examples/cases/bug-rep-name-capture.sol | 6 +- .../ok/test/examples/cases/catch-all.sol | 18 +++--- .../ok/test/examples/cases/class-context.sol | 5 +- .../ok/test/examples/cases/clone-deriving.sol | 17 +++--- .../examples/cases/closure-capture-only.sol | 4 +- .../cases/closure-free-bound-test.sol | 2 +- .../examples/cases/closure-free-var-local.sol | 4 +- .../examples/cases/closure-free-var-std.sol | 6 +- .../test/examples/cases/closure-free-var.sol | 14 ++--- .../corpus/ok/test/examples/cases/closure.sol | 2 +- .../ok/test/examples/cases/comparisons.sol | 6 +- .../ok/test/examples/cases/compose0.sol | 2 +- .../examples/cases/compound-operators.sol | 6 +- .../corpus/ok/test/examples/cases/const.sol | 4 +- .../cases/constrained-instance-context.sol | 26 +++++---- .../examples/cases/constrained-instance.sol | 26 +++++---- .../examples/cases/constructor-weak-args.sol | 6 +- .../examples/cases/contract-local-derive.sol | 8 +-- .../cases/contract-local-type-same-name.sol | 34 ++++++----- .../ok/test/examples/cases/copytomem.sol | 14 +++-- .../examples/cases/cyclical-defs-inferred.sol | 6 +- .../ok/test/examples/cases/cyclical-defs.sol | 10 ++-- .../examples/cases/derive-custom-hash.sol | 57 ++++++++++--------- .../test/examples/cases/derive-eq-action.sol | 12 ++-- .../ok/test/examples/cases/derive-eq-enum.sol | 24 ++++---- .../ok/test/examples/cases/derive-eq-pair.sol | 18 +++--- .../cases/derive-generic-excluded.sol | 45 ++++++++------- .../examples/cases/derive-generic-sum.sol | 48 +++++++++------- .../cases/derive-universe-instances.sol | 28 ++++----- .../examples/cases/deriving-empty-type.sol | 6 +- .../dot-expression-assignment-context.sol | 6 +- .../cases/dot-expression-call-arg-context.sol | 18 +++--- .../cases/dot-expression-constructor.sol | 18 +++--- .../cases/dot-expression-match-return.sol | 22 ++++--- .../cases/dot-expression-nested-context.sol | 4 +- .../cases/dot-pattern-constructor.sol | 18 +++--- .../cases/dot-pattern-nested-constructor.sol | 30 ++++++---- .../cases/dot-primitive-constructor.sol | 14 +++-- .../ok/test/examples/cases/empty-asm.sol | 15 +++-- .../corpus/ok/test/examples/cases/encoder.sol | 44 ++++++++------ .../ok/test/examples/cases/encoder1.sol | 24 ++++---- .../cases/false-redundant-warning.sol | 22 ++++--- .../cases/field-helper-cxt-collision.sol | 6 +- .../test/examples/cases/field-name-error.sol | 4 +- .../ok/test/examples/cases/foo-class.sol | 5 +- .../test/examples/cases/for-body-shadow.sol | 4 +- .../ok/test/examples/cases/for-break.sol | 4 +- .../ok/test/examples/cases/for-continue.sol | 4 +- .../ok/test/examples/cases/for-empty-init.sol | 4 +- .../test/examples/cases/for-init-shadow.sol | 4 +- .../test/examples/cases/for-inner-block.sol | 4 +- .../corpus/ok/test/examples/cases/for-let.sol | 4 +- .../ok/test/examples/cases/for-loop.sol | 4 +- .../ok/test/examples/cases/for-multi-init.sol | 4 +- .../ok/test/examples/cases/for-multi-post.sol | 4 +- .../examples/cases/fresh-pat-arg-synonym.sol | 4 +- .../ok/test/examples/cases/fresh-pat-arg.sol | 6 +- .../cases/fresh-variable-shadowing.sol | 18 +++--- .../ok/test/examples/cases/if-examples.sol | 26 +++++---- .../ok/test/examples/cases/import-std.sol | 2 +- .../ok/test/examples/cases/inc-closure.sol | 4 +- .../examples/cases/instance-closure-error.sol | 8 +-- .../examples/cases/instance-synonym-int.sol | 11 ++-- .../test/examples/cases/instance-synonym.sol | 10 ++-- .../test/examples/cases/invokable-issue.sol | 16 +++--- .../corpus/ok/test/examples/cases/ixa.sol | 34 +++++------ 67 files changed, 494 insertions(+), 406 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol index 3048b4e2..5925aad6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-import-default-inst-shadow.sol @@ -6,7 +6,7 @@ import * from std.Generic; // Minimal reproducer for the "imported-default-instance-stub mis-tagged" bug. // -// std/Generic.solc exports: +// std/Generic.sol exports: // forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => // default instance a : ABIEncode { function encodeInto ... } // @@ -24,9 +24,8 @@ import * from std.Generic; // 4. tcTopDeclWithVisibility calls tcTopDecl' on the stub (funs = []). // 5. tcInstance' -> checkCompleteInstDef -> "Incomplete definition for ABIEncode". -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -default instance a : ABIEncode { - function encodeInto(x : a, basePtr : word, offset : word, tail : word) -> word { +default impl ABIEncode where a: Generic, rep: ABIAttribs, rep: ABIEncode { + function encodeInto(x: a, basePtr: word, offset: word, tail: word) returns (word) { return ABIEncode.encodeInto(Generic.from(x), basePtr, offset, tail); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.sol index 953fdb33..13736195 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/bug-rep-name-capture.sol @@ -7,8 +7,8 @@ // Expected: compiles successfully; `Typedef.rep` resolves to the class method. // Actual (before fix): PANIC: no resolution found for invokable.invoke -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-patterson-condition; pragma no-coverage-condition; pragma no-bounded-variable-condition; @@ -16,7 +16,7 @@ pragma no-bounded-variable-condition; contract Bug { constructor() {} - function f(a : uint256) -> uint256 { + function f(a: uint256) returns (uint256) { let rep : uint256 = a; let w : word = Typedef.rep(a); return Typedef.abs(w); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.sol index a3fd9f8b..c78083ce 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/catch-all.sol @@ -1,14 +1,18 @@ -data Bool = False | True; +enum Bool { False, True } contract CatchAll { - public function catchAll(x : Bool, y : Bool) -> Bool{ - match x, y { - | Bool.True, Bool.True => return Bool.True; - | z, w => return z; - } + function catchAll(x: Bool, y: Bool) public returns (Bool) { + match (x, y) { +case (Bool.True, Bool.True) { +return Bool.True; +} +case (z, w) { +return z; +} +} } - public function main() -> Bool { + function main() public returns (Bool) { catchAll(Bool.True, Bool.False) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.sol index 8a2477c7..85444e7e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/class-context.sol @@ -1,4 +1,3 @@ -forall self fieldType offsetType -. class self:CStructField(fieldType, offsetType) { - function offsetSize(s: self) -> word; +trait CStructField { + function offsetSize(s: self) returns (word) ; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.sol index 0d5faedd..ffbf9a18 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/clone-deriving.sol @@ -1,21 +1,20 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a. -class a : Clone { - function clone(x : a) -> a; +trait Clone { + function clone(x: a) returns (a) ; } -instance word : Clone { - function clone(x : word) -> word { return x; } +impl Clone { + function clone(x: word) returns (word) { return x; } } #[derive(Clone)] -data Box = Box(word); +enum Box { Box(word) } -function cloneBox(x : Box) -> Box { +function cloneBox(x: Box) returns (Box) { return Clone.clone(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.sol index 96228cd1..199845cb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-capture-only.sol @@ -1,7 +1,7 @@ -function testApplied(x: word) -> word { +function testApplied(x: word) returns (word) { return x; } -function main() -> word { +function main() returns (word) { return testApplied(1); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.sol index 6ffc20ca..434fdc31 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-bound-test.sol @@ -1,4 +1,4 @@ -function foo (b : bool) -> () { +function foo(b: bool) { let y:word; let f = lam(x : word) { if (b) { let z : word = 7; y = z; } else {x = 1;} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.sol index a396740c..398a2cd6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-local.sol @@ -1,4 +1,4 @@ -function test() -> word { +function test() returns (word) { let f = lam (x: word) -> word { let y : word = 42; return y; @@ -7,7 +7,7 @@ function test() -> word { } contract C { - public function main() -> word { + function main() public returns (word) { return test(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.sol index 8ce806b8..352e4a08 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var-std.sol @@ -1,14 +1,14 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract Bug { - public function main() -> word { + function main() public returns (word) { return makeClosure(42); } - public function makeClosure(e : word) -> word { + function makeClosure(e: word) public returns (word) { let f = lam (x : word) { return e + x; // Uses Add.add typeclass method }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.sol index dd29195b..b866c6c6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure-free-var.sol @@ -1,4 +1,4 @@ -function addW (l: word, r: word) -> word { +function addW(l: word, r: word) returns (word) { let rw : word; assembly { rw := add(l,r) @@ -6,20 +6,20 @@ function addW (l: word, r: word) -> word { return rw; } -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -instance word:Add { - function add(l: word, r: word) -> word { return addW(l,r); } +impl Add { + function add(l: word, r: word) returns (word) { return addW(l,r); } } contract Bug { - public function main() -> word { + function main() public returns (word) { return makeClosure(42); } - public function makeClosure(e : word) -> word { + function makeClosure(e: word) public returns (word) { let f = lam (x : word) { return Add.add(x,e); // this crashes // return addW(e,x); // this works diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.sol index 497d5acc..9c5441d8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/closure.sol @@ -1,4 +1,4 @@ - function foo (z : word, k : (), a : word) -> word { + function foo(z: word, k: (), a: word) returns (word) { let f = lam (x : word, y : word) { k; return primAddWord(a,primAddWord(y,z)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.sol index 98608204..c524956f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/comparisons.sol @@ -1,8 +1,8 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function f(x: word, y:word) -> bool { +function f(x: word, y: word) returns (bool) { return (!((x == y) && (x != y) && (x >= y) @@ -13,5 +13,5 @@ function f(x: word, y:word) -> bool { } contract Comparisons { - public function main() -> bool { return f(0,1); } + function main() public returns (bool) { return f(0,1); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.sol index 10a70385..485e35fa 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compose0.sol @@ -1,4 +1,4 @@ -forall a b c . function compose (f : (b) -> c,g : (a) -> b) -> ((a) -> c) { +function compose(f: function(b) returns (c), g: function(a) returns (b)) returns (function(a) returns (c)) { return lam (x) { return f(g(x)); }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.sol index 44f4a082..54196425 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/compound-operators.sol @@ -1,4 +1,4 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -10,7 +10,7 @@ pragma no-bounded-variable-condition ; // ^= &= |= (bitwise: BitXor / BitAnd / BitOr) // ~= (unary bitwise NOT: BitNot, `acc ~=` -> `acc := ~acc`) // each binary `lhs op= rhs` desugars to `lhs := lhs op rhs`. -function f(x: word) -> word { +function f(x: word) returns (word) { let acc : word = x; // 6 acc += 4; // 10 acc -= 3; // 7 @@ -27,5 +27,5 @@ function f(x: word) -> word { contract CompoundOperators { // f(6) == 3 — folded at compile time. - public function main() -> word { return f(6); } + function main() public returns (word) { return f(6); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.sol index 0871138b..a36e76d0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/const.sol @@ -1,9 +1,9 @@ -function constApplied(x : word, y : word) -> word { +function constApplied(x: word, y: word) returns (word) { return y; } contract Foo { - public function main () -> word { + function main() public returns (word) { return constApplied(0,1); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.sol index 8a6781cb..fc96451e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance-context.sol @@ -1,25 +1,27 @@ -data memory(t) = memory(word); +enum memory { memory(word) } -forall t . class t:ValueTy { - function rep(x:t) -> word; +trait ValueTy { + function rep(x: t) returns (word) ; } -forall t . instance memory(t) : ValueTy { - function rep(x: memory(t)) -> word { - match x { - | memory(w) => return w; - } +impl ValueTy> { + function rep(x: memory) returns (word) { + match (x) { +case memory(w) { +return w; +} +} } } -forall ref deref . class ref:Ref(deref) { - function store(loc: ref, value: deref) -> (); +trait Ref { + function store(loc: ref, value: deref) ; } -forall t . t : ValueTy => instance memory(t) : Ref(t) { - function store(loc: memory(t), value: t) -> () { +impl Ref, t> where t: ValueTy { + function store(loc: memory, value: t) { // We don't have a `ValueTy` bound on `t` anywhere, so this should raise a type error... let vw = ValueTy.rep(value); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.sol index 9ae0ccb4..49f85904 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constrained-instance.sol @@ -1,24 +1,26 @@ -data memory(t) = memory(word); +enum memory { memory(word) } -forall t . class t:ValueTy { - function rep(x:t) -> word; +trait ValueTy { + function rep(x: t) returns (word) ; } -forall t . instance memory(t) : ValueTy { - function rep(x: memory(t)) -> word { - match x { - | memory(w) => return w; - } +impl ValueTy> { + function rep(x: memory) returns (word) { + match (x) { +case memory(w) { +return w; +} +} } } -forall ref deref . class ref:Ref(deref) { - function store(loc: ref, value: deref) -> (); +trait Ref { + function store(loc: ref, value: deref) ; } -forall t . t : ValueTy => instance memory(t) : Ref(t) { - function store(loc: memory(t), value: t) -> () { +impl Ref, t> where t: ValueTy { + function store(loc: memory, value: t) { // We don't have a `ValueTy` bound on `t` anywhere, so this should raise a type error... let vw = ValueTy.rep(value); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.sol index 4f2ee34b..0ba6be42 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/constructor-weak-args.sol @@ -1,7 +1,7 @@ -forall ref deref . class ref:Loadable (deref) { - function load (r : ref) -> deref; +trait Loadable { + function load(r: ref) returns (deref) ; } -forall t . t : Loadable(word) => function foo(v : t) -> word { +function foo(v: t) returns (word) where t: Loadable { return Loadable.load(v); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.sol index bb6c24f3..ac98da5b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-derive.sol @@ -1,14 +1,14 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; contract ContractLocalDerive { #[derive(Eq)] - data Color = Red | Green; + enum Color { Red, Green } - public function same() -> bool { + function same() public returns (bool) { return Eq.eq(Color.Red, Color.Red); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.sol index 4473b0ba..b66419d0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/contract-local-type-same-name.sol @@ -3,26 +3,34 @@ // declarations are distinct and neither the type names nor the constructor // names collide. If they aliased to a single `T`, one contract's `match` would // fail to find its constructors. -import std.{*}; +import * from std; contract A { - data T = Foo | Bar; + enum T { Foo, Bar } - public function pickA() -> word { - match T.Foo { - | T.Foo => return 1; - | T.Bar => return 2; - } + function pickA() public returns (word) { + match (T.Foo) { +case T.Foo { +return 1; +} +case T.Bar { +return 2; +} +} } } contract B { - data T = Baz | Qux; + enum T { Baz, Qux } - public function pickB() -> word { - match T.Qux { - | T.Baz => return 3; - | T.Qux => return 4; - } + function pickB() public returns (word) { + match (T.Qux) { +case T.Baz { +return 3; +} +case T.Qux { +return 4; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.sol index b37fb5b8..68ae5d88 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/copytomem.sol @@ -1,13 +1,15 @@ -data MemoryWordReader = MemoryWordReader(word); +enum MemoryWordReader { MemoryWordReader(word) } -function copyToMem(reader:MemoryWordReader, dst:word, cnt: word) -> () { - match reader { - | MemoryWordReader(ptr) => assembly { mcopy(dst, ptr, cnt) } - } +function copyToMem(reader: MemoryWordReader, dst: word, cnt: word) { + match (reader) { +case MemoryWordReader(ptr) { +assembly { mcopy(dst, ptr, cnt) } +} +} } contract Main { - public function main() -> () { + function main() public { let r : MemoryWordReader = MemoryWordReader(42); copyToMem(r, 0, 32); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.sol index 4304a96b..3c54829e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs-inferred.sol @@ -1,12 +1,12 @@ -function foo(x : word) -> word { +function foo(x: word) returns (word) { return bar(x); } -function bar(x : word) -> word { +function bar(x: word) returns (word) { return foo(x); } contract C { - public function main() -> word { + function main() public returns (word) { return foo(1); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.sol index 9c31ed61..ce57434e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/cyclical-defs.sol @@ -1,18 +1,18 @@ -function foo(x : word) -> word { +function foo(x: word) returns (word) { return bar(x); } -function bar(x : word) -> word { +function bar(x: word) returns (word) { return foo(x); } contract C { - public function m(x : word) -> word { + function m(x: word) public returns (word) { return n(x); } - public function n(x : word) -> word { + function n(x: word) public returns (word) { return m(x); } - public function main() -> word { + function main() public returns (word) { return m(1); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.sol index d3a7c440..0ac6127a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-custom-hash.sol @@ -1,52 +1,55 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a. -class a : Hash { - function hash(x : a) -> word; +trait Hash { + function hash(x: a) returns (word) ; } -instance word : Hash { - function hash(x : word) -> word { return x; } +impl Hash { + function hash(x: word) returns (word) { return x; } } -instance () : Hash { - function hash(x : ()) -> word { return 0; } +impl Hash<()> { + function hash(x: ()) returns (word) { return 0; } } -forall f g . f:Hash, g:Hash => -instance sum(f, g) : Hash { - function hash(x : sum(f, g)) -> word { - match x { - | inl(u) => return Hash.hash(u); - | inr(v) => return Hash.hash(v) + 1; - } +impl Hash> where f: Hash, g: Hash { + function hash(x: sum) returns (word) { + match (x) { +case inl(u) { +return Hash.hash(u); +} +case inr(v) { +return Hash.hash(v) + 1; +} +} } } -forall f g . f:Hash, g:Hash => -instance (f, g) : Hash { - function hash(x : (f, g)) -> word { - match x { - | (u, v) => return Hash.hash(u) * 31 + Hash.hash(v); - } +impl Hash<(f, g)> where f: Hash, g: Hash { + function hash(x: (f, g)) returns (word) { + match (x) { +case (u, v) { +return Hash.hash(u) * 31 + Hash.hash(v); +} +} } } #[derive(Hash)] -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } #[derive(Hash)] -data Pair(a, b) = Pair(a, b); +enum Pair { Pair(a, b) } -function hashRed() -> word { +function hashRed() returns (word) { return Hash.hash(Color.Red); } -function hashPair() -> word { - let p : Pair(word, word) = Pair(3, 7); +function hashPair() returns (word) { + let p : Pair = Pair(3, 7); return Hash.hash(p); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.sol index 0b47064b..b972a5b5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-action.sol @@ -1,21 +1,21 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq, Ord)] -data Action = Transfer(word, word) | Approve(word); +enum Action { Transfer(word, word), Approve(word) } -function sameTransfer() -> bool { +function sameTransfer() returns (bool) { return Eq.eq(Action.Transfer(1, 100), Action.Transfer(1, 100)); } -function transferLtApprove() -> bool { +function transferLtApprove() returns (bool) { return Ord.gt(Action.Approve(1), Action.Transfer(1, 100)); } // Within the same constructor fields compare left to right. -function amountsCompare() -> bool { +function amountsCompare() returns (bool) { return Ord.gt(Action.Transfer(1, 100), Action.Transfer(1, 50)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.sol index fec8ff02..85f2fcd3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-enum.sol @@ -1,23 +1,27 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq, Ord)] -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } -function sameColor() -> bool { +function sameColor() returns (bool) { return Eq.eq(Color.Red, Color.Red); } -function diffColor() -> bool { +function diffColor() returns (bool) { return ne(Color.Red, Color.Blue); } -function ordering() -> bool { - match Ord.gt(Color.Green, Color.Red) { - | true => return not(Ord.gt(Color.Red, Color.Green)); - | false => return false; - } +function ordering() returns (bool) { + match (Ord.gt(Color.Green, Color.Red)) { +case true { +return not(Ord.gt(Color.Red, Color.Green)); +} +case false { +return false; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.sol index 9a812a30..28ae5b3e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-eq-pair.sol @@ -1,20 +1,20 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq)] -data Pair(a, b) = Pair(a, b); +enum Pair { Pair(a, b) } -function samePair() -> bool { - let p : Pair(word, word) = Pair(1, 2); - let q : Pair(word, word) = Pair(1, 2); +function samePair() returns (bool) { + let p : Pair = Pair(1, 2); + let q : Pair = Pair(1, 2); return Eq.eq(p, q); } -function diffPair() -> bool { - let p : Pair(word, word) = Pair(1, 2); - let q : Pair(word, word) = Pair(1, 3); +function diffPair() returns (bool) { + let p : Pair = Pair(1, 2); + let q : Pair = Pair(1, 3); return ne(p, q); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.sol index 784f244c..5d5d922e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-excluded.sol @@ -2,38 +2,43 @@ // listed types. Pair has its instance suppressed and provided manually; // Box gets its instance generated automatically. -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-generic-instance-for Pair; -data Pair(a, b) = MkPair(a, b); +enum Pair { MkPair(a, b) } -data Box(a) = MkBox(a); +enum Box { MkBox(a) } // Manual instance for Pair (suppressed from auto-derivation). -forall a b. -instance Pair(a, b) : Generic((a, b)) { - function from(p : Pair(a, b)) -> (a, b) { - match p { - | Pair.MkPair(x, y) => return (x, y); - } +impl Generic, (a, b)> { + function from(p: Pair) returns (a, b) { + match (p) { +case Pair.MkPair(x, y) { +return (x, y); +} +} } - function to(t : (a, b)) -> Pair(a, b) { - match t { - | (x, y) => return Pair.MkPair(x, y); - } + function to(t: (a, b)) returns (Pair) { + match (t) { +case (x, y) { +return Pair.MkPair(x, y); +} +} } } // Box gets its Generic instance auto-derived (not excluded). -function boxRoundtrip(v : word) -> bool { - let b : Box(word) = Box.MkBox(v); +function boxRoundtrip(v: word) returns (bool) { + let b : Box = Box.MkBox(v); let r : word = Generic.from(b); - let b2 : Box(word) = Generic.to(r); - match b2 { - | Box.MkBox(v2) => return eqWord(v, v2); - } + let b2 : Box = Generic.to(r); + match (b2) { +case Box.MkBox(v2) { +return eqWord(v, v2); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.sol index aa93b560..35842af3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-generic-sum.sol @@ -2,33 +2,41 @@ // Neither Option nor Tree has an explicit Generic instance; both should be // generated automatically by DeriveGeneric. -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; -data Option(a) = None | Some(a); +enum Option { None, Some(a) } -data Tree(a) = Leaf | Node(Tree(a), a, Tree(a)); +enum Tree { Leaf, Node(Tree, a, Tree) } // Use the auto-derived instances to check that from/to round-trip. -function roundtripNone() -> bool { - let x : Option(word) = Option.None; - let r : sum((), word) = Generic.from(x); - let x2 : Option(word) = Generic.to(r); - match x2 { - | Option.None => return true; - | Option.Some(_) => return false; - } +function roundtripNone() returns (bool) { + let x : Option = Option.None; + let r : sum<(), word> = Generic.from(x); + let x2 : Option = Generic.to(r); + match (x2) { +case Option.None { +return true; +} +case Option.Some(_) { +return false; +} +} } -function roundtripSome(v : word) -> bool { - let x : Option(word) = Option.Some(v); - let r : sum((), word) = Generic.from(x); - let x2 : Option(word) = Generic.to(r); - match x2 { - | Option.None => return false; - | Option.Some(v2) => return eqWord(v, v2); - } +function roundtripSome(v: word) returns (bool) { + let x : Option = Option.Some(v); + let r : sum<(), word> = Generic.from(x); + let x2 : Option = Generic.to(r); + match (x2) { +case Option.None { +return false; +} +case Option.Some(v2) { +return eqWord(v, v2); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.sol index 12a9795a..94a1b8bb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/derive-universe-instances.sol @@ -1,39 +1,39 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; -function eqUnit() -> bool { +function eqUnit() returns (bool) { let u : () = (); return Eq.eq(u, u); } -function eqInl() -> bool { - let x : sum(word, word) = inl(1); - let y : sum(word, word) = inl(1); +function eqInl() returns (bool) { + let x : sum = inl(1); + let y : sum = inl(1); return Eq.eq(x, y); } -function neqTags() -> bool { - let x : sum(word, word) = inl(1); - let y : sum(word, word) = inr(1); +function neqTags() returns (bool) { + let x : sum = inl(1); + let y : sum = inr(1); return ne(x, y); } -function ordInlLtInr() -> bool { - let x : sum(word, word) = inl(1); - let y : sum(word, word) = inr(1); +function ordInlLtInr() returns (bool) { + let x : sum = inl(1); + let y : sum = inr(1); return not(Ord.gt(x, y)); } -function eqPair() -> bool { +function eqPair() returns (bool) { let p : (word, word) = (1, 2); let q : (word, word) = (1, 2); return Eq.eq(p, q); } -function ordPairLex() -> bool { +function ordPairLex() returns (bool) { let p : (word, word) = (1, 100); let q : (word, word) = (1, 50); return Ord.gt(p, q); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.sol index d9f993ac..79517d6d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/deriving-empty-type.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq)] -data Void; +enum Void {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.sol index 6037f00a..724fdc67 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-assignment-context.sol @@ -1,7 +1,7 @@ -data Option(a) = Some(a) | None; +enum Option { Some(a), None } -function main() -> Option(word) { - let x : Option(word); +function main() returns (Option) { + let x : Option; x = .None; return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.sol index ba4781ed..43925fe1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-call-arg-context.sol @@ -1,12 +1,16 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function use(x: Option) -> word { - match x { - | Option.Some(v) => return v; - | Option.None => return 0; - } +function use(x: Option) returns (word) { + match (x) { +case Option.Some(v) { +return v; +} +case Option.None { +return 0; +} +} } -function main() -> word { +function main() returns (word) { return use(.Some(7)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.sol index 5163ac1c..192427e5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-constructor.sol @@ -1,12 +1,16 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function mkSome(x: word) -> Option { +function mkSome(x: word) returns (Option) { return .Some(x); } -function main() -> word { - match mkSome(7) { - | Option.Some(v) => return v; - | Option.None => return 0; - } +function main() returns (word) { + match (mkSome(7)) { +case Option.Some(v) { +return v; +} +case Option.None { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.sol index 26f6c946..0eabf9ee 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-match-return.sol @@ -1,13 +1,17 @@ -data Bar = Foo(word); +enum Bar { Foo(word) } -function x(x: Bar) -> Bar { - match x { - | .Foo(w) => return .Foo(w); - } +function x(x: Bar) returns (Bar) { + match (x) { +case .Foo(w) { +return .Foo(w); +} +} } -function main() -> word { - match x(Bar.Foo(7)) { - | Bar.Foo(w) => return w; - } +function main() returns (word) { + match (x(Bar.Foo(7))) { +case Bar.Foo(w) { +return w; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.sol index 97d6f177..effe5742 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-expression-nested-context.sol @@ -1,5 +1,5 @@ -data Option(a) = Some(a) | None; +enum Option { Some(a), None } -function main() -> Option(Option(word)) { +function main() returns (Option>) { return .Some(.None); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.sol index 0f204633..94b372b1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-constructor.sol @@ -1,12 +1,16 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function fromOption(x: Option) -> word { - match x { - | .Some(v) => return v; - | .None => return 0; - } +function fromOption(x: Option) returns (word) { + match (x) { +case .Some(v) { +return v; +} +case .None { +return 0; +} +} } -function main() -> word { +function main() returns (word) { return fromOption(Option.Some(3)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.sol index 10cb4a89..6258de0c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-pattern-nested-constructor.sol @@ -1,15 +1,23 @@ -data Option(a) = None | Some(a); +enum Option { None, Some(a) } -function join(mmx: Option(Option(word))) -> Option(word) { - match mmx { - | .Some(.Some(x)) => return .Some(x); - | _ => return .None; - } +function join(mmx: Option>) returns (Option) { + match (mmx) { +case .Some(.Some(x)) { +return .Some(x); +} +default { +return .None; +} +} } -function main() -> word { - match join(.Some(.Some(9))) { - | .Some(v) => return v; - | .None => return 0; - } +function main() returns (word) { + match (join(.Some(.Some(9)))) { +case .Some(v) { +return v; +} +case .None { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.sol index fb935c67..a3ba9b4b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/dot-primitive-constructor.sol @@ -1,7 +1,11 @@ -function main() -> word { +function main() returns (word) { let b: bool = .true; - match b { - | .true => return 1; - | .false => return 0; - } + match (b) { +case .true { +return 1; +} +case .false { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.sol index 7c288305..13a60f78 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/empty-asm.sol @@ -1,9 +1,12 @@ -function f(x : word) -> word { - match x { - | 0 => - let ret : word; +function f(x: word) returns (word) { + match (x) { +case 0 { +let ret : word; assembly {} return ret; - | _ => return 0; - } +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.sol index bc470ddd..8bc7bff1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder.sol @@ -1,35 +1,45 @@ -data TagA = TagA(word); -data TagB = TagB(word); +enum TagA { TagA(word) } +enum TagB { TagB(word) } -forall self rep. -class self:Tag(rep) { - function getTag(x:self) -> rep; +trait Tag { + function getTag(x: self) returns (rep) ; } -data TypeA = TypeA(word); -instance TypeA:Tag(TagA) { - function getTag(x:TypeA) -> TagA { - match x { | TypeA(w) => return TagA(w); } +enum TypeA { TypeA(word) } +impl Tag { + function getTag(x: TypeA) returns (TagA) { + match (x) { +case TypeA(w) { +return TagA(w); +} +} } } -data TypeB = TypeB(word); -instance TypeB:Tag(TagB) { - function getTag(x:TypeB) -> TagB { - match x { | TypeB(w) => return TagB(w); } +enum TypeB { TypeB(word) } +impl Tag { + function getTag(x: TypeB) returns (TagB) { + match (x) { +case TypeB(w) { +return TagB(w); +} +} } } -forall a b rep1 rep2 . a:Tag(rep1), b:Tag(rep2) => -function tagFirst(x:a, y:b) -> rep1 { +function tagFirst(x: a, y: b) returns (rep1) where a: Tag, b: Tag { return Tag.getTag(x); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { let r : TagA = tagFirst(TypeA(42), TypeB(7)); - match r { | TagA(w) => return w; } + match (r) { +case TagA(w) { +return w; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.sol index ac418562..f2418c53 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/encoder1.sol @@ -1,25 +1,27 @@ -import std.{*}; +import * from std; -forall self rep. -class self:Encoder(rep) { - function encode(x:self, hint:word) -> rep; +trait Encoder { + function encode(x: self, hint: word) returns (rep) ; } -data Foo = Foo(word); -instance Foo:Encoder(word) { - function encode(x:Foo, hint:word) -> word { - match x { | Foo(w) => return w; } +enum Foo { Foo(word) } +impl Encoder { + function encode(x: Foo, hint: word) returns (word) { + match (x) { +case Foo(w) { +return w; +} +} } } -forall a rep . a:Encoder(rep) => -function encodeAndDiscard(x:a) -> () { +function encodeAndDiscard(x: a) where a: Encoder { let enc : rep = Encoder.encode(x, 0); return (); } contract C { - public function main() -> word { + function main() public returns (word) { encodeAndDiscard(Foo(42)); return 0; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.sol index 88f95679..4cf0da15 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/false-redundant-warning.sol @@ -1,15 +1,21 @@ -data Bool = False | True; +enum Bool { False, True } -function test(x : Bool, y : Bool) -> Bool { - match x, y { - | Bool.True, z => return z; - | w, Bool.True => return w; - | a, b => return b; - } +function test(x: Bool, y: Bool) returns (Bool) { + match (x, y) { +case (Bool.True, z) { +return z; +} +case (w, Bool.True) { +return w; +} +case (a, b) { +return b; +} +} } contract FalseRedundantWarning { - public function main() -> Bool { + function main() public returns (Bool) { test(Bool.False, Bool.True) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.sol index 994f6568..06e40161 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-helper-cxt-collision.sol @@ -1,14 +1,14 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -data FooCxt = FooCxt; +enum FooCxt { FooCxt } contract Foo { x: word; - public function get() -> word { + function get() public returns (word) { return x; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.sol index fd1bc3c5..5cdbf428 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/field-name-error.sol @@ -1,4 +1,4 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -6,7 +6,7 @@ pragma no-bounded-variable-condition ; contract PoC { x : word; - public function main () -> word { + function main() public returns (word) { return 0; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.sol index bb78a2ef..7b67326d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/foo-class.sol @@ -1,4 +1,3 @@ -forall b self . -class self:Foo(b) { - function foo(x:self) -> b; +trait Foo { + function foo(x: self) returns (b) ; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.sol index 94fc9fc8..a1f60bb2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-body-shadow.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract C { - public function main() -> word { + function main() public returns (word) { let x : word = 100; let i : word = 0; let s : word = 0; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol index 79e827d9..a4ef2ad9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-break.sol @@ -1,6 +1,6 @@ -import std.{lt,Ord,Add,Sub,Bounded,Num,Eq,Typedef}; +import {lt,Ord,Add,Sub,Bounded,Num,Eq,Typedef} from std; contract BreakTest { - public function main() -> word { + function main() public returns (word) { let result : word = 0; for (let i : word = 0; i < 10; i = i + 1) { if (i == 5) { diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.sol index 03c68ed3..acf93627 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-continue.sol @@ -1,6 +1,6 @@ -import std.{lt,Ord,Add,Sub,Bounded,Num,Eq,Typedef}; +import {lt,Ord,Add,Sub,Bounded,Num,Eq,Typedef} from std; contract ContinueTest { - public function main() -> word { + function main() public returns (word) { let result : word = 0; for (let i : word = 0; i < 10; i = i + 1) { if (i < 5) { diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.sol index 5bbaa539..008a0e99 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-empty-init.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract ForEmptyInit { - function main() -> word { + function main() returns (word) { let i : word = 1; let s = 0; for(; i <= 10; i = i + 1) { s = s + i; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.sol index d6ceaf8b..e79dc931 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-init-shadow.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract Prefor { - public function main() -> word { + function main() public returns (word) { let i : word = 100; let s : word = 0; for(let i=1;i<=10;i=i+1) { s = s + i; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.sol index 30790370..e251eeb2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-inner-block.sol @@ -1,6 +1,6 @@ -import std.{lt,Ord,Add,Sub,Bounded,Num,Eq,Typedef}; +import {lt,Ord,Add,Sub,Bounded,Num,Eq,Typedef} from std; contract ForInner { - public function main() -> word { + function main() public returns (word) { let result : word = 0; for (let height : word = 0; height < 7; height = height + 1) { if (true) { result = height; } else {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.sol index b5900f17..807cf86c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-let.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract Prefor { - public function main() -> word { + function main() public returns (word) { let s : word = 0; for(let i=1;i<=10;i=i+1) { s = s + i;} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.sol index d910c943..12511915 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-loop.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract Prefor { - public function main() -> word { + function main() public returns (word) { let i:word; let s : word = 0; for(i=1;i<=10;i=i+1) { s = s + i;} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.sol index 5f134c4a..46c1763b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-init.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract ForMultiInit { - function main() -> word { + function main() returns (word) { let i = 0; let j = 0; for (i = 1, j = 10; i <= 3; i = i + 1) { diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.sol index b0183e9a..e4559026 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/for-multi-post.sol @@ -1,7 +1,7 @@ -import std.{Num,Add,Sub,Eq,Ord,Bounded,Typedef,le}; +import {Num,Add,Sub,Eq,Ord,Bounded,Typedef,le} from std; contract ForMultiPost { - function main() -> word { + function main() returns (word) { let j = 0; for (let i = 0; i <= 3; i = i + 1, j = j + 2) { j = j + i; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.sol index 876e5bda..c24a6442 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg-synonym.sol @@ -1,10 +1,10 @@ type W = word; -function f(x:W) -> W { x } +function f(x: W) returns (W) { x } contract C { - public function main () -> word { + function main() public returns (word) { return f(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.sol index b7e0958b..ccc92693 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-pat-arg.sol @@ -1,7 +1,7 @@ -function g(x:word) -> word { x } +function g(x: word) returns (word) { x } -forall a. function h(x:a) -> a { x } +function h(x: a) returns (a) { x } contract C { - public function main() -> word { g(h(42)) } + function main() public returns (word) { g(h(42)) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.sol index 930f81ba..f8ab5e51 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/fresh-variable-shadowing.sol @@ -1,14 +1,18 @@ -data Bool = False | True; +enum Bool { False, True } -function test(v0 : Bool, p : Bool) -> Bool { - match p { - | Bool.True => return Bool.False; - | z => return v0; - } +function test(v0: Bool, p: Bool) returns (Bool) { + match (p) { +case Bool.True { +return Bool.False; +} +case z { +return v0; +} +} } contract FreshVariableShadowing { - public function main() -> Bool { + function main() public returns (Bool) { test(Bool.True, Bool.False) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.sol index a440c275..f2e9b678 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/if-examples.sol @@ -1,11 +1,15 @@ -function toBool(x : word) -> bool { - match x { - | 0 => return false; - | _ => return true; - } +function toBool(x: word) returns (bool) { + match (x) { +case 0 { +return false; +} +default { +return true; +} +} } -function gt(x : word, y : word) -> bool { +function gt(x: word, y: word) returns (bool) { let res : word; assembly { res := gt(x,y) @@ -13,7 +17,7 @@ function gt(x : word, y : word) -> bool { return toBool(res); } -function max(x : word, y : word) -> word { +function max(x: word, y: word) returns (word) { let res : word; if (gt(x,y)) { res = x; @@ -23,11 +27,11 @@ function max(x : word, y : word) -> word { return res; } -function not(x:bool) -> bool { +function not(x: bool) returns (bool) { if (x) { return false; } else { return true; } } -function foo(x : word) -> bool { +function foo(x: word) returns (bool) { if (gt(x,0)) { return true; } else { @@ -37,7 +41,7 @@ function foo(x : word) -> bool { contract IfExamples { - public function main() -> word { - return (if not(foo(42)) then 0 else 1); + function main() public returns (word) { + return ( not(foo(42)) ? 0 : 1); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.sol index cbb62e40..0dede110 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/import-std.sol @@ -4,7 +4,7 @@ pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract Test { - public function main() -> word { + function main() public returns (word) { return std.addWord(21, 21); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.sol index 210cf69b..bf4c784f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/inc-closure.sol @@ -1,4 +1,4 @@ -function inc(x : word) -> word { +function inc(x: word) returns (word) { let f = lam () { let res : word ; assembly { @@ -11,7 +11,7 @@ function inc(x : word) -> word { contract Foo { - public function main () -> word { + function main() public returns (word) { return inc(0); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.sol index 0d6d22fc..3ebe396a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-closure-error.sol @@ -1,9 +1,9 @@ -forall t . class t:CtFun { - function ct(x : t) -> ((t) -> t); +trait CtFun { + function ct(x: t) returns (function(t) returns (t)) ; } -instance word:CtFun { - function ct(x : word) -> ((word) -> word) { +impl CtFun { + function ct(x: word) returns (function(word) returns (word)) { return lam(y : word) { return x; }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.sol index e705196d..45cd4ff7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym-int.sol @@ -1,17 +1,16 @@ type W = word; -forall i. -class i : FromWord { - function fromWord(x:word) -> i; +trait FromWord { + function fromWord(x: word) returns (i) ; } -instance word : FromWord { - function fromWord(x:word) -> word { x } +impl FromWord { + function fromWord(x: word) returns (word) { x } } contract C { - public function main () -> W { + function main() public returns (W) { let r : W = FromWord.fromWord(42); return r; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.sol index 17d1520d..cefe95d1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/instance-synonym.sol @@ -1,17 +1,17 @@ type W = word; -forall self . class self:IdTy { - function id(x:self) -> self; +trait IdTy { + function id(x: self) returns (self) ; } -instance W:IdTy { - function id(x:W) -> W { +impl IdTy { + function id(x: W) returns (W) { return x; } } contract C { - public function main() -> word { + function main() public returns (word) { return IdTy.id(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.sol index a282f233..3e2ac6ef 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/invokable-issue.sol @@ -1,13 +1,11 @@ -forall abs rep . class abs:Typedef(rep) { - function abs(x:rep) -> abs; - function rep(x:abs) -> rep; +trait Typedef { + function abs(x: rep) returns (abs) ; + function rep(x: abs) returns (rep) ; } -forall t. -/* default */ instance t:Typedef(t) { - function abs(x:t) -> t { return x; } - function rep(x:t) -> t { return x; } +impl Typedef { + function abs(x: t) returns (t) { return x; } + function rep(x: t) returns (t) { return x; } } -forall abs rep res. abs:Typedef(rep) => -function lift1ac(f:(rep) -> res, x:rep) -> res { f(Typedef.rep(x)) } +function lift1ac(f: function(rep) returns (res), x: rep) returns (res) where abs: Typedef { f(Typedef.rep(x)) } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol index 1cddc66c..4855489d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol @@ -1,18 +1,18 @@ // --- preamble / duplicated std defs --- -data Proxy(a) = Proxy; +enum Proxy { Proxy } // dynamic arrays with a runtime size. cannot exist on stack so no data constructor (i.e. should be used in combination with memory / storage pointers). -data array(a); +enum array {} // a typed pointer to a location in memory -data memory(a) = memory(word); +enum memory { memory(word) } // word arithmetc -forall t . class t:Add { function add(l: t, r: t) -> t; } -forall t . class t:Mul { function mul(l: t, r: t) -> t; } -instance word:Add { - function add(l: word, r: word) -> word { +trait Add { function add(l: t, r: t) returns (t) ; } +trait Mul { function mul(l: t, r: t) returns (t) ; } +impl Add { + function add(l: word, r: word) returns (word) { let rw : word; assembly { rw := add(l,r) @@ -20,8 +20,8 @@ instance word:Add { return rw; } } -instance word:Mul { - function mul(l: word, r: word) -> word { +impl Mul { + function mul(l: word, r: word) returns (word) { let rw : word; assembly { rw := mul(l,r) @@ -32,24 +32,24 @@ instance word:Mul { // --- MemoryType --- -forall a . class a:MemoryType { - function load(loc : word) -> a; - function store(loc: word, val : a) -> (); - function size(prx : Proxy(a)) -> word; +trait MemoryType { + function load(loc: word) returns (a) ; + function store(loc: word, val: a) ; + function size(prx: Proxy) returns (word) ; } -instance word:MemoryType { - function load(loc : word) -> word { +impl MemoryType { + function load(loc: word) returns (word) { let ret : word; assembly { ret := mload(loc) } return ret; } - function store(loc : word, val : word) -> () { + function store(loc: word, val: word) { assembly { mstore(loc,val) } } - function size(prx : Proxy(word)) -> word { + function size(prx: Proxy) returns (word) { return 32; } } From 18a9c19a253e6a7990a45c2213aa96711a96637a Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 069/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../corpus/ok/test/examples/cases/ixa.sol | 87 +++++---- .../corpus/ok/test/examples/cases/join.sol | 42 ++-- .../corpus/ok/test/examples/cases/listid.sol | 18 +- .../corpus/ok/test/examples/cases/ltimp.sol | 4 +- .../corpus/ok/test/examples/cases/ltproxy.sol | 4 +- .../ok/test/examples/cases/match-bitwise.sol | 33 ++-- .../ok/test/examples/cases/match-yul.sol | 15 +- .../corpus/ok/test/examples/cases/memory.sol | 6 +- .../ok/test/examples/cases/mod-example.sol | 4 +- .../ok/test/examples/cases/modifier.sol | 6 +- .../corpus/ok/test/examples/cases/modulo.sol | 6 +- .../examples/cases/monomorphic-require.sol | 17 +- .../corpus/ok/test/examples/cases/morefun.sol | 10 +- .../examples/cases/mptc-both-templates.sol | 32 +-- .../examples/cases/mptc-chain-phantom.sol | 31 +-- .../cases/mptc-guard-extras-concrete.sol | 22 ++- .../examples/cases/mptc-multi-instance.sol | 44 +++-- .../examples/cases/mptc-nop-mainty-free.sol | 22 ++- .../examples/cases/mptc-partial-instance.sol | 34 ++-- .../examples/cases/mptc-template-a-only.sol | 22 ++- .../examples/cases/mptc-template-b-only.sol | 22 ++- .../examples/cases/multi-stmt-var-leaf.sol | 13 +- .../corpus/ok/test/examples/cases/nid.sol | 4 +- .../ok/test/examples/cases/noclosure.sol | 2 +- .../corpus/ok/test/examples/cases/notif.sol | 4 +- .../corpus/ok/test/examples/cases/option2.sol | 62 +++--- .../ok/test/examples/cases/pair-bug.sol | 4 +- .../corpus/ok/test/examples/cases/pars.sol | 2 +- .../cases/phantom-type-return-con.sol | 16 +- .../test/examples/cases/polymatch-error.sol | 20 +- .../examples/cases/polymorphic-require.sol | 13 +- .../test/examples/cases/pragma_merge_base.sol | 32 +-- .../examples/cases/pragma_test_patterson.sol | 8 +- .../ok/test/examples/cases/proxy-desugar.sol | 6 +- .../corpus/ok/test/examples/cases/proxy.sol | 11 +- .../corpus/ok/test/examples/cases/rec.sol | 14 +- .../test/examples/cases/redundant-match.sol | 22 ++- .../cases/reference-encoding-good.sol | 183 +++++++++--------- 38 files changed, 500 insertions(+), 397 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol index 4855489d..27e5df86 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ixa.sol @@ -54,79 +54,90 @@ impl MemoryType { } } -forall a . instance memory(array(a)):MemoryType { - function load(loc: word) -> memory(array(a)) { +impl MemoryType>> { + function load(loc: word) returns (memory>) { let ret : word; assembly { ret := mload(loc) } return memory(ret); } - function store(loc : word, val : memory(array(a))) -> () { - match val { - | memory(ptr) => assembly { mstore(loc,ptr) } - } + function store(loc: word, val: memory>) { + match (val) { +case memory(ptr) { +assembly { mstore(loc,ptr) } +} +} } - function size(prx : Proxy(memory(a))) -> word { + function size(prx: Proxy>) returns (word) { return 32; } } // --- Assignment --- -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l : lhs, r : rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -instance memory(word):Assign(word) { - function assign(ptr : memory(word), val : word) -> () { - match ptr { - | memory(loc) => assembly { +impl Assign, word> { + function assign(ptr: memory, val: word) { + match (ptr) { +case memory(loc) { +assembly { mstore(loc, val) } - } +} +} } } // --- Index Access --- -forall col_idx val . class col_idx:RValueIdxAccess(val) { - function lookup(ci : col_idx) -> val; +trait RValueIdxAccess { + function lookup(ci: col_idx) returns (val) ; } -forall col_idx val . class col_idx:LValueIdxAccess(val) { - function lookup(ci : col_idx) -> val; +trait LValueIdxAccess { + function lookup(ci: col_idx) returns (val) ; } -forall a . a:MemoryType => instance (memory(array(a)), word):RValueIdxAccess(a) { - function lookup(col_idx : (memory(array(a)), word)) -> a { - let sz = MemoryType.size(Proxy : Proxy(a)); - match col_idx { - | (col, idx) => match col { - | memory(loc) => - return MemoryType.load(Add.add(loc, Mul.mul(idx, sz))); - } - } +impl RValueIdxAccess<(memory>, word), a> where a: MemoryType { + function lookup(col_idx: (memory>, word)) returns (a) { + let sz = MemoryType.size(@a); + match (col_idx) { +case (col, idx) { +match (col) { +case memory(loc) { +return MemoryType.load(Add.add(loc, Mul.mul(idx, sz))); +} +} +} +} } } -forall a . a:MemoryType => instance (memory(array(a)), word):LValueIdxAccess(memory(a)) { - function lookup(col_idx : (memory(array(a)), word)) -> memory(a) { - let sz = MemoryType.size(Proxy : Proxy(a)); - match col_idx { - | (col, idx) => match col { - | memory(loc) => return memory(Add.add(loc, Mul.mul(idx, sz))); - } - } +impl LValueIdxAccess<(memory>, word), memory> where a: MemoryType { + function lookup(col_idx: (memory>, word)) returns (memory) { + let sz = MemoryType.size(@a); + match (col_idx) { +case (col, idx) { +match (col) { +case memory(loc) { +return memory(Add.add(loc, Mul.mul(idx, sz))); +} +} +} +} } } // --- Examples --- -function main() -> () { - let x : memory(array(memory(array(word)))) = memory(0); +function main() { + let x : memory>>> = memory(0); let y : word = 0; - let z : memory(array(word)) = memory(0); + let z : memory> = memory(0); let i0 : word = 0; let i1 : word = 1; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.sol index e320eece..25d39a58 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/join.sol @@ -1,26 +1,38 @@ contract Option { - data Option(a) = None | Some(a); - data Bool = False | True; + enum Option { None, Some(a) } + enum Bool { False, True } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { + function join(mmx: Option>) public returns (Option) { let result = Option.None; - match mmx { - | Option.Some(Option.Some(x)) => result = Option.Some(x); - | Option.None => result = Option.None; - | Option.Some(Option.None) => result = Option.None; - | _ => result = Option.None; - } + match (mmx) { +case Option.Some(Option.Some(x)) { +result = Option.Some(x); +} +case Option.None { +result = Option.None; +} +case Option.Some(Option.None) { +result = Option.None; +} +default { +result = Option.None; +} +} return result; } - public function main() -> word { + function main() public returns (word) { return maybe(0, join(Option.Some(Option.Some(0)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.sol index b483fa4f..3d219646 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/listid.sol @@ -1,12 +1,16 @@ -data List(a) = Nil | Cons(a, List(a)); +enum List { Nil, Cons(a, List) } -forall a . function id(x : a) -> a { +function id(x: a) returns (a) { return x; } -function listid(xs : List(word)) -> List(word) { - match xs { - | List.Nil => return List.Nil ; - | List.Cons(x,xs) => return List.Cons(id(x), listid(xs)); - } +function listid(xs: List) returns (List) { + match (xs) { +case List.Nil { +return List.Nil ; +} +case List.Cons(x,xs) { +return List.Cons(id(x), listid(xs)); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.sol index c31fc5f3..866c9b5e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltimp.sol @@ -1,5 +1,5 @@ -import ltproxy.{ltproxy}; +import {ltproxy} from ltproxy; contract LtImp { - public function main() -> bool { ltproxy() } + function main() public returns (bool) { ltproxy() } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.sol index 15e88c87..493118bf 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ltproxy.sol @@ -1,7 +1,7 @@ -import std.{lt}; +import {lt} from std; export { ltproxy }; -function ltproxy() -> bool { +function ltproxy() returns (bool) { let zero : word = 0; return (zero < 42); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.sol index 509088f9..37e266f6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-bitwise.sol @@ -1,26 +1,29 @@ -import std.{*}; -import std.opcodes.{mstore}; +import * from std; +import {mstore} from std.opcodes; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -// Regression for the `|` ambiguity between the bitwise-or operator and the -// match-arm separator. Each arm below ends in a *bare* expression statement -// (no trailing `;`), which is exactly the shape that previously made the -// parser read `mstore(...) | => ...` as a single bitwise-or -// expression and break the `match`. The `|` *inside* the parentheses is a -// genuine bitwise-or; the `|` that starts each arm is a separator. -function emit(x: word) -> () { - match x { - | 0 => mstore(0, x | 1) - | 1 => mstore(0, x & 1) - | _ => mstore(0, x) - } +// Regression for parsing the bitwise-or operator inside a match case block. +// The `|` inside the call is an expression operator; `case` starts the next +// arm, and each expression statement uses the canonical trailing semicolon. +function emit(x: word) { + match (x) { +case 0 { +mstore(0, x | 1); +} +case 1 { +mstore(0, x & 1); +} +default { +mstore(0, x); +} +} } contract MatchBitwise { // `0 | 1` still folds to 1 at the top level. - public function main() -> word { + function main() public returns (word) { emit(0); return 0 | 1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.sol index a9fe458b..a4d3af7a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/match-yul.sol @@ -1,15 +1,16 @@ -data Wrapper = Wrapper(word); +enum Wrapper { Wrapper(word) } contract C { - public function main() -> word { + function main() public returns (word) { return foo(Wrapper(1)); } - public function foo(w:Wrapper) -> word { + function foo(w: Wrapper) public returns (word) { let result : word; - match w { - | Wrapper(ptr) => - //let ptr2 : word = ptr; + match (w) { +case Wrapper(ptr) { +//let ptr2 : word = ptr; assembly { result := calldataload(ptr) } - } +} +} return result; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.sol index 9ed30b4b..360a2b9a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/memory.sol @@ -1,7 +1,7 @@ -data Memory(t) = Memory(word); -data Bytes = Bytes; +enum Memory { Memory(word) } +enum Bytes { Bytes } -function get_bytes() -> Memory(Bytes) { +function get_bytes() returns (Memory) { let ptr : word; assembly { ptr := mload(0x40) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.sol index c69f188e..15b19327 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mod-example.sol @@ -1,7 +1,7 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function foo(x: word, y: word) -> word { +function foo(x: word, y: word) returns (word) { return x % y; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.sol index ad6c5009..b425f38b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modifier.sol @@ -1,5 +1,5 @@ contract C { - public function add(x: word, y:word) -> word { + function add(x: word, y: word) public returns (word) { let r : word; assembly { r := add(x, y) @@ -8,14 +8,14 @@ contract C { } // modifier pattern: wrap add with before/after code - public function modifiedAdd(x : word, y : word) -> word { + function modifiedAdd(x: word, y: word) public returns (word) { // before solidity placeholder let result = add(x, y); // Solidity's placeholder: _; // after solidity placeholder return result; } - public function main() -> word { + function main() public returns (word) { return modifiedAdd(2, 1); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.sol index 0c05ad3d..ead52317 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/modulo.sol @@ -1,11 +1,11 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; // Exercises the `%` operator and the `%=` compound assignment // (the Mod class), plus the mod constant folding. -function f(x: word, y: word) -> word { +function f(x: word, y: word) returns (word) { let acc : word = x % y; acc %= y; // (x % y) % y == x % y once reduced return acc; @@ -13,5 +13,5 @@ function f(x: word, y: word) -> word { contract Modulo { // 17 % 5 == 2, 2 % 5 == 2 — folded at compile time. - public function main() -> word { return f(17, 5); } + function main() public returns (word) { return f(17, 5); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.sol index df7b1a2a..0754b24e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/monomorphic-require.sol @@ -1,22 +1,21 @@ // This should trigger a warning and an error in the specialiser // due to unability to resolve result type of require -import std.{uint256,lt,not,Eq,ne,Proxy,bytes4,string}; -import std.dispatch.{*}; +import {uint256,lt,not,Eq,ne,Proxy,bytes4,string} from std; +import * from std.dispatch; -forall a. -function myrevert(offset:word, length:word) -> a { +function myrevert(offset: word, length: word) returns (a) { assembly { revert(offset, length) } } -function require(cond: bool) -> () { +function require(cond: bool) { if (!cond) { - myrevert(0,0):(); + myrevert(0,0); } } -function callvalue() -> uint256 { +function callvalue() returns (uint256) { let res : word; assembly { res := callvalue() @@ -25,12 +24,12 @@ function callvalue() -> uint256 { } contract Deposit { -public function deposit() -> () { +function deposit() public { require(callvalue() != uint256(0)); return (); } -public function main() -> () { +function main() public { deposit(); } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.sol index fbcd6058..31efb0d2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/morefun.sol @@ -1,9 +1,9 @@ -data Proxy(a) = Proxy; +enum Proxy { Proxy } -forall a . class a:C { - function fun(p:Proxy(a)) -> word; +trait C { + function fun(p: Proxy) returns (word) ; } -forall t . t : C => function morefun(p:Proxy(t)) -> word { - return C.fun(Proxy:Proxy(t)); +function morefun(p: Proxy) returns (word) where t: C { + return C.fun(@t); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.sol index 222c102a..be3aa13f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-both-templates.sol @@ -2,33 +2,39 @@ // both directions. Both should discover the same binding rep=word; the second // application is idempotent (extSpSubst with the same binding is a no-op). -data Box = Box(word); +enum Box { Box(word) } -forall self rep. -class self:Convert(rep) { - function toRep(x:self) -> rep; - function fromRep(x:rep) -> self; +trait Convert { + function toRep(x: self) returns (rep) ; + function fromRep(x: rep) returns (self) ; } -instance Box:Convert(word) { - function toRep(x:Box) -> word { - match x { | Box(w) => return w; } +impl Convert { + function toRep(x: Box) returns (word) { + match (x) { +case Box(w) { +return w; +} +} } - function fromRep(x:word) -> Box { + function fromRep(x: word) returns (Box) { return Box(x); } } -forall a rep . a:Convert(rep) => -function roundtrip(x:a) -> a { +function roundtrip(x: a) returns (a) where a: Convert { let r : rep = Convert.toRep(x); return Convert.fromRep(r); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { let b : Box = roundtrip(Box(99)); - match b { | Box(w) => return w; } + match (b) { +case Box(w) { +return w; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.sol index f5822c36..d03e83d8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-chain-phantom.sol @@ -7,26 +7,28 @@ // sink's specialisation name is being built, which would produce sink$rep // (wrong) instead of sink$word (correct). -data Foo = Foo(word); +enum Foo { Foo(word) } -forall self rep. -class self:Encoder(rep) { - function encode(x:self, hint:word) -> rep; +trait Encoder { + function encode(x: self, hint: word) returns (rep) ; } -forall rep r. -class rep:Sink(r) { - function sink(x:rep) -> (); +trait Sink { + function sink(x: rep) ; } -instance Foo:Encoder(word) { - function encode(x:Foo, hint:word) -> word { - match x { | Foo(v) => return v; } +impl Encoder { + function encode(x: Foo, hint: word) returns (word) { + match (x) { +case Foo(v) { +return v; +} +} } } -instance word:Sink(word) { - function sink(x:word) -> () { +impl Sink { + function sink(x: word) { return (); } } @@ -35,8 +37,7 @@ instance word:Sink(word) { // Inside the body, encode returns rep and sink consumes rep. // resolveMPTCsFromPreds must bind rep=word so that sink specialises // to sink$word (not sink$rep). -forall a rep . a:Encoder(rep), rep:Sink(word) => -function f(x:a) -> () { +function f(x: a) where a: Encoder, rep: Sink { let r : rep = Encoder.encode(x, 0); Sink.sink(r); return (); @@ -44,7 +45,7 @@ function f(x:a) -> () { contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { f(Foo(42)); return 0; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.sol index 588af17f..84782a26 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-guard-extras-concrete.sol @@ -3,27 +3,29 @@ // `word` directly in the constraint, so freetv extras = [] and the function // compiles through normal type inference without phantom variable discovery. -data Box = Box(word); +enum Box { Box(word) } -forall self rep. -class self:Unbox(rep) { - function unbox(x:self) -> rep; +trait Unbox { + function unbox(x: self) returns (rep) ; } -instance Box:Unbox(word) { - function unbox(x:Box) -> word { - match x { | Box(w) => return w; } +impl Unbox { + function unbox(x: Box) returns (word) { + match (x) { +case Box(w) { +return w; +} +} } } -forall a . a:Unbox(word) => -function extractWord(x:a) -> word { +function extractWord(x: a) returns (word) where a: Unbox { return Unbox.unbox(x); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { return extractWord(Box(42)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.sol index 20d74d23..5f47e3a0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-multi-instance.sol @@ -4,38 +4,48 @@ // so only the Foo entry fires and rep is resolved to RepFoo. // Similarly for getTag(Bar(2)) rep resolves to RepBar. -data Foo = Foo(word); -data Bar = Bar(word); -data RepFoo = RepFoo(word); -data RepBar = RepBar(word); +enum Foo { Foo(word) } +enum Bar { Bar(word) } +enum RepFoo { RepFoo(word) } +enum RepBar { RepBar(word) } -forall self rep. -class self:Tagged(rep) { - function tag(x:self) -> rep; +trait Tagged { + function tag(x: self) returns (rep) ; } -instance Foo:Tagged(RepFoo) { - function tag(x:Foo) -> RepFoo { - match x { | Foo(w) => return RepFoo(w); } +impl Tagged { + function tag(x: Foo) returns (RepFoo) { + match (x) { +case Foo(w) { +return RepFoo(w); +} +} } } -instance Bar:Tagged(RepBar) { - function tag(x:Bar) -> RepBar { - match x { | Bar(w) => return RepBar(w); } +impl Tagged { + function tag(x: Bar) returns (RepBar) { + match (x) { +case Bar(w) { +return RepBar(w); +} +} } } -forall a rep . a:Tagged(rep) => -function getTag(x:a) -> rep { +function getTag(x: a) returns (rep) where a: Tagged { return Tagged.tag(x); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { let rf : RepFoo = getTag(Foo(1)); let rb : RepBar = getTag(Bar(2)); - match rf { | RepFoo(w) => return w; } + match (rf) { +case RepFoo(w) { +return w; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.sol index 0ddc08e2..9dfd101b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-nop-mainty-free.sol @@ -13,27 +13,29 @@ // interfere with the normal specialisation of `mapEncode` when called // from a concrete call site. -data Foo = Foo(word); +enum Foo { Foo(word) } -forall self rep. -class self:Encoder(rep) { - function encode(x:self, hint:word) -> rep; +trait Encoder { + function encode(x: self, hint: word) returns (rep) ; } -instance Foo:Encoder(word) { - function encode(x:Foo, hint:word) -> word { - match x { | Foo(v) => return v; } +impl Encoder { + function encode(x: Foo, hint: word) returns (word) { + match (x) { +case Foo(v) { +return v; +} +} } } -forall a rep. a:Encoder(rep) => -function extractVal(x:a) -> rep { +function extractVal(x: a) returns (rep) where a: Encoder { return Encoder.encode(x, 0); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { return extractVal(Foo(7)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.sol index ac1f8743..9883e3db 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-partial-instance.sol @@ -7,31 +7,39 @@ pragma no-coverage-condition Nth; -data Zero; -data Succ(a); -data Proxy(a) = Proxy; +enum Zero {} +enum Succ {} +enum Proxy { Proxy } -forall a b c. class a:Nth(b, c) { - function nth(x:Proxy(a), y:b) -> c; +trait Nth { + function nth(x: Proxy, y: b) returns (c) ; } -forall a b. instance Zero:Nth((a,b), a) { - function nth(x:Proxy(Zero), y:(a,b)) -> a { - match y { | (a, b) => return a; } +impl Nth { + function nth(x: Proxy, y: (a, b)) returns (a) { + match (y) { +case (a, b) { +return a; +} +} } } -forall n a b c. n:Nth(b,c) => instance Succ(n):Nth((a,b), c) { - function nth(x:Proxy(Succ(n)), y:(a,b)) -> c { - match y { | (a, b) => return Nth.nth(Proxy : Proxy(n), b); } +impl Nth, (a, b), c> where n: Nth { + function nth(x: Proxy>, y: (a, b)) returns (c) { + match (y) { +case (a, b) { +return Nth.nth(@n, b); +} +} } } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { let p : (word, word, word) = (1, 2, 3); - let x : word = Nth.nth(Proxy : Proxy(Zero), p); + let x : word = Nth.nth(@Zero, p); return x; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.sol index c42458eb..f292d99f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-a-only.sol @@ -3,27 +3,29 @@ // fire. The specialiser must discover rep=word solely via Template A: // specmgu (Box -> word) (Box -> freshV) => freshV = word => rep = word -data Box = Box(word); +enum Box { Box(word) } -forall self rep. -class self:Unbox(rep) { - function unbox(x:self) -> rep; +trait Unbox { + function unbox(x: self) returns (rep) ; } -instance Box:Unbox(word) { - function unbox(x:Box) -> word { - match x { | Box(w) => return w; } +impl Unbox { + function unbox(x: Box) returns (word) { + match (x) { +case Box(w) { +return w; +} +} } } -forall a rep . a:Unbox(rep) => -function extract(x:a) -> rep { +function extract(x: a) returns (rep) where a: Unbox { return Unbox.unbox(x); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { return extract(Box(42)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.sol index 07ac91c8..2437d413 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/mptc-template-b-only.sol @@ -4,28 +4,30 @@ // specmgu (word -> Box) (freshV -> Box) => freshV = word => rep = word // The `hint:a` argument makes a=Box concrete at the call site. -data Box = Box(word); +enum Box { Box(word) } -forall self rep. -class self:Rebox(rep) { - function rebox(x:rep) -> self; +trait Rebox { + function rebox(x: rep) returns (self) ; } -instance Box:Rebox(word) { - function rebox(x:word) -> Box { +impl Rebox { + function rebox(x: word) returns (Box) { return Box(x); } } -forall a rep . a:Rebox(rep) => -function rewrap(val:rep, hint:a) -> a { +function rewrap(val: rep, hint: a) returns (a) where a: Rebox { return Rebox.rebox(val); } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { let b : Box = rewrap(7, Box(0)); - match b { | Box(w) => return w; } + match (b) { +case Box(w) { +return w; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.sol index aff2196a..2ccc9626 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/multi-stmt-var-leaf.sol @@ -1,11 +1,12 @@ -data Bool = False | True; +enum Bool { False, True } contract MultiStmtVarLeaf { - public function main(x:Bool) -> Bool { - match x { - | y => - let z = y; + function main(x: Bool) public returns (Bool) { + match (x) { +case y { +let z = y; return z; - } +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.sol index 24d8a88c..4c06795e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/nid.sol @@ -1,8 +1,8 @@ -function id (x : word) -> word { +function id(x: word) returns (word) { return x; } -function nid (x : word) -> word { +function nid(x: word) returns (word) { return id(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.sol index f961cdae..163ca306 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/noclosure.sol @@ -1,4 +1,4 @@ -function foo (z : word) -> word { +function foo(z: word) returns (word) { let f = lam (x : word, y : word) { return primAddWord(x,primAddWord(y,1)); }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.sol index ee4e9244..2a114790 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/notif.sol @@ -1,4 +1,4 @@ -function not(x : bool) -> bool { +function not(x: bool) returns (bool) { if (x) { return false ; } else { @@ -6,7 +6,7 @@ function not(x : bool) -> bool { } } -function not2(x : bool) -> bool { +function not2(x: bool) returns (bool) { if (x) { return false ; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.sol index b60d551d..1a470118 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/option2.sol @@ -1,34 +1,52 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.None => return Option.None; - | Option.Some(Option.None) => return Option.None; - | Option.Some(Option.Some(x)) => return Option.Some(x); - } + function join(mmx: Option>) public returns (Option) { + match (mmx) { +case Option.None { +return Option.None; +} +case Option.Some(Option.None) { +return Option.None; +} +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +} } - public function join2(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.Some(m) => match m { - | Option.None => return Option.None; - | Option.Some(x) => return Option.Some(x); - } - | _ => return Option.None; - } + function join2(mmx: Option>) public returns (Option) { + match (mmx) { +case Option.Some(m) { +match (m) { +case Option.None { +return Option.None; +} +case Option.Some(x) { +return Option.Some(x); +} +} +} +default { +return Option.None; +} +} } - public function main() -> word { + function main() public returns (word) { // return maybe(0, join(Option.Some(Option.Some(42)))); return 42; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.sol index 3006338f..f5a83b45 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pair-bug.sol @@ -1,9 +1,9 @@ -import std.{*}; +import * from std; contract TupleRet { constructor() {} - function pair() -> (uint256, uint256) { + function pair() returns (uint256, uint256) { return (uint256(7), uint256(11)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.sol index d25d89f6..70417bee 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pars.sol @@ -1,3 +1,3 @@ contract Pars { - public function main() -> (){ let f:word; 42:word; (); } + function main() public { let f: word; let ignored: word = 42; (); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.sol index 87ae1364..137321aa 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/phantom-type-return-con.sol @@ -1,16 +1,18 @@ -data Foo(a) = Foo(word); - forall a . function wrap(x : word) -> Foo(a) { +enum Foo { Foo(word) } + function wrap(x: word) returns (Foo) { return Foo(x); } - function unwrap() -> word { - match(wrap(42)) { - | Foo(w) => return w; - } + function unwrap() returns (word) { + match (wrap(42)) { +case Foo(w) { +return w; +} +} } contract C { - public function main() -> word { + function main() public returns (word) { return unwrap(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.sol index 96462fd7..7fcbac6f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymatch-error.sol @@ -1,12 +1,16 @@ -forall a b . function fst(p: (a, b)) -> a { - match p { - | (a, _) => return a; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (a, _) { +return a; +} +} } contract TestUnitMatch { - public function main() -> () { - match ((), ()) { - | x => return fst(x); - } + function main() public { + match (((), ())) { +case x { +return fst(x); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.sol index dbab329e..fc89944b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/polymorphic-require.sol @@ -1,10 +1,9 @@ // This should trigger a warning and an error in the specialiser // due to unability to resolve result type of require -import std.{uint256,lt,not,Eq,ne,Proxy,bytes4,string}; -import std.dispatch.{*}; +import {uint256,lt,not,Eq,ne,Proxy,bytes4,string} from std; +import * from std.dispatch; -forall a. -function require(cond: bool) -> a { +function require(cond: bool) returns (a) { if (!cond) { assembly { revert(0, 0) @@ -12,7 +11,7 @@ function require(cond: bool) -> a { } } -function callvalue() -> uint256 { +function callvalue() returns (uint256) { let res : word; assembly { res := callvalue() @@ -21,12 +20,12 @@ function callvalue() -> uint256 { } contract Deposit { -public function deposit() -> () { +function deposit() public { require(callvalue() != uint256(0)); return (); } -public function main() -> () { +function main() public { deposit(); } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.sol index 98d66cfb..334a200f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_merge_base.sol @@ -8,40 +8,40 @@ pragma no-bounded-variable-condition TestClassB1, TestClassB3; // --- Test Classes --- -forall a . class a:TestClassP1 {} -forall a . class a:TestClassP2 {} -forall a b . class a:TestClassP3(b) {} +trait TestClassP1 {} +trait TestClassP2 {} +trait TestClassP3 {} -forall a b . class a:TestClassC1(b) {} -forall a b c . class a:TestClassC2(b,c) {} +trait TestClassC1 {} +trait TestClassC2 {} -forall a b . class a:TestClassB1(b) {} -forall a b . class a:TestClassB2(b) {} -forall a . class a:TestClassB3 {} +trait TestClassB1 {} +trait TestClassB2 {} +trait TestClassB3 {} // --- Data Types --- -data TestType1(x) = TestType1; -data TestType2 = TestType2; +enum TestType1 { TestType1 } +enum TestType2 { TestType2 } // Fails Patterson: context constraint not smaller then head -forall U . (U,word):TestClassP1 => instance U:TestClassP1 {} +impl TestClassP1 where (U, word): TestClassP1 {} // Patterson OK: No context predicates -instance TestType2:TestClassP2 {} +impl TestClassP2 {} // --- Coverage Condition --- // Fails Coverage: Variable 'a' only appears in weak position (parameter to TestClassC1) -forall a b . instance TestType1(b):TestClassC1(a) {} +impl TestClassC1, a> {} // Coverage OK: All variables in strong positions -instance TestType2:TestClassC2(TestType2, TestType2) {} +impl TestClassC2 {} // === Bound Variable Violations === // Fails Bound Variable & Patterson: Variable 'c' appears in context but not in instance head -forall a c . c:TestClassB2(a) => instance TestType1(a):TestClassB1(a) {} +impl TestClassB1, a> where c: TestClassB2 {} // Bound Variable OK: Simple instance without context -instance TestType1(TestType2):TestClassB2(TestType2) {} +impl TestClassB2, TestType2> {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.sol index fd7be0ed..91062406 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/pragma_test_patterson.sol @@ -1,9 +1,9 @@ // Simple Patterson test - should fail without pragma -forall a . class a:C1 {} -forall a . class a:C2 {} +trait C1 {} +trait C2 {} -data T(x) = T; +enum T { T } // This violates Patterson: context measure (2) >= conclusion measure (2) -forall U . U:C1, U:C2 => instance T(U):C1 {} \ No newline at end of file +impl C1> where U: C1, U: C2 {} \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.sol index 82be4dea..04229265 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy-desugar.sol @@ -1,12 +1,12 @@ -import std.{*}; +import * from std; pragma no-patterson-condition; pragma no-coverage-condition; pragma no-bounded-variable-condition; -function foo(x : @word) -> word { +function foo(x: @word) returns (word) { return 0; } -function fuz(y : word) -> word { +function fuz(y: word) returns (word) { return y + foo(@word); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.sol index a3e30424..7f883c93 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/proxy.sol @@ -1,11 +1,10 @@ -data Proxy(a) = Proxy; +enum Proxy { Proxy } -forall self . class self:BaseMemoryType { - function memorySize(x:Proxy(self)) -> word; +trait BaseMemoryType { + function memorySize(x: Proxy) returns (word) ; } -forall t . t : BaseMemoryType => -function morefun(p:Proxy(t)) -> word { - return BaseMemoryType.memorySize(Proxy:Proxy(t)); +function morefun(p: Proxy) returns (word) where t: BaseMemoryType { + return BaseMemoryType.memorySize(@t); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.sol index 53aec28d..333925dd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/rec.sol @@ -1,6 +1,10 @@ -function rec (n : word, b : word, f : word) -> word { - match n { - | 0 => return b; - | m => return f(primAddWord(m,1), rec(m, b, f)); - } +function rec(n: word, b: word, f: word) returns (word) { + match (n) { +case 0 { +return b; +} +case m { +return f(primAddWord(m,1), rec(m, b, f)); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.sol index f7913c2b..34a24b1d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/redundant-match.sol @@ -1,13 +1,19 @@ -data Bool = False | True; +enum Bool { False, True } - function f(x : Bool) -> Bool { - match x { - | z => return z; - | Bool.True => return Bool.True; - | Bool.False => return Bool.False; - } + function f(x: Bool) returns (Bool) { + match (x) { +case z { +return z; +} +case Bool.True { +return Bool.True; +} +case Bool.False { +return Bool.False; +} +} } contract Test { - public function main() -> Bool { f(Bool.True) } + function main() public returns (Bool) { f(Bool.True) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.sol index c7c7dd10..64588046 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good.sol @@ -1,135 +1,142 @@ /////// Construction -forall abs rep . class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -instance word:Typedef(word) { - function rep(x:word) -> word { return x; } - function abs(x:word) -> word { return x; } +impl Typedef { + function rep(x: word) returns (word) { return x; } + function abs(x: word) returns (word) { return x; } } -data uint = uint(word); +enum uint { uint(word) } -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -forall a . instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -forall a . instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -forall a . instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -forall self . class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -forall self . class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { +impl MemoryType { + function load(ptr: word) returns (uint) { return Typedef.abs(MemoryType.load(ptr)); } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return MemoryType.store(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) -> () { +impl Assign, a> where a: MemoryType { + function assign(l: memoryRef, y: a) { MemoryType.store(Typedef.rep(l), y); } } -data MemberAccessProxy(a, field) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field . -function memberAccessD1(x:MemberAccessProxy(a, field)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -forall self memberRefType . class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } // This is *a lot* of pragmas... pragma no-coverage-condition CStructField, LValueMemberAccess, RValueMemberAccess; pragma no-patterson-condition LValueMemberAccess, RValueMemberAccess; pragma no-bounded-variable-condition LValueMemberAccess, RValueMemberAccess; -forall self fieldType offsetType . class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector):CStructField(fieldType, offsetType), offsetType:MemorySize => instance MemberAccessProxy(memory(structType), fieldSelector):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector)) -> memoryRef(fieldType) { +impl LValueMemberAccess, fieldSelector>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -137,29 +144,29 @@ forall structType fieldSelector fieldType offsetType . StructField(structType, f } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -167,38 +174,38 @@ forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector):CStructField(fieldType, offsetType), fieldType:MemoryType, offsetType:MemorySize => instance MemberAccessProxy(memory(structType), fieldSelector):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector)) -> fieldType { +impl RValueMemberAccess, fieldSelector>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); // BUG: Something wrong here? Complains about ptr not being word... assembly { ptr := add(ptr, size) } - return MemoryType.load(Typedef.abs(ptr)):fieldType; + return MemoryType.load(Typedef.abs(ptr)); } } ////// Testing // struct S { x:word; y:uint; z:word; } -data S = S(word, uint, word); -data x_sel = x_sel; -data y_sel = y_sel; -data z_sel = z_sel; +enum S { S(word, uint, word) } +enum x_sel { x_sel } +enum y_sel { y_sel } +enum z_sel { z_sel } -instance StructField(S, x_sel):CStructField(word, ()) {} -instance StructField(S, y_sel):CStructField(uint, word) {} +impl CStructField, word, ()> {} +impl CStructField, uint, word> {} // BUG: This next one should really be the following, but that breaks weirdly: // (I get a patterson condition violation on an invoke instance for g) // instance StructField(S, z_sel):CStructField(word, (word,uint)) {} // So instead I use: -instance StructField(S, z_sel):CStructField(word, word) {} +impl CStructField, word, word> {} -function f() -> () { - let x:memory(word); - let y:memory(word); +function f() { + let x:memory; + let y:memory; // x = y Assign.assign(ref(x), y); /* @@ -211,8 +218,8 @@ function f() -> () { */ } -function g() -> () { - let s:memory(S) = Typedef.abs(0x80); +function g() { + let s:memory = Typedef.abs(0x80); let y:word = 42; let z:uint = uint(42); // s.x = y @@ -227,7 +234,7 @@ function g() -> () { Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, z_sel)), RValueMemberAccess.memberAccess(MemberAccessProxy(s, x_sel))); } contract C { - public function main() -> () { + function main() public { f(); g(); } From 3918bc2692cd69b9be86d1727578b709814e7cd0 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 070/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../cases/reference-encoding-good1.sol | 183 +++++++++--------- .../test/examples/cases/return-fun-adder.sol | 4 +- .../test/examples/cases/return-fun-const.sol | 2 +- .../ok/test/examples/cases/return-fun-eq.sol | 4 +- .../examples/cases/return-fun-instance.sol | 8 +- .../cases/same-name-constructor-qualifier.sol | 26 ++- .../ok/test/examples/cases/simpleDiscount.sol | 30 +-- .../ok/test/examples/cases/simpleid.sol | 2 +- .../ok/test/examples/cases/single-lambda.sol | 2 +- .../corpus/ok/test/examples/cases/snds.sol | 10 +- .../examples/cases/spec-fail-ungrounded.sol | 8 +- .../cases/storage-adt-recursive-fail.sol | 10 +- .../cases/storage-adt-recursive-ok.sol | 30 +-- .../test/examples/cases/strange-unbound.sol | 6 +- .../test/examples/cases/sum-match-default.sol | 18 +- .../test/examples/cases/super-class-cycle.sol | 10 +- .../test/examples/cases/super-class-num.sol | 89 +++++---- .../ok/test/examples/cases/super-class.sol | 65 ++++--- .../ok/test/examples/cases/synonym-basic.sol | 18 +- .../examples/cases/synonym-in-function.sol | 28 +-- .../ok/test/examples/cases/synonym-nested.sol | 16 +- .../ok/test/examples/cases/synonym-param.sol | 16 +- .../cases/tabled-default-instance.sol | 13 +- .../examples/cases/tabled-given-order.sol | 16 +- .../examples/cases/tabled-residual-given.sol | 12 +- .../corpus/ok/test/examples/cases/td.sol | 20 +- .../corpus/ok/test/examples/cases/tiamat.sol | 101 +++++----- .../ok/test/examples/cases/tuple-trick.sol | 44 +++-- .../corpus/ok/test/examples/cases/tuva.sol | 47 +++-- .../corpus/ok/test/examples/cases/tyexp.sol | 4 +- .../test/examples/cases/type-synonym-arg.sol | 4 +- .../corpus/ok/test/examples/cases/typedef.sol | 9 +- .../test/examples/cases/ufcs-no-conflict.sol | 19 +- .../ok/test/examples/cases/uintdesugared.sol | 21 +- 34 files changed, 471 insertions(+), 424 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.sol index 42f1d4af..8ff5eab1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/reference-encoding-good1.sol @@ -1,136 +1,143 @@ /////// Construction -forall abs rep . class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } -data uint = uint(word); +enum uint { uint(word) } -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data memory(a) = memory(word); -data memoryRef(a) = memoryRef(word); -data Proxy(a) = Proxy; +enum memory { memory(word) } +enum memoryRef { memoryRef(word) } +enum Proxy { Proxy } -forall a . instance memory(a):Typedef(word) { - function rep(x:memory(a)) -> word { - match x { - | memory(y) => return y; - } +impl Typedef, word> { + function rep(x: memory) returns (word) { + match (x) { +case memory(y) { +return y; +} +} } - function abs(x:word) -> memory(a) { + function abs(x: word) returns (memory) { return memory(x); } } -forall a . instance memoryRef(a):Typedef(word) { - function rep(x:memoryRef(a)) -> word { - match x { - | memoryRef(y) => return y; - } +impl Typedef, word> { + function rep(x: memoryRef) returns (word) { + match (x) { +case memoryRef(y) { +return y; +} +} } - function abs(x:word) -> memoryRef(a) { + function abs(x: word) returns (memoryRef) { return memoryRef(x); } } -forall lhs rhs . class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -forall a . instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -forall self . class self:MemoryType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait MemoryType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -forall self . class self:MemorySize { - function size(x:Proxy(self)) -> word; +trait MemorySize { + function size(x: Proxy) returns (word) ; } -instance word:MemoryType { - function load(ptr:word) -> word { +impl MemoryType { + function load(ptr: word) returns (word) { let r:word; assembly { r := mload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { mstore(ptr, value) } } } -instance uint:MemoryType { - function load(ptr:word) -> uint { +impl MemoryType { + function load(ptr: word) returns (uint) { return Typedef.abs(MemoryType.load(ptr)); } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return MemoryType.store(ptr, Typedef.rep(value)); } } -forall a . a : MemoryType => instance memoryRef(a):Assign(a) { - function assign(l:memoryRef(a), y:a) -> () { +impl Assign, a> where a: MemoryType { + function assign(l: memoryRef, y: a) { MemoryType.store(Typedef.rep(l), y); } } -instance word:Typedef(word) { - function rep(x:word) -> word { return x; } - function abs(x:word) -> word { return x; } +impl Typedef { + function rep(x: word) returns (word) { return x; } + function abs(x: word) returns (word) { return x; } } -data MemberAccessProxy(a, field) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field . -function memberAccessD1(x:MemberAccessProxy(a, field)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -forall self memberRefType . class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } // This is *a lot* of pragmas... pragma no-coverage-condition CStructField, LValueMemberAccess, RValueMemberAccess; pragma no-patterson-condition LValueMemberAccess, RValueMemberAccess; pragma no-bounded-variable-condition LValueMemberAccess, RValueMemberAccess; -forall self fieldType offsetType . class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector):CStructField(fieldType, offsetType), offsetType:MemorySize => instance MemberAccessProxy(memory(structType), fieldSelector):LValueMemberAccess(memoryRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector)) -> memoryRef(fieldType) { +impl LValueMemberAccess, fieldSelector>, memoryRef> where StructField: CStructField, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector>) returns (memoryRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -138,29 +145,29 @@ forall structType fieldSelector fieldType offsetType . StructField(structType, f } } -instance ():MemorySize { - function size(x:Proxy(())) -> word { +impl MemorySize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:MemorySize { - function size(x:Proxy(word)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -instance uint:MemorySize { - function size(x:Proxy(uint)) -> word { +impl MemorySize { + function size(x: Proxy) returns (word) { return 32; } } -forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = MemorySize.size(Proxy:Proxy(a)); - let b_sz:word = MemorySize.size(Proxy:Proxy(b)); +impl MemorySize<(a, b)> where a: MemorySize, b: MemorySize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = MemorySize.size(@a); + let b_sz:word = MemorySize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -168,38 +175,38 @@ forall a b . a:MemorySize, b:MemorySize => instance (a,b):MemorySize { } } -forall structType fieldSelector fieldType offsetType . StructField(structType, fieldSelector):CStructField(fieldType, offsetType), fieldType:MemoryType, offsetType:MemorySize => instance MemberAccessProxy(memory(structType), fieldSelector):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(memory(structType), fieldSelector)) -> fieldType { +impl RValueMemberAccess, fieldSelector>, fieldType> where StructField: CStructField, fieldType: MemoryType, offsetType: MemorySize { + function memberAccess(x: MemberAccessProxy, fieldSelector>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = MemorySize.size(Proxy:Proxy(offsetType)); + let size:word = MemorySize.size(@offsetType); // BUG: Something wrong here? Complains about ptr not being word... assembly { ptr := add(ptr, size) } - return MemoryType.load(Typedef.abs(ptr)):fieldType; + return MemoryType.load(Typedef.abs(ptr)); } } ////// Testing // struct S { x:word; y:uint; z:word; } -data S = S(word, uint, word); -data x_sel = x_sel; -data y_sel = y_sel; -data z_sel = z_sel; +enum S { S(word, uint, word) } +enum x_sel { x_sel } +enum y_sel { y_sel } +enum z_sel { z_sel } -instance StructField(S, x_sel):CStructField(word, ()) {} -instance StructField(S, y_sel):CStructField(uint, word) {} +impl CStructField, word, ()> {} +impl CStructField, uint, word> {} // BUG: This next one should really be the following, but that breaks weirdly: // (I get a patterson condition violation on an invoke instance for g) // instance StructField(S, z_sel):CStructField(word, (word,uint)) {} // So instead I use: -instance StructField(S, z_sel):CStructField(word, word) {} +impl CStructField, word, word> {} -function f() -> () { - let x:memory(word); - let y:memory(word); +function f() { + let x:memory; + let y:memory; // x = y Assign.assign(ref(x), y); /* @@ -212,8 +219,8 @@ function f() -> () { */ } -function g() -> () { - let s:memory(S) = Typedef.abs(0x80); +function g() { + let s:memory = Typedef.abs(0x80); let y:word = 42; let z:uint = uint(42); // s.x = y @@ -228,7 +235,7 @@ function g() -> () { Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(s, z_sel)), RValueMemberAccess.memberAccess(MemberAccessProxy(s, x_sel))); } contract C { - public function main() -> () { + function main() public { f(); g(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.sol index 552fda13..9b3b7cf7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-adder.sol @@ -2,7 +2,7 @@ // Validates the single-pass type checker: closure conversion must not hide // that the returned lambda really has type (word) -> word. // Uses an assembly block instead of primAddWord so it lowers end-to-end. -function makeAdder(x : word) -> ((word) -> word) { +function makeAdder(x: word) returns (function(word) returns (word)) { return lam (y : word) -> word { let res : word; assembly { @@ -13,7 +13,7 @@ function makeAdder(x : word) -> ((word) -> word) { } contract C { - public function main() -> word { + function main() public returns (word) { let f = makeAdder(10); return f(5); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.sol index b2709271..b77bd7df 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-const.sol @@ -1,6 +1,6 @@ // Returns a constant function that closes over its argument. // Correct annotations: (word) -> word, body returns the captured word. -function constFn(x : word) -> ((word) -> word) { +function constFn(x: word) returns (function(word) returns (word)) { return lam (y : word) -> word { return x; }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.sol index 6f148fc8..85892d3e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-eq.sol @@ -1,6 +1,6 @@ // Returns a function comparing against a captured word, CORRECT annotations. // Uses an assembly `eq` instead of primEqWord so it lowers end-to-end. -function makeEq(x : word) -> ((word) -> word) { +function makeEq(x: word) returns (function(word) returns (word)) { return lam (y : word) -> word { let res : word; assembly { @@ -11,7 +11,7 @@ function makeEq(x : word) -> ((word) -> word) { } contract C { - public function main() -> word { + function main() public returns (word) { let f = makeEq(7); return f(7); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.sol index 067da6c6..88699204 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/return-fun-instance.sol @@ -1,11 +1,11 @@ // Instance member returning a function with CORRECT annotations. // The compiled-away validation pass used to check this; the single pass must too. -forall t . class t:CtFun { - function ct(x : t) -> ((t) -> t); +trait CtFun { + function ct(x: t) returns (function(t) returns (t)) ; } -instance word:CtFun { - function ct(x : word) -> ((word) -> word) { +impl CtFun { + function ct(x: word) returns (function(word) returns (word)) { return lam (y : word) -> word { return x; }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.sol index 6850b084..53613291 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/same-name-constructor-qualifier.sol @@ -1,23 +1,29 @@ // Qualifier access (T.C) must work even when T has a same-name constructor. // Regression test for: `Error.Empty` reporting "Unqualified constructor: Empty". -data Err = Err(word) | Empty | Msg(word); +enum Err { Err(word), Empty, Msg(word) } -function pickEmpty() -> Err { +function pickEmpty() returns (Err) { return Err.Empty; } -function pickMsg(x: word) -> Err { +function pickMsg(x: word) returns (Err) { return Err.Msg(x); } -function pickErr(x: word) -> Err { +function pickErr(x: word) returns (Err) { return Err.Err(x); } -function main() -> word { - match pickEmpty() { - | Err.Empty => return 1; - | Err.Err(_) => return 2; - | Err.Msg(_) => return 3; - } +function main() returns (word) { + match (pickEmpty()) { +case Err.Empty { +return 1; +} +case Err.Err(_) { +return 2; +} +case Err.Msg(_) { +return 3; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.sol index ebafe1b0..fba9820f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleDiscount.sol @@ -1,26 +1,28 @@ // test complex match example from the blog post // simplified to use word instead of uint256 -import std.{address, Num, Add, Sub, Div, Bounded, Eq, Ord, Typedef}; +import {address, Num, Add, Sub, Div, Bounded, Eq, Ord, Typedef} from std; -data AuctionState = - NotStarted(word) - | Active(word, address) - | Ended(word, address) - | Cancelled(word, address); +enum AuctionState { NotStarted(word), Active(word, address), Ended(word, address), Cancelled(word, address) } -data Phase = Early | Late; +enum Phase { Early, Late } -function discount(state : AuctionState, phase : Phase) -> word { - match state, phase { - | .Active(bid, _), .Early => return bid / 10; - | .Active(bid, _), .Late => return bid / 20; - | _, _ => return 0; - } +function discount(state: AuctionState, phase: Phase) returns (word) { + match (state, phase) { +case (.Active(bid, _), .Early) { +return bid / 10; +} +case (.Active(bid, _), .Late) { +return bid / 20; +} +default { +return 0; +} +} } contract Discount { - public function main() -> word { + function main() public returns (word) { discount(.Active(420,.address(0)), .Early) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.sol index a85da975..f344c110 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/simpleid.sol @@ -1,3 +1,3 @@ -forall a . function id(x : a) -> a { +function id(x: a) returns (a) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.sol index 7c6a1729..b9397c2a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/single-lambda.sol @@ -1,3 +1,3 @@ -function foo () -> (word) -> bool { +function foo() returns (function(word) returns (bool)) { return lam (x:word) -> bool { return true; }; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.sol index 44b7bdb1..e9d9c050 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/snds.sol @@ -1,7 +1,9 @@ - function snds (p1 : (word, word), p2 : (word, word)) -> (word, word) { - match p1, p2 { - | (a,b) , (c,d) => return (b,d); - } + function snds(p1: (word, word), p2: (word, word)) returns (word, word) { + match (p1, p2) { +case ((a,b) , (c,d)) { +return (b,d); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.sol index dde3745a..8a168910 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/spec-fail-ungrounded.sol @@ -11,19 +11,17 @@ // no constraint, no instance, and no return-type context to fix 'a', so // ensureClosed reports a free type variable and aborts. -forall a. -function abort_(x:word) -> a { +function abort_(x: word) returns (a) { return abort_(x); } -forall b. -function sink_(y:b) -> word { +function sink_(y: b) returns (word) { return 0; } contract C { constructor() {} - public function main() -> word { + function main() public returns (word) { return sink_(abort_(0)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.sol index d7739a57..0895dd9a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-fail.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // A recursive data type has no bounded slot footprint, so DeriveGeneric // (isRecursiveData) deliberately skips deriving StorageSize and @@ -11,7 +11,7 @@ import std.StorageGeneric.{*}; // The failure surfaces at the use site (the field assignment), not at // derivation time, which is the design stated in DeriveGeneric. -data IntList = Nil | Cons(uint256, IntList); +enum IntList { Nil, Cons(uint256, IntList) } contract C { xs : IntList; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.sol index e28974fc..cacf5e80 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/storage-adt-recursive-ok.sol @@ -1,30 +1,34 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; -// The counterpart of storage-adt-recursive-fail.solc: skipping storage +// The counterpart of storage-adt-recursive-fail.sol: skipping storage // derivation for a recursive type is a SKIP, not a hard error. The type still // gets its Generic instance and remains usable everywhere except storage. -data IntList = Nil | Cons(uint256, IntList); +enum IntList { Nil, Cons(uint256, IntList) } -function len(xs : IntList) -> uint256 { - match xs { - | IntList.Nil => return uint256(0); - | IntList.Cons(_, r) => return uint256(1) + len(r); - } +function len(xs: IntList) returns (uint256) { + match (xs) { +case IntList.Nil { +return uint256(0); +} +case IntList.Cons(_, r) { +return uint256(1) + len(r); +} +} } // A non-recursive neighbour in the same module still gets its storage // instances, so the skip is per-type rather than per-module. -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } contract C { p : Point; constructor() { p = Point(uint256(1), uint256(2)); - assert(StorageSize.size(Proxy : Proxy(Point)) == 2); + assert(StorageSize.size(@Point) == 2); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.sol index 230f6ae5..2fa817cb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/strange-unbound.sol @@ -1,5 +1,3 @@ -forall b. -class b:IsA { - forall a. - function ais(p : (a,b)) -> a; +trait IsA { + function ais(p: (a, b)) returns (a) ; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.sol index fb90bf70..ded6f663 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/sum-match-default.sol @@ -1,14 +1,18 @@ contract SumMatchDefault { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function g(s : Option(word)) -> Option(word) { - match s { - | Option.None => return Option.None; - | x => return x; - } + function g(s: Option) public returns (Option) { + match (s) { +case Option.None { +return Option.None; +} +case x { +return x; +} +} } - public function main() -> word { + function main() public returns (word) { g(Option.None); return 42; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.sol index 04a42f71..c21df6ca 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-cycle.sol @@ -1,14 +1,14 @@ -forall a . a:B => class a:A {} -forall a . a:A => class a:B {} +trait A where a: B {} +trait B where a: A {} -forall a . a:B => function needsB(x:a) -> () { +function needsB(x: a) where a: B { return (); } -forall a . a:A => function usesSuperCycle(x:a) -> () { +function usesSuperCycle(x: a) where a: A { return needsB(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.sol index 920a0b45..fcc615bb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class-num.sol @@ -1,26 +1,33 @@ -data Bool = False | True; +enum Bool { False, True } -function fromBool(b:Bool) -> word { - match b { - | Bool.False => return 0; - | Bool.True => return 1; - } +function fromBool(b: Bool) returns (word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } -function toBool(x: word) -> Bool { - match x { - | 0 => return Bool.False; - | _ => return Bool.True; - } +function toBool(x: word) returns (Bool) { + match (x) { +case 0 { +return Bool.False; +} +default { +return Bool.True; +} +} } -forall a. -class a:Eq { - function eq(x:a, y:a) -> Bool; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } -instance word:Eq { - function eq(x:word, y:word) -> Bool { +impl Eq { + function eq(x: word, y: word) returns (Bool) { let res : word; assembly { res := eq(x, y) @@ -29,42 +36,46 @@ instance word:Eq { } } -function not (b : Bool) -> Bool { - match b { - | Bool.True => return Bool.False ; - | Bool.False => return Bool.True ; - } +function not(b: Bool) returns (Bool) { + match (b) { +case Bool.True { +return Bool.False ; +} +case Bool.False { +return Bool.True ; +} +} } -forall a . a:Eq => function ne(x : a, y : a) -> Bool { +function ne(x: a, y: a) returns (Bool) where a: Eq { return not(Eq.eq(x,y)); } -forall a. a:Eq => -class a:Num { - function toWord(x:a) -> word; - function fromWord(x:word) -> a; +trait Num where a: Eq { + function toWord(x: a) returns (word) ; + function fromWord(x: word) returns (a) ; } -instance word:Num { - function toWord(x:word) -> word { return x; } - function fromWord(x:word) -> word { return x; } +impl Num { + function toWord(x: word) returns (word) { return x; } + function fromWord(x: word) returns (word) { return x; } } -data uint = uint(word); +enum uint { uint(word) } -instance uint:Eq { - function eq(x:uint, y:uint) -> Bool { return Eq.eq(Num.toWord(x), Num.toWord(y)); } +impl Eq { + function eq(x: uint, y: uint) returns (Bool) { return Eq.eq(Num.toWord(x), Num.toWord(y)); } } -instance uint:Num { - function toWord(x:uint) -> word - { - match x { - | uint(y) => return y; - } +impl Num { + function toWord(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function fromWord(x:word) -> uint { return uint(x); } + function fromWord(x: word) returns (uint) { return uint(x); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.sol index e413219a..6189e9b1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/super-class.sol @@ -1,38 +1,53 @@ -data List(a) = Nil | Cons(a,List(a)); -data Bool = False | True; +enum List { Nil, Cons(a, List) } +enum Bool { False, True } -function and (x : Bool, y : Bool) -> Bool { - match x,y { - | Bool.False, _ => return Bool.False; - | Bool.True, y => return y; - } +function and(x: Bool, y: Bool) returns (Bool) { + match (x,y) { +case (Bool.False, _) { +return Bool.False; +} +case (Bool.True, y) { +return y; +} +} } -forall a . class a : Eq { - function eq(x : a, y : a) -> Bool; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } -instance Bool : Eq { - function eq (x : Bool, y : Bool) -> Bool { - match x, y { - | Bool.False, Bool.False => return Bool.True; - | Bool.True, Bool.True => return Bool.True; - | _, _ => return Bool.False; - } +impl Eq { + function eq(x: Bool, y: Bool) returns (Bool) { + match (x, y) { +case (Bool.False, Bool.False) { +return Bool.True; +} +case (Bool.True, Bool.True) { +return Bool.True; +} +default { +return Bool.False; +} +} } } -forall a . a : Eq => instance (List(a)) : Eq { - function eq (xs : List(a), ys : List(a)) -> Bool { - match xs, ys { - | List.Nil, List.Nil => return Bool.True; - | List.Cons(x,xs), List.Cons(y,ys) => - return and(Eq.eq(x,y),Eq.eq(xs,ys)); - | _ , _ => return Bool.False; - } +impl Eq<(List)> where a: Eq { + function eq(xs: List, ys: List) returns (Bool) { + match (xs, ys) { +case (List.Nil, List.Nil) { +return Bool.True; +} +case (List.Cons(x,xs), List.Cons(y,ys)) { +return and(Eq.eq(x,y),Eq.eq(xs,ys)); +} +default { +return Bool.False; +} +} } } -function foo() -> () { +function foo() { let x = Eq.eq(List.Cons(Bool.True,List.Nil), List.Nil); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.sol index 2f521980..5ed70679 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-basic.sol @@ -1,21 +1,23 @@ type Uint = word; -type Point = pair(word, word); +type Point = pair; -function useUint(x: Uint) -> word { +function useUint(x: Uint) returns (word) { return x; } -function makePoint(x: word, y: word) -> Point { +function makePoint(x: word, y: word) returns (Point) { return pair(x, y); } -function getX(p: Point) -> word { - match p { - | pair(x, _) => return x; - } +function getX(p: Point) returns (word) { + match (p) { +case pair(x, _) { +return x; +} +} } -function main() -> word { +function main() returns (word) { let p: Point = makePoint(10, 20); return getX(p); } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.sol index a71676b0..c776227c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-in-function.sol @@ -1,28 +1,32 @@ // Synonyms in function parameter and return types type Int = word; -type Point = pair(Int, Int); +type Point = pair; -function add(a: Int, b: Int) -> Int { +function add(a: Int, b: Int) returns (Int) { return a; } -function makePoint(x: Int, y: Int) -> Point { +function makePoint(x: Int, y: Int) returns (Point) { return pair(x, y); } -function getX(p: Point) -> Int { - match p { - | pair(x, _) => return x; - } +function getX(p: Point) returns (Int) { + match (p) { +case pair(x, _) { +return x; +} +} } -function getY(p: Point) -> Int { - match p { - | pair(_, y) => return y; - } +function getY(p: Point) returns (Int) { + match (p) { +case pair(_, y) { +return y; +} +} } -function main() -> word { +function main() returns (word) { let a: Int = 10; let b: Int = 20; let p: Point = makePoint(a, b); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.sol index 912cc705..fed660be 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-nested.sol @@ -3,21 +3,23 @@ type Word1 = word; type Word2 = Word1; type Word3 = Word2; -type Pair1 = pair(word, word); +type Pair1 = pair; type Pair2 = Pair1; type Pair3 = Pair2; -function useWord3(x: Word3) -> word { +function useWord3(x: Word3) returns (word) { return x; } -function usePair3(p: Pair3) -> word { - match p { - | pair(x, _) => return x; - } +function usePair3(p: Pair3) returns (word) { + match (p) { +case pair(x, _) { +return x; +} +} } -function main() -> word { +function main() returns (word) { let x: Word3 = 42; let p: Pair3 = pair(1, 2); return useWord3(x); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.sol index 1ed3f566..0d27f46e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/synonym-param.sol @@ -1,13 +1,15 @@ -type MyPair(a, b) = pair(a, b); -type IntPair = MyPair(word, word); +type MyPair(a, b) = pair; +type IntPair = MyPair; -function makePair(x: word, y: word) -> MyPair(word, word) { +function makePair(x: word, y: word) returns (MyPair) { return pair(x, y); } -function main() -> word { +function main() returns (word) { let p: IntPair = makePair(42, 100); - match p { - | pair(x, _) => return x; - } + match (p) { +case pair(x, _) { +return x; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.sol index 8bc39371..c2b8dedd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-default-instance.sol @@ -1,13 +1,14 @@ -forall a . class a:Fallback { - function tag(x:a) -> word; +trait Fallback { + function tag(x: a) returns (word) ; } -forall a . default instance a:Fallback { - function tag(x:a) -> word { +default impl Fallback { + function tag(x: a) returns (word) { return 7; } } -function main() -> word { - return Fallback.tag(0:word); +function main() returns (word) { + let value: word = 0; + return Fallback.tag(value); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.sol index 689dee14..4d688c8f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-given-order.sol @@ -1,23 +1,23 @@ pragma no-patterson-condition C; -forall a . class a:A {} -forall a . class a:B {} -forall a . class a:C {} +trait A {} +trait B {} +trait C {} -forall a . a:A, a:B => instance a:C {} +impl C where a: A, a: B {} -forall a . a:C => function needsC(x:a) -> () { +function needsC(x: a) where a: C { return (); } -forall a . a:A, a:B => function fromAB(x:a) -> () { +function fromAB(x: a) where a: A, a: B { return needsC(x); } -forall a . a:B, a:A => function fromBA(x:a) -> () { +function fromBA(x: a) where a: B, a: A { return needsC(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.sol index 29daa886..02beed75 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tabled-residual-given.sol @@ -1,18 +1,18 @@ pragma no-patterson-condition Wanted; -forall a . class a:Known {} -forall a . class a:Wanted {} +trait Known {} +trait Wanted {} -forall a . a:Known => instance a:Wanted {} +impl Wanted where a: Known {} -forall a . a:Wanted => function needsWanted(x:a) -> () { +function needsWanted(x: a) where a: Wanted { return (); } -forall a . a:Known => function passKnown(x:a) -> () { +function passKnown(x: a) where a: Known { return needsWanted(x); } -function main() -> () { +function main() { return (); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.sol index 8b922c9d..f456e1fa 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/td.sol @@ -1,19 +1,17 @@ -forall abs rep . class abs:Typedef(rep) { - function abs(x:rep) -> abs; - function rep(x:abs) -> rep; +trait Typedef { + function abs(x: rep) returns (abs) ; + function rep(x: abs) returns (rep) ; } -forall t. -/* default */ instance t:Typedef(t) { - function abs(x:t) -> t { return x; } - function rep(x:t) -> t { return x; } +impl Typedef { + function abs(x: t) returns (t) { return x; } + function rep(x: t) returns (t) { return x; } } -forall abs rep res. abs:Typedef(rep) => -function lift1ac(f:(rep) -> res, x:abs) -> res { f(Typedef.rep(x)) } +function lift1ac(f: function(rep) returns (res), x: abs) returns (res) where abs: Typedef { f(Typedef.rep(x)) } -forall a. function id(x:a) -> a {x} +function id(x: a) returns (a) {x} contract TD { - public function main() -> word { lift1ac(id, 42) } + function main() public returns (word) { lift1ac(id, 42) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.sol index f51124d8..6a48f806 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tiamat.sol @@ -1,42 +1,43 @@ -data Proxy (a) = Proxy ; -data dict(member, index) = dict(word, Proxy(member), Proxy(index)) ; -data address = address(word) ; -data storage(a) = storage(word) ; - -forall a. -function saddr(s: storage(a)) -> word { - match s { - | storage(a) => return a; - } +enum Proxy { Proxy } +enum dict { dict(word, Proxy, Proxy) } +enum address { address(word) } +enum storage { storage(word) } + +function saddr(s: storage) returns (word) { + match (s) { +case storage(a) { +return a; +} +} } // Untyped Index (access) Proxy -data UIP (m, idx, member) = UIP(m ,idx); +enum UIP { UIP(m, idx) } // Typed Index (access) Proxy -data TIP (m, idx, member) = TIP(m ,idx, Proxy(member)); +enum TIP { TIP(m, idx, Proxy) } -function setbal(ref: storage(dict(address, word)) , src : address, amt: word) -> () { +function setbal(ref: storage>, src: address, amt: word) { /* Based on inference: ref : storage(dict(address, word)) => ref[src] : storage(word) assuming src is of the right type */ - let tip = TIP(ref, src, Proxy:Proxy(word)); + let tip = TIP(ref, src, @word); Assign.assign(LVA.acc(tip), amt); } -function setAllowance(ref: storage(dict(address, dict(address, word))), owner : address, spender : address, amt : word) -> () { +function setAllowance(ref: storage>>, owner: address, spender: address, amt: word) { - let tip1 : TIP(storage(dict(address, dict(address, word))), address, dict(address, word)) - = TIP(ref, owner, Proxy:Proxy(dict(address, word) )); - let ref2 : storage(dict(address,word)) = LVA.acc(tip1); - let tip2 : TIP(storage(dict(address, word)), address, word) - = TIP(ref2, spender, Proxy:Proxy(word)); - let ref3 : storage(word) = LVA.acc(tip2); + let tip1 : TIP>>, address, dict> + = TIP(ref, owner, @dict); + let ref2 : storage> = LVA.acc(tip1); + let tip2 : TIP>, address, word> + = TIP(ref2, spender, @word); + let ref3 : storage = LVA.acc(tip2); Assign.assign(ref3, amt); } -function getAllowance(ref: storage(dict(address, dict(address, word))), owner : address, spender : address) -> word { +function getAllowance(ref: storage>>, owner: address, spender: address) returns (word) { /* let tip : TIP(storage(dict(address, dict(address, word))), address, dict(address, word)) = TIP(ref, owner, Proxy:Proxy(dict(address, word) )); @@ -50,85 +51,77 @@ function getAllowance(ref: storage(dict(address, dict(address, word))), owner : TIP (ref , owner - , Proxy:Proxy(dict(address, word) ) + , @dict ) /* tip : TIP(storage(dict(address, dict(address, word))), address, dict(address, word)) */ ) /* ref2 : storage(dict(address,word)) */ , spender - , Proxy:Proxy(word) + , @word ) /* tip2 : TIP(storage(dict(address, word)), address, word) */ ); } -forall self memberRefType. -class self:LVA(memberRefType) { - function acc(x:self) -> memberRefType; +trait LVA { + function acc(x: self) returns (memberRefType) ; } -forall self member. -class self:RVA(member) { - function acc(x:self) -> member; +trait RVA { + function acc(x: self) returns (member) ; } -forall index member. - instance TIP(storage(dict(index,member)), index, member):LVA(storage(member)) { - function acc(x:TIP(storage(dict(index,member)), index, member)) -> storage(member) { +impl LVA>, index, member>, storage> { + function acc(x: TIP>, index, member>) returns (storage) { return storage(42); } } -forall index member. - instance UIP(storage(dict(index,member)), index, member):LVA(storage(member)) { - function acc(x:UIP(storage(dict(index,member)), index, member)) -> storage(member) { +impl LVA>, index, member>, storage> { + function acc(x: UIP>, index, member>) returns (storage) { return storage(42); } } -forall self. -class self:StorageType { - function sload(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait StorageType { + function sload(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -instance word:StorageType { - function sload(ptr:word) -> word { +impl StorageType { + function sload(ptr: word) returns (word) { let r:word; assembly { r := sload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { sstore(ptr, value) } } } -forall index member. member:StorageType => - instance TIP(storage(dict(index,member)), index, member):RVA(member) { - function acc(x:TIP(storage(dict(index,member)), index, member)) -> member { +impl RVA>, index, member>, member> where member: StorageType { + function acc(x: TIP>, index, member>) returns (member) { let addr = saddr(LVA.acc(x)); return StorageType.sload(addr); } } -forall lhs rhs. -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -forall a. a:StorageType => -instance storage(a):Assign(a) { - function assign(l:storage(a), r:a) -> () { +impl Assign, a> where a: StorageType { + function assign(l: storage, r: a) { StorageType.store(saddr(l), r); } } contract Tiamat { - public function main() -> word { - let allowances : storage(dict(address, dict(address, word))); + function main() public returns (word) { + let allowances : storage>>; let src = address(17); setAllowance(allowances, address(1),address(2), 666); return getAllowance(allowances, address(1),address(2)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.sol index 0de688ce..46b620b9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuple-trick.sol @@ -1,40 +1,44 @@ pragma no-coverage-condition Nth; -data Zero; -data Succ(a); +enum Zero {} +enum Succ {} -data Proxy(a) = Proxy; +enum Proxy { Proxy } -forall a b c . class a : Nth(b,c) { - function nth (x : Proxy(a), y : b) -> c; +trait Nth { + function nth(x: Proxy, y: b) returns (c) ; } -forall a b . instance Zero : Nth((a,b), a) { - function nth (x : Proxy(Zero), y : (a,b)) -> a { - match y { - | (a, b) => return a ; - } +impl Nth { + function nth(x: Proxy, y: (a, b)) returns (a) { + match (y) { +case (a, b) { +return a ; +} +} } } -forall n a b c . n : Nth (b,c) => instance Succ(n) : Nth ((a,b), c) { - function nth (x : Proxy(Succ(n)), y : (a,b)) -> c { - match y { - | (a,b) => return Nth.nth(Proxy : Proxy(n), b); - } +impl Nth, (a, b), c> where n: Nth { + function nth(x: Proxy>, y: (a, b)) returns (c) { + match (y) { +case (a,b) { +return Nth.nth(@n, b); +} +} } } contract C { - public function id (x : word) -> word { + function id(x: word) public returns (word) { return x; } - public function main () -> () { + function main() public { let p : (word, word, word, ()); - let x : word = Nth.nth(Proxy : Proxy(Zero), p); - let y : word = Nth.nth(Proxy : Proxy(Succ(Zero)), p); - let z : word = Nth.nth(Proxy : Proxy(Succ(Succ(Zero))), p); + let x : word = Nth.nth(@Zero, p); + let y : word = Nth.nth(@Succ, p); + let z : word = Nth.nth(@Succ>, p); id(z); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.sol index 31bb144b..001fb9f3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tuva.sol @@ -7,35 +7,35 @@ - Assign class */ -import std.{*} hiding {LValueIdxAccess, RValueIdxAccess, readStorage}; -import std.{Typedef, storage, mapping, address, hash2, StorageType, Assign}; +import * from std hiding {LValueIdxAccess, RValueIdxAccess, readStorage}; +import {Typedef, storage, mapping, address, hash2, StorageType, Assign} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -forall col_idx val . class col_idx:RValueIdxAccess(val) { - function lookup(ci : col_idx) -> val; +trait RValueIdxAccess { + function lookup(ci: col_idx) returns (val) ; } -forall col_idx ref . class col_idx:LValueIdxAccess(ref) { - function lookup(ci : col_idx) -> ref; +trait LValueIdxAccess { + function lookup(ci: col_idx) returns (ref) ; } -forall i a . i:Typedef(word) => -instance (storage(mapping(i,a)), i): LValueIdxAccess(storage(a)) { - function lookup(xi : (storage(mapping(i,a)), i)) -> storage(a) { - match(xi) { - | (x, i) => return storage(hash2(Typedef.rep(x), Typedef.rep(i))); - } +impl LValueIdxAccess<(storage a)>, i), storage> where i: Typedef { + function lookup(xi: (storage a)>, i)) returns (storage) { + match (xi) { +case (x, i) { +return storage(hash2(Typedef.rep(x), Typedef.rep(i))); +} +} // return storage(42); // FIXME: hash2(x,i); } } -forall i a . a:StorageType, i:Typedef(word) => -instance (storage(mapping(i,a)), i): RValueIdxAccess(a) { - function lookup(xi : (storage(mapping(i,a)), i)) -> a { +impl RValueIdxAccess<(storage a)>, i), a> where a: StorageType, i: Typedef { + function lookup(xi: (storage a)>, i)) returns (a) { /* match(xi) { | (x, i) => return StorageType.load(hash2(Typedef.rep(x), Typedef.rep(i))); @@ -45,26 +45,23 @@ instance (storage(mapping(i,a)), i): RValueIdxAccess(a) { } } -forall a. a:StorageType => -function readStorage(x:storage(a)) -> a { +function readStorage(x: storage) returns (a) where a: StorageType { return StorageType.load(Typedef.rep(x)); } -forall r a. r: RValueIdxAccess(a) => -function idx_rval(x:r) -> a { +function idx_rval(x: r) returns (a) where r: RValueIdxAccess { return RValueIdxAccess.lookup(x); } -forall r a. r: LValueIdxAccess(a) => -function idx_lval(x:r) -> a { +function idx_lval(x: r) returns (a) where r: LValueIdxAccess { return LValueIdxAccess.lookup(x); } contract TestTuva { - public function main() -> word { - let balances : storage(mapping(address, word)); - let allowances : storage(mapping(address, mapping(address, word) )); - let ref1 : storage(word) = idx_lval( (balances, address(17)) ); + function main() public returns (word) { + let balances : storage word)>; + let allowances : storage mapping(address => word))>; + let ref1 : storage = idx_lval( (balances, address(17)) ); Assign.assign(idx_lval( (balances, address(1)) ), 1337); let ref2a // : storage( mapping(address, word) ) // omitting this type makes instance resolution fail diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.sol index c3fec25c..c6b5f9d0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/tyexp.sol @@ -1,4 +1,4 @@ -function main () -> word { - let y = 0 : word ; +function main() returns (word) { + let y = 0 ; return y; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.sol index 876e5bda..c24a6442 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/type-synonym-arg.sol @@ -1,10 +1,10 @@ type W = word; -function f(x:W) -> W { x } +function f(x: W) returns (W) { x } contract C { - public function main () -> word { + function main() public returns (word) { return f(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.sol index 1421e691..754ddce9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/typedef.sol @@ -1,9 +1,8 @@ -forall self underlyingType . class self:Typedef(underlyingType) { - function rep(x:self) -> underlyingType; - function abs(x:underlyingType) -> self; +trait Typedef { + function rep(x: self) returns (underlyingType) ; + function abs(x: underlyingType) returns (self) ; } -forall t . t : Typedef((word,(word,word))) => - function tripleFun(x:t) -> (word, (word, word)) { +function tripleFun(x: t) returns (word, (word, word)) where t: Typedef<(word, (word, word))> { return Typedef.rep(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.sol index 78990e05..59473364 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/ufcs-no-conflict.sol @@ -1,4 +1,4 @@ -import std.{*}; +import * from std; // Regression test: the UFCS (receiver-style) method-call rewriting in // NameResolution must coexist with the other uses of dot syntax without @@ -14,18 +14,17 @@ import std.{*}; // type name (`Color.Red`) is handled by the earlier qualified-name cases and // never reaches the UFCS rule. -forall a. -class a : Combiner { - function combine(x : a, y : word) -> word; +trait Combiner { + function combine(x: a, y: word) returns (word) ; } -instance word : Combiner { - function combine(x : word, y : word) -> word { +impl Combiner { + function combine(x: word, y: word) returns (word) { return y; } } -data Color = Red | Green; +enum Color { Red, Green } contract UfcsNoConflict { val : word; @@ -33,19 +32,19 @@ contract UfcsNoConflict { constructor() {} // UFCS receiver call on a contract field. - public function viaUfcs(z : word) -> word { + function viaUfcs(z: word) public returns (word) { return val.combine(z); } // The explicit qualified class call for the same method: NOT rewritten by // UFCS (receiver is the class name `Combiner`, not a field). - public function viaQualified(z : word) -> word { + function viaQualified(z: word) public returns (word) { return Combiner.combine(val, z); } // A dotted constructor and a bare field read still resolve normally // alongside the UFCS rule. - public function dottedConstructorAndFieldRead() -> word { + function dottedConstructorAndFieldRead() public returns (word) { let c : Color = Color.Red; return val; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol index 47365ee2..43b196d9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol @@ -28,7 +28,7 @@ contract Uint { */ -function addW(x : word, y : word) -> word { +function addW(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -36,7 +36,7 @@ function addW(x : word, y : word) -> word { return res; } -function subW(x : word, y : word) -> word { +function subW(x: word, y: word) returns (word) { let res: word; assembly { res := sub(x, y) @@ -44,7 +44,7 @@ function subW(x : word, y : word) -> word { return res; } -function addU(x : uint, y : uint) -> uint { +function addU(x: uint, y: uint) returns (uint) { let res: word; let xw : word = Num.toWord(x); let yw : word = Num.toWord(y); @@ -54,7 +54,7 @@ function addU(x : uint, y : uint) -> uint { return uint(res); } -function hash1(x: word) -> word { +function hash1(x: word) returns (word) { let result: word = 0; assembly { mstore(0, x) @@ -63,7 +63,7 @@ function hash1(x: word) -> word { return result; } -function hash2(x: word, y: word) -> word { +function hash2(x: word, y: word) returns (word) { let result: word = 0; assembly { mstore(0, x) @@ -73,12 +73,11 @@ function hash2(x: word, y: word) -> word { return result; } -forall a. -class a:Num { - function toWord(x:a) -> word; - function fromWord(x:word) -> a; - function add(x:a, y:a) -> a; - function sub(x:a, y:a) -> a; +trait Num { + function toWord(x: a) returns (word) ; + function fromWord(x: word) returns (a) ; + function add(x: a, y: a) returns (a) ; + function sub(x: a, y: a) returns (a) ; } instance word:Num { From 206927c80c3757d83f270125d2f3c6bbb2b293eb Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 071/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../ok/test/examples/cases/uintdesugared.sol | 329 +++++++++--------- .../ok/test/examples/cases/undefined.sol | 6 +- .../corpus/ok/test/examples/cases/unit.sol | 26 +- .../examples/cases/word-match-default.sol | 16 +- .../ok/test/examples/cases/word-match.sol | 15 +- .../cases/yul-asm-break-continue-leave.sol | 6 +- .../test/examples/cases/yul-asm-for-body.sol | 6 +- .../examples/cases/yul-asm-switch-body.sol | 6 +- .../examples/cases/yul-deposit-example.sol | 6 +- .../corpus/ok/test/examples/cases/yul-for.sol | 2 +- .../examples/cases/yul-function-typing.sol | 2 +- .../test/examples/cases/yul-multi-return.sol | 2 +- .../ok/test/examples/cases/yul-return.sol | 2 +- .../ok/test/examples/comptime/CondExpr.sol | 8 +- .../ok/test/examples/comptime/CondStmt.sol | 8 +- .../ok/test/examples/comptime/OneTwo.sol | 10 +- .../corpus/ok/test/examples/comptime/Plus.sol | 10 +- .../corpus/ok/test/examples/comptime/Size.sol | 34 +- .../ok/test/examples/comptime/StdSize.sol | 35 +- .../examples/comptime/comptime_syntax.sol | 8 +- .../ok/test/examples/comptime/counter.sol | 8 +- .../ok/test/examples/comptime/ct_asm_mem.sol | 6 +- .../ok/test/examples/comptime/ct_asm_ret.sol | 4 +- .../ok/test/examples/comptime/ct_chain_ok.sol | 6 +- .../ok/test/examples/comptime/ct_let_ok.sol | 6 +- .../test/examples/comptime/ct_let_runtime.sol | 6 +- .../examples/comptime/ct_overloaded_bad.sol | 12 +- .../examples/comptime/ct_overloaded_ok.sol | 16 +- .../ok/test/examples/comptime/ct_param_ok.sol | 4 +- .../test/examples/comptime/ct_runtime_arg.sol | 6 +- .../ok/test/examples/comptime/erc7201-lit.sol | 6 +- .../corpus/ok/test/examples/comptime/fib.sol | 6 +- .../corpus/ok/test/examples/comptime/fib2.sol | 8 +- .../corpus/ok/test/examples/comptime/fib3.sol | 8 +- .../examples/comptime/int-untyped-let.sol | 8 +- .../test/examples/comptime/integer-basic.sol | 2 +- .../ok/test/examples/comptime/integer-fib.sol | 4 +- .../comptime/integer-from-integer.sol | 10 +- .../examples/comptime/integer-lit-class.sol | 10 +- .../examples/comptime/integer-lit-cond.sol | 4 +- .../examples/comptime/integer-lit-pat.sol | 44 ++- .../examples/comptime/integer-lit-poly.sol | 4 +- .../examples/comptime/integer-lit-safe.sol | 8 +- .../comptime/integer-lit-word-site.sol | 2 +- .../ok/test/examples/comptime/integer-lit.sol | 8 +- .../test/examples/comptime/match_labels.sol | 26 +- .../examples/comptime/string-concat-mem.sol | 14 +- .../examples/comptime/string-lit-dedup.sol | 10 +- .../examples/comptime/string-lit-keccak.sol | 2 +- .../test/examples/comptime/string-lit-len.sol | 2 +- .../test/examples/comptime/string-lit-mem.sol | 4 +- .../test/examples/comptime/string-lit-ops.sol | 6 +- .../comptime/string-param-erasure.sol | 20 +- .../comptime/string-user-instance.sol | 20 +- .../ok/test/examples/comptime/uint256-lit.sol | 4 +- .../ok/test/examples/dispatch/Revert.sol | 10 +- .../examples/dispatch/abi_address_array.sol | 12 +- .../test/examples/dispatch/abi_array_sum.sol | 18 +- 58 files changed, 451 insertions(+), 440 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol index 43b196d9..249a9a5a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/uintdesugared.sol @@ -80,26 +80,27 @@ trait Num { function sub(x: a, y: a) returns (a) ; } -instance word:Num { - function toWord(x:word) -> word { return x; } - function fromWord(x:word) -> word { return x; } - function add(x:word, y:word) -> word { return addW(x, y); } - function sub(x:word, y:word) -> word { return addW(x, y); } +impl Num { + function toWord(x: word) returns (word) { return x; } + function fromWord(x: word) returns (word) { return x; } + function add(x: word, y: word) returns (word) { return addW(x, y); } + function sub(x: word, y: word) returns (word) { return addW(x, y); } } -data uint = uint(word); +enum uint { uint(word) } -instance uint:Num { - function toWord(x:uint) -> word - { - match x { - | uint(y) => return y; - } +impl Num { + function toWord(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function fromWord(x:word) -> uint { return uint(x); } - function add(x:uint, y:uint) -> uint { return uint(addW(Num.toWord(x), Num.toWord(y))); } - function sub(x:uint, y:uint) -> uint { return uint(subW(Num.toWord(x), Num.toWord(y))); } + function fromWord(x: word) returns (uint) { return uint(x); } + function add(x: uint, y: uint) returns (uint) { return uint(addW(Num.toWord(x), Num.toWord(y))); } + function sub(x: uint, y: uint) returns (uint) { return uint(subW(Num.toWord(x), Num.toWord(y))); } } /* // this breaks the Paterson condition @@ -115,10 +116,9 @@ instance a:Num { /////// Construction -forall abs rep. -class abs:Typedef(rep) { - function rep(x:abs) -> rep; - function abs(x:rep) -> abs; +trait Typedef { + function rep(x: abs) returns (rep) ; + function abs(x: rep) returns (abs) ; } @@ -131,97 +131,99 @@ forall a } */ -instance word:Typedef(word) { - function rep(x:word) -> word { return x; } - function abs(x:word) -> word { return x; } +impl Typedef { + function rep(x: word) returns (word) { return x; } + function abs(x: word) returns (word) { return x; } } -instance uint:Typedef(word) { - function rep(x:uint) -> word { - match x { - | uint(y) => return y; - } +impl Typedef { + function rep(x: uint) returns (word) { + match (x) { +case uint(y) { +return y; +} +} } - function abs(x:word) -> uint { + function abs(x: word) returns (uint) { return uint(x); } } -data address = address(word); +enum address { address(word) } -instance address:Typedef(word) { - function rep(x:address) -> word { - match x { - | address(y) => return y; - } +impl Typedef { + function rep(x: address) returns (word) { + match (x) { +case address(y) { +return y; +} +} } - function abs(x:word) -> address { + function abs(x: word) returns (address) { return address(x); } } -data storage(a) = storage(word); -data ContractStorage(cxt) = ContractStorage(cxt); +enum storage { storage(word) } +enum ContractStorage { ContractStorage(cxt) } -data storageRef(a) = storageRef(word); -data Proxy(a) = Proxy; +enum storageRef { storageRef(word) } +enum Proxy { Proxy } -data mapRef(a) = mapRef(word); //ref to a map elem +enum mapRef { mapRef(word) } //ref to a map elem // data memoryRef(a) = memoryRef(word); -forall a. -instance storage(a):Typedef(word) { - function rep(x:storage(a)) -> word { - match x { - | storage(y) => return y; - } +impl Typedef, word> { + function rep(x: storage) returns (word) { + match (x) { +case storage(y) { +return y; +} +} } - function abs(x:word) -> storage(a) { + function abs(x: word) returns (storage) { return storage(x); } } -forall a. -instance storageRef(a):Typedef(word) { - function rep(x:storageRef(a)) -> word { - match x { - | storageRef(y) => return y; - } +impl Typedef, word> { + function rep(x: storageRef) returns (word) { + match (x) { +case storageRef(y) { +return y; +} +} } - function abs(x:word) -> storageRef(a) { + function abs(x: word) returns (storageRef) { return storageRef(x); } } -forall lhs rhs. -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -data ref(a) = ref(a); +enum ref { ref(a) } -forall a. -instance ref(a):Assign(a) { - function assign(l:ref(a), r:a) -> () { +impl Assign, a> { + function assign(l: ref, r: a) { // builtin "stack store" return (); } } -forall self. -class self:StorageType { - function sload(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait StorageType { + function sload(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } -forall self. -class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -function sload_(x:word) -> word { +function sload_(x: word) returns (word) { let res: word; assembly { res := sload(x) @@ -229,80 +231,75 @@ function sload_(x:word) -> word { return res; } -function sstore_(a:word, v:word) -> () { +function sstore_(a: word, v: word) { assembly { sstore(a,v) } } -instance word:StorageType { - function sload(ptr:word) -> word { +impl StorageType { + function sload(ptr: word) returns (word) { let r:word; assembly { r := sload(ptr) } return r; } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { assembly { sstore(ptr, value) } } } -instance uint:StorageType { - function sload(ptr:word) -> uint { - return Typedef.abs(sload_(ptr)):uint; // type annotation needed due to a typechecker bug +impl StorageType { + function sload(ptr: word) returns (uint) { + return Typedef.abs(sload_(ptr)); // type annotation needed due to a typechecker bug } - function store(ptr:word, value:uint) -> () { + function store(ptr: word, value: uint) { return sstore_(ptr, Typedef.rep(value)); } } -instance address:StorageType { - function sload(ptr:word) -> address { - return Typedef.abs(sload_(ptr)):address; // type annotation needed due to a typechecker bug +impl StorageType
{ + function sload(ptr: word) returns (address) { + return Typedef.abs(sload_(ptr)); // type annotation needed due to a typechecker bug } - function store(ptr:word, value:address) -> () { + function store(ptr: word, value: address) { return sstore_(ptr, Typedef.rep(value)); } } -forall a . a : StorageType => instance storageRef(a):Assign(a) { - function assign(l:storageRef(a), y:a) -> () { +impl Assign, a> where a: StorageType { + function assign(l: storageRef, y: a) { StorageType.store(Typedef.rep(l), y); } } -forall self fieldType offsetType. -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field offset . -function memberAccessD1(x:MemberAccessProxy(a, field, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessD1(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } -forall self memberRefType. -class self:LValueMemberAccess(memberRefType) { - function memberAccess(x:self) -> memberRefType; +trait LValueMemberAccess { + function memberAccess(x: self) returns (memberRefType) ; } -forall self memberValueType . -class self:RValueMemberAccess(memberValueType) { - function memberAccess(x:self) -> memberValueType; +trait RValueMemberAccess { + function memberAccess(x: self) returns (memberValueType) ; } -forall structType fieldSelector fieldType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(storage(structType), fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(storage(structType), fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr:word = Typedef.rep(memberAccessD1(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); + let size:word = StorageSize.size(@offsetType); assembly { ptr := add(ptr, size) } @@ -310,26 +307,26 @@ forall structType fieldSelector fieldType offsetType } } -instance ():StorageSize { - function size(x:Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance uint:StorageSize { - function size(x:Proxy(uint)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance address:StorageSize { - function size(x:Proxy(address)) -> word { +impl StorageSize
{ + function size(x: Proxy
) returns (word) { return 1; } } @@ -345,10 +342,10 @@ forall a b . a:Typedef(b), b:StorageSize } */ -forall a b . a:StorageSize, b:StorageSize => instance (a,b):StorageSize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = StorageSize.size(Proxy:Proxy(a)); - let b_sz:word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = StorageSize.size(@a); + let b_sz:word = StorageSize.size(@b); assembly { a_sz := add(a_sz, b_sz) } @@ -363,13 +360,10 @@ pragma no-coverage-condition MemberAccessProxy, LValueMemberAccess, RValueMember // Contract field access // ------------------------------------------------------------------ -forall cxt fieldSelector fieldType offsetType - . StructField(ContractStorage(cxt), fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType):LValueMemberAccess(storageRef(fieldType)) { - function memberAccess(x:MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType)) -> storageRef(fieldType) { +impl LValueMemberAccess, fieldSelector, offsetType>, storageRef> where StructField, fieldSelector>: CStructField, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (storageRef) { let ptr:word = 0x100; // forge uses at least 1 storage slot - let offsetSize:word = StorageSize.size(Proxy:Proxy(offsetType)); + let offsetSize:word = StorageSize.size(@offsetType); assembly { ptr := add(ptr, offsetSize) @@ -378,15 +372,11 @@ forall cxt fieldSelector fieldType offsetType } } -forall cxt fieldSelector fieldType offsetType - . StructField(ContractStorage(cxt), fieldSelector):CStructField(fieldType, offsetType) - , fieldType:StorageType - , offsetType:StorageSize - => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType):RValueMemberAccess(fieldType) { - function memberAccess(x:MemberAccessProxy(ContractStorage(cxt), fieldSelector, offsetType)) -> fieldType { +impl RValueMemberAccess, fieldSelector, offsetType>, fieldType> where StructField, fieldSelector>: CStructField, fieldType: StorageType, offsetType: StorageSize { + function memberAccess(x: MemberAccessProxy, fieldSelector, offsetType>) returns (fieldType) { let ptr:word = 0x100; - let offsetSize:word = StorageSize.size(Proxy:Proxy(offsetType)); - return StorageType.sload(addW(ptr, offsetSize)):fieldType; + let offsetSize:word = StorageSize.size(@offsetType); + return StorageType.sload(addW(ptr, offsetSize)); } } @@ -407,55 +397,53 @@ forall cxt fieldSelector fieldType offsetType // Indexed access // ------------------------------------------------------------------ -data mapping(index, member) = mapping(word); +enum mapping { mapping(word) } -forall member index . instance mapping(index, member):Typedef(word) { - function rep(x:mapping(index, member)) -> word { - match x { - | mapping(y) => return y; - } +impl Typedef member), word> { + function rep(x: mapping(index => member)) returns (word) { + match (x) { +case mapping(y) { +return y; +} +} } - function abs(x:word) -> mapping(index,member) { + function abs(x: word) returns (mapping(index => member)) { return mapping(x); } } // cf https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays -forall index member . -instance mapping(index, member):StorageSize { - function size(x:Proxy(mapping(index, member))) -> word { +impl StorageSize member)> { + function size(x: Proxy member)>) returns (word) { return 1; } } -data IndexAccessProxy(map, index, member) = IndexAccessProxy(map, index); +enum IndexAccessProxy { IndexAccessProxy(map, index) } -forall map index member. index:Typedef(word), map:Typedef(word) -=> instance IndexAccessProxy(map, index, member):LValueMemberAccess(storageRef(member)) { - function memberAccess(x:IndexAccessProxy(map, index, member)) -> storageRef(member) { +impl LValueMemberAccess, storageRef> where index: Typedef, map: Typedef { + function memberAccess(x: IndexAccessProxy) returns (storageRef) { return storageRef(indexStorageSlot(x)); } } -forall map index member . index:Typedef(word), member:StorageType, map:Typedef(word) -=> instance IndexAccessProxy(map, index, member):RValueMemberAccess(member) { - function memberAccess(x:IndexAccessProxy(map, index, member)) -> member { +impl RValueMemberAccess, member> where index: Typedef, member: StorageType, map: Typedef { + function memberAccess(x: IndexAccessProxy) returns (member) { let slot:word = indexStorageSlot(x); return StorageType.sload(slot); } } -forall index map member. map:Typedef(word), index:Typedef(word) => function indexStorageSlot(x:IndexAccessProxy(map, index, member)) -> word -//function indexStorageSlot(x) -{ - match x { - | IndexAccessProxy(map, i) => - let mapptr:word = Typedef.rep(map); +function indexStorageSlot(x: IndexAccessProxy) returns (word) where map: Typedef, index: Typedef { + match (x) { +case IndexAccessProxy(map, i) { +let mapptr:word = Typedef.rep(map); let rawidx:word = Typedef.rep(i); let loc:word = hash2(mapptr, rawidx); return loc; - } +} +} } /* @@ -471,41 +459,40 @@ forall index map member. map:Typedef(word), index:Typedef(word) } */ -forall a b. a:RValueMemberAccess(b) => -function rval(x:a) -> b { +function rval(x: a) returns (b) where a: RValueMemberAccess { return RValueMemberAccess.memberAccess(x); } -data UintCxt = UintCxt ; -data reserved_sel = reserved_sel ; -instance StructField(ContractStorage(UintCxt), reserved_sel) :CStructField(word, ()) { +enum UintCxt { UintCxt } +enum reserved_sel { reserved_sel } +impl CStructField, reserved_sel>, word, ()> { } -data owner_sel = owner_sel ; -instance StructField(ContractStorage(UintCxt), owner_sel) :CStructField(address, (word, ())) { +enum owner_sel { owner_sel } +impl CStructField, owner_sel>, address, (word, ())> { } -data decimals_sel = decimals_sel ; -instance StructField(ContractStorage(UintCxt), decimals_sel) :CStructField(uint, (word, (address, ()))) { +enum decimals_sel { decimals_sel } +impl CStructField, decimals_sel>, uint, (word, (address, ()))> { } -data totalSupply_sel = totalSupply_sel ; -instance StructField(ContractStorage(UintCxt), totalSupply_sel) :CStructField(uint, (word, (address, (uint, ())))) { +enum totalSupply_sel { totalSupply_sel } +impl CStructField, totalSupply_sel>, uint, (word, (address, (uint, ())))> { } -data balances_sel = balances_sel ; -instance StructField(ContractStorage(UintCxt), balances_sel) :CStructField(mapping(address, uint), (word, (address, (uint, (uint, ()))))) { +enum balances_sel { balances_sel } +impl CStructField, balances_sel>, mapping(address => uint), (word, (address, (uint, (uint, ()))))> { } contract Uint { - public function mint (amount : uint) -> () { + function mint(amount: uint) public { Assign.assign(LValueMemberAccess.memberAccess(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)))), Num.add(rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)))), amount)); Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), totalSupply_sel)), Num.add(rval(MemberAccessProxy(ContractStorage(UintCxt), totalSupply_sel)), amount)); } - public function init () -> () { + function init() public { Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)), address(81985529216486895)); Assign.assign(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), decimals_sel)), Num.fromWord(18)); } - public function main () -> uint { + function main() public returns (uint) { init(); mint(uint(1000)); mint(uint(1000)); - return rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)))) : uint; + return rval(IndexAccessProxy(LValueMemberAccess.memberAccess(MemberAccessProxy(ContractStorage(UintCxt), balances_sel)), rval(MemberAccessProxy(ContractStorage(UintCxt), owner_sel)))) ; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.sol index 38e05d12..5015f383 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/undefined.sol @@ -1,13 +1,13 @@ -forall any.function undefined() -> any { +function undefined() returns (any) { assembly { revert(0,0) } } -function useWord(w:word) -> () {} +function useWord(w: word) {} contract Magic { - public function main() -> () { + function main() public { useWord(undefined()); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.sol index 98e93ae7..4fc1e729 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/unit.sol @@ -1,33 +1,35 @@ contract Unit { -public function one (x : ()) -> word { +function one(x: ()) public returns (word) { return 1; } -public function unitVal() -> () { +function unitVal() public { return (); } -public function unitMatch (x : ()) -> word { - match x { - | () => return 1; - } +function unitMatch(x: ()) public returns (word) { + match (x) { +case () { +return 1; +} +} } -public function foo (x : word) -> () { +function foo(x: word) public { return (); } -public function main() -> word { +function main() public returns (word) { return unitMatch(foo(one(unitVal()))); } } -forall a . class a : Def { - function def () -> a ; +trait Def { + function def() returns (a) ; } -instance () : Def { - function def() -> () { +impl Def<()> { + function def() { return (); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.sol index c1b17b95..e69d4611 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match-default.sol @@ -1,14 +1,18 @@ contract WordMatchDefault { - public function f(n : word) -> word { + function f(n: word) public returns (word) { let result : word; - match n { - | 0 => assembly { result := 100 } - | x => assembly { result := x } - } + match (n) { +case 0 { +assembly { result := 100 } +} +case x { +assembly { result := x } +} +} return result; } - public function main() -> word { + function main() public returns (word) { return f(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.sol index 07c20ad0..8a298dad 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/word-match.sol @@ -1,11 +1,12 @@ -forall a . class a:IsWord { function toWord(x : a) -> word; } +trait IsWord { function toWord(x: a) returns (word) ; } -function kw(a:word, b:word) -> word {return a;} +function kw(a: word, b: word) returns (word) {return a;} -forall a b . a:IsWord, b:IsWord -=> function bar(x:(a,b)) -> word { - match x { - | (t,u) => return kw(IsWord.toWord(t), IsWord.toWord(u)); - } +function bar(x: (a, b)) returns (word) where a: IsWord, b: IsWord { + match (x) { +case (t,u) { +return kw(IsWord.toWord(t), IsWord.toWord(u)); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.sol index bee240d3..47ce5cc7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-break-continue-leave.sol @@ -1,6 +1,6 @@ -import std.{*}; +import * from std; -function yul_asm_break_continue_leave() -> () { +function yul_asm_break_continue_leave() { let result : word = 0; assembly { function clamp(x) -> y { @@ -23,7 +23,7 @@ function yul_asm_break_continue_leave() -> () { } contract Foo { - public function main() -> () { + function main() public { yul_asm_break_continue_leave() } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.sol index 806a0d11..7a94c2fd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-for-body.sol @@ -1,6 +1,6 @@ -import std.{*}; +import * from std; -function yul_asm_for_body() -> () { +function yul_asm_for_body() { let result : word = 0; assembly { for { let i := 0 } lt(i, 3) { i := add(i, 1) } { @@ -10,7 +10,7 @@ function yul_asm_for_body() -> () { } contract Foo { - public function main() -> () { + function main() public { yul_asm_for_body() } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.sol index 76e914ff..73e7e5cd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-asm-switch-body.sol @@ -1,6 +1,6 @@ -import std.{*}; +import * from std; -function yul_asm_switch_body() -> () { +function yul_asm_switch_body() { let result : word = 0; let flag : word = 1; assembly { @@ -11,7 +11,7 @@ function yul_asm_switch_body() -> () { } contract Foo { - public function main() -> () { + function main() public { yul_asm_switch_body() } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.sol index 53992aa8..8e5b9147 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-deposit-example.sol @@ -1,6 +1,6 @@ -import std.{*}; +import * from std; -function deposit(pubkey: memory(string), withdrawal_credentials: memory(string), signature: memory(string), deposit_data_root: uint256) -> () { +function deposit(pubkey: memory, withdrawal_credentials: memory, signature: memory, deposit_data_root: uint256) { let msg_value : word = 0; assembly { msg_value := callvalue() @@ -8,7 +8,7 @@ function deposit(pubkey: memory(string), withdrawal_credentials: memory(string), } contract Foo { - public function main () -> () { + function main() public { deposit(memory(0), memory(0), memory(0), uint256(2)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.sol index f0a1497d..020aa5b9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-for.sol @@ -1,5 +1,5 @@ contract YulFor { - public function main() -> word { + function main() public returns (word) { let loopStart : word = 128; let loopEnd : word = 256; let res : word; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.sol index 32812c24..68bf6430 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-function-typing.sol @@ -1,4 +1,4 @@ -function foo(length:word, pos:word) -> word { +function foo(length: word, pos: word) returns (word) { let ret: word; assembly { // ret := add(pos, mul(0x20, iszero(iszero(length)))) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.sol index 4c2666ed..3b6a6d10 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-multi-return.sol @@ -3,7 +3,7 @@ // so the type checker must accept it (regression for the arity check that used // to collapse every non-empty return list to a single 'word'). contract YulMultiRet { - public function main() -> word { + function main() public returns (word) { let x : word; let y : word; assembly { diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.sol index 0dc00a80..675e1b96 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/cases/yul-return.sol @@ -1,5 +1,5 @@ contract C { - public function main() -> () { + function main() public { assembly { return(0,0) } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.sol index a2fac7f5..90eb4633 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondExpr.sol @@ -1,12 +1,12 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function notAnswer(n : word) -> word { if(n == 42) then 0 else 42 } +function notAnswer(n: word) returns (word) { (n == 42) ? 0 : 42 } -function answer(n:word) -> word { notAnswer(notAnswer(42)) } +function answer(n: word) returns (word) { notAnswer(notAnswer(42)) } contract Fib { - public function main() -> word { answer(42) } + function main() public returns (word) { answer(42) } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.sol index c0bb72f0..46aaef86 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/CondStmt.sol @@ -1,17 +1,17 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function notAnswer(n : word) -> word { +function notAnswer(n: word) returns (word) { if(n == 42) { return 0; } else {return 42; } } -function answer(n:word) -> word { +function answer(n: word) returns (word) { return notAnswer(notAnswer(42)); } contract Fib { -public function main() -> word { +function main() public returns (word) { return answer(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.sol index 9a16738d..d27b73c6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/OneTwo.sol @@ -1,5 +1,5 @@ // This function should be in stdlib -function addWord(l: word, r: word) -> word { +function addWord(l: word, r: word) returns (word) { let rw : word; assembly { rw := add(l,r) @@ -7,15 +7,15 @@ function addWord(l: word, r: word) -> word { return rw; } - function zero () -> word { + function zero() returns (word) { return 0; } -function one() -> word { +function one() returns (word) { return addWord(1, zero()) ; } -function two () -> word { +function two() returns (word) { let x = zero(); x = addWord(x, one()); x = addWord(x,x); @@ -23,6 +23,6 @@ function two () -> word { } contract OneTwo { - public function main() -> word { return two(); } + function main() public returns (word) { return two(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol index 2d34d846..d4a651f1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol @@ -1,16 +1,16 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; - function zero () -> word { + function zero() returns (word) { return 0; } -function one() -> word { +function one() returns (word) { return 1 + zero() ; } -function two () -> word { +function two() returns (word) { let x = zero(); x = x + one(); x = x + x ; @@ -18,5 +18,5 @@ function two () -> word { } contract Plus { - public function main() -> word { return two() + two(); } + function main() public returns (word) { return two() + two(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.sol index 292b99e7..f7b3c124 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Size.sol @@ -1,6 +1,6 @@ -data Proxy(t) = Proxy; +enum Proxy { Proxy } -function addWord(l: word, r: word) -> word { +function addWord(l: word, r: word) returns (word) { let rw : word; assembly { rw := add(l,r) @@ -8,42 +8,40 @@ function addWord(l: word, r: word) -> word { return rw; } -forall self. -class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -forall self. -default instance self:StorageSize { - function size(x:Proxy(self)) -> word { +default impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance ():StorageSize { - function size(x:Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -forall a b. a:StorageSize, b:StorageSize => instance (a,b):StorageSize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = StorageSize.size(Proxy:Proxy(a)); - let b_sz:word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = StorageSize.size(@a); + let b_sz:word = StorageSize.size(@b); return addWord(a_sz, b_sz); } } contract Size { - public function main() -> word { + function main() public returns (word) { return - StorageSize.size(Proxy:Proxy( (word, (word, ())))); } + StorageSize.size(@(word, (word, ()))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.sol index 17123de6..12a59f14 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/StdSize.sol @@ -1,6 +1,6 @@ -data Proxy(t) = Proxy; +enum Proxy { Proxy } -function addWord(l: word, r: word) -> word { +function addWord(l: word, r: word) returns (word) { let rw: word; assembly { rw := add(l, r) @@ -8,41 +8,38 @@ function addWord(l: word, r: word) -> word { return rw; } -forall self. -class self:StorageSize { - function size(x: Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -forall self. -default instance self:StorageSize { - function size(x: Proxy(self)) -> word { +default impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance ():StorageSize { - function size(x: Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x: Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -forall a b. a:StorageSize, b:StorageSize => -instance (a, b):StorageSize { - function size(x: Proxy((a, b))) -> word { - let a_sz: word = StorageSize.size(Proxy:Proxy(a)); - let b_sz: word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz: word = StorageSize.size(@a); + let b_sz: word = StorageSize.size(@b); return addWord(a_sz, b_sz); } } contract Size { - public function main() -> word { - return StorageSize.size(Proxy:Proxy((word, (word, ())))); + function main() public returns (word) { + return StorageSize.size(@(word, (word, ()))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.sol index 50c9ef37..21fe626a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/comptime_syntax.sol @@ -1,15 +1,15 @@ contract ComptimeSyntax { - function f(comptime x : word) -> comptime word { + function f(comptime x: word) returns (comptime) { return x; } - function g() -> word { - let y : comptime word = f(42); + function g() returns (word) { + let y : comptime = f(42); return y; } - function main() -> word { + function main() returns (word) { return g(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.sol index 8c93f43e..7d60ab20 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/counter.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.{uint256, address}; -import std.dispatch.{*}; +import * from std; +import {uint256, address} from std; +import * from std.dispatch; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -18,7 +18,7 @@ contract Counter { fld0 = 7; } - public function main() -> word { + function main() public returns (word) { counter = counter + 1; return counter; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.sol index 94a8d86a..765d09d9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_mem.sol @@ -2,7 +2,7 @@ when its argument is known at compile time. The evaluator runs in comptime mode for the RHS of `let x : comptime`. */ -function storeLoad(x : word) -> word { +function storeLoad(x: word) returns (word) { let r : word; assembly { mstore(0, x) @@ -12,8 +12,8 @@ function storeLoad(x : word) -> word { } contract ComptimeAsmMem { - function main() -> word { - let res : comptime word = storeLoad(42); + function main() returns (word) { + let res : comptime = storeLoad(42); return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.sol index b0d3893b..3ba34ae7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_asm_ret.sol @@ -4,14 +4,14 @@ */ contract ComptimeAsmRet { - function loadFromStorage() -> comptime word { + function loadFromStorage() returns (comptime) { let v : word; assembly { v := sload(0) } return v; } - function main() -> word { + function main() returns (word) { return loadFromStorage(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.sol index a35f9f41..5dc8d050 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_chain_ok.sol @@ -4,13 +4,13 @@ import std; contract ComptimeChainOk { - function increment(comptime x : word) -> comptime word { + function increment(comptime x: word) returns (comptime) { return x + 1; } - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function main() -> word { + function main() returns (word) { return double(increment(20)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.sol index 4f3739a9..6bad2af6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_ok.sol @@ -2,11 +2,11 @@ import std; contract ComptimeLetOk { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function main() -> word { - let y : comptime word = double(21); + function main() returns (word) { + let y : comptime = double(21); return y; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.sol index 2db7a7d6..16c9def3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_let_runtime.sol @@ -5,7 +5,7 @@ */ import std; -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -14,8 +14,8 @@ function sloadWord() -> word { } contract ComptimeLetRuntime { - function main() -> word { - let y : comptime word = sloadWord(); + function main() returns (word) { + let y : comptime = sloadWord(); return y; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.sol index 68042e0a..19af3db5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_bad.sol @@ -5,12 +5,12 @@ */ import std; -forall a. class a : Scale { - function scale(comptime factor : word, comptime x : a) -> comptime a; +trait Scale { + function scale(comptime factor: word, comptime x: a) returns (comptime) ; } -instance word : Scale { - function scale(comptime factor : word, comptime x : word) -> comptime word { +impl Scale { + function scale(comptime factor: word, comptime x: word) returns (comptime) { let base : word; assembly { base := sload(0) @@ -20,8 +20,8 @@ instance word : Scale { } contract ComptimeOverloadedBad { - function main() -> word { - let a : comptime word = Scale.scale(3, 10); + function main() returns (word) { + let a : comptime = Scale.scale(3, 10); return a; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.sol index f6252490..1b274e2c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_overloaded_ok.sol @@ -4,14 +4,14 @@ mulWord is builtinPure, so multiplication of comptime values is comptime. The verifier must follow specialization and accept this. */ -import std.{*}; +import * from std; -forall a. class a : Scale { - function scale(comptime factor : word, comptime x : a) -> comptime a; +trait Scale { + function scale(comptime factor: word, comptime x: a) returns (comptime) ; } -instance word : Scale { - function scale(comptime factor : word, comptime x : word) -> comptime word { +impl Scale { + function scale(comptime factor: word, comptime x: word) returns (comptime) { if (factor == 1) { return x; } else { @@ -21,9 +21,9 @@ instance word : Scale { } contract ComptimeOverloadedOk { - function main() -> word { - let a : comptime word = Scale.scale(1, 32); - let b : comptime word = Scale.scale(3, 10); + function main() returns (word) { + let a : comptime = Scale.scale(1, 32); + let b : comptime = Scale.scale(3, 10); return a + b; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.sol index 68bf7247..58d98c54 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_param_ok.sol @@ -5,10 +5,10 @@ import std; contract ComptimeParamOk { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function main() -> word { + function main() returns (word) { return double(21); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.sol index ed9e0132..d40acb84 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/ct_runtime_arg.sol @@ -4,7 +4,7 @@ */ import std; -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -13,10 +13,10 @@ function sloadWord() -> word { } contract ComptimeRuntimeArg { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function main() -> word { + function main() returns (word) { return double(sloadWord()); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.sol index 4431bc35..004f225b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/erc7201-lit.sol @@ -1,17 +1,17 @@ -import std.{*}; +import * from std; // erc7201 is comptime-only: given a string-literal namespace it folds the two // nested keccaks and the word arithmetic down to a single bytes32 slot // constant, with no runtime hashing. contract Erc7201Lit { - public function main() -> bytes32 { + function main() public returns (bytes32) { // keccak256(abi.encode(uint256(keccak256("example.main")) - 1)) & ~0xff // == 0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500 return erc7201("example.main"); } // keccakWordLit on its own: keccak of a word's 32-byte big-endian form. - public function wordHash() -> word { + function wordHash() public returns (word) { return keccakWordLit(0); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.sol index 46498180..cf054116 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib.sol @@ -1,14 +1,14 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function fib(n : word) -> word { +function fib(n: word) returns (word) { if(n < 2) { return n; } else {return fib(n-1) + fib(n-2); } } contract Fib { -public function main() -> word { +function main() public returns (word) { return fib(10); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.sol index 5cd5c869..48c31936 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib2.sol @@ -1,12 +1,12 @@ -import std.{*}; +import * from std; -function fib2(n : word) -> comptime word { +function fib2(n: word) returns (comptime) { if(n < 2) { return n; } else {return fib2(n-1) + fib2(n-2); } } contract Fib { - function main() -> word { - let res : comptime word = fib2(10); + function main() returns (word) { + let res : comptime = fib2(10); return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.sol index 62d396e8..4295ea80 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/fib3.sol @@ -1,12 +1,12 @@ -import std.{*}; +import * from std; -function fib3(n : word) -> word { +function fib3(n: word) returns (word) { if(n < 2) { return n; } else {return fib3(n-1) + fib3(n-2); } } contract Fib { - function main() -> word { - let res : comptime word = fib3(10); + function main() returns (word) { + let res : comptime = fib3(10); return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.sol index ffad1f7d..e727bd83 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/int-untyped-let.sol @@ -1,8 +1,8 @@ // Bare integer literals with integer class instances from std. -import std.{Eq,Ord,lt,Add,Sub}; +import {Eq,Ord,lt,Add,Sub} from std; -function fib(comptime n : integer) -> comptime integer { +function fib(comptime n: integer) returns (comptime) { if (n < 2) { return n; } else { @@ -12,9 +12,9 @@ function fib(comptime n : integer) -> comptime integer { } contract IntegerLit { - function main() -> word { + function main() returns (word) { let x = 20; - let res : comptime word = Int.fromInteger(fib(x)); + let res : comptime = Int.fromInteger(fib(x)); return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.sol index c58ee6ef..a7072fc1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-basic.sol @@ -3,7 +3,7 @@ // Expected: main() folds to word literal 100. contract IntegerBasic { - function main() -> word { + function main() returns (word) { let x = 42; let y = integerAdd(x, 8); return wordFromInteger(integerMul(y, 2)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.sol index 9726d8e8..54b5d56b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-fib.sol @@ -2,7 +2,7 @@ // No import std needed: uses only compiler builtins. // Expected: main() folds to word literal 55 (fib(10)). -function fib(comptime n : integer) -> comptime integer { +function fib(comptime n: integer) returns (comptime) { if (integerLt(n, 2)) { return n; } else { @@ -14,7 +14,7 @@ function fib(comptime n : integer) -> comptime integer { } contract FibInteger { - function main() -> word { + function main() returns (word) { return wordFromInteger(fib(10)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.sol index e156e2d4..c18110ae 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-from-integer.sol @@ -1,9 +1,9 @@ -import std.{*}; +import * from std; // Tests Num.fromInteger for word (Typedef.abs = identity) and uint256 (wraps in uint256(...)). // Also tests the full design-doc pattern: comptime integer fib result converted via Num.fromInteger. -function fib(comptime n : integer) -> comptime integer { +function fib(comptime n: integer) returns (comptime) { if (integerLt(n, wordToInteger(2))) { return n; } else { @@ -20,9 +20,9 @@ function fib(comptime n : integer) -> comptime integer { // Returns Typedef.rep(u) = 55, demonstrating the uint256 round-trip. // Expected: main() folds to word literal 55. contract IntegerFromInteger { - function main() -> word { - let w : comptime word = Num.fromInteger(wordToInteger(42)); - let u : comptime uint256 = Num.fromInteger(fib(wordToInteger(10))); + function main() returns (word) { + let w : comptime = Num.fromInteger(wordToInteger(42)); + let u : comptime = Num.fromInteger(fib(wordToInteger(10))); return Typedef.rep(u); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.sol index 636381a7..24319eea 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-class.sol @@ -2,9 +2,9 @@ // The type checker infers the literal type from context: the integer:Ord/Add/Sub // instances constrain unresolved literals to `integer`. -import std.{Eq,Ord,lt,Add,Sub}; +import {Eq,Ord,lt,Add,Sub} from std; -function fib(comptime n : integer) -> comptime integer { +function fib(comptime n: integer) returns (comptime) { if (n < 2) { return n; } else { @@ -14,9 +14,9 @@ function fib(comptime n : integer) -> comptime integer { } contract IntegerLit { - function main() -> word { - let x : comptime integer = 20; - let res : comptime word = wordFromInteger(fib(x)); + function main() returns (word) { + let x : comptime = 20; + let res : comptime = wordFromInteger(fib(x)); return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.sol index f6dcd8c5..794e868e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-cond.sol @@ -3,9 +3,9 @@ // in branches infer the correct type. contract CondLit { - function main() -> word { + function main() returns (word) { // Both literal branches should infer type word from the return annotation. - let x : word = if (true) then 1 else 2; + let x : word = (true) ? 1 : 2; return x; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.sol index f5ec9007..bc1b3fe8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-pat.sol @@ -1,27 +1,39 @@ // Integer literal patterns against word and integer scrutinees. -import std.{Add}; +import {Add} from std; -function classify_word(comptime n : word) -> comptime word { - match n { - | 0 => return 10; - | 1 => return 20; - | _ => return 0; - } +function classify_word(comptime n: word) returns (comptime) { + match (n) { +case 0 { +return 10; +} +case 1 { +return 20; +} +default { +return 0; +} +} } -function classify_integer(comptime n : integer) -> comptime integer { - match n { - | 0 => return integerAdd(n, 10); - | 1 => return integerAdd(n, 20); - | _ => return n; - } +function classify_integer(comptime n: integer) returns (comptime) { + match (n) { +case 0 { +return integerAdd(n, 10); +} +case 1 { +return integerAdd(n, 20); +} +default { +return n; +} +} } contract PatternLit { - function main() -> word { - let a : comptime word = classify_word(1); - let b : comptime integer = classify_integer(0); + function main() returns (word) { + let a : comptime = classify_word(1); + let b : comptime = classify_integer(0); return Add.add(a, wordFromInteger(b)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.sol index d67ab32c..17fd000b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-poly.sol @@ -4,10 +4,10 @@ // Add.add(s, 1) with s:word => 1 infers as word (Add a => a->a->a, a=word) // integerAdd(n, 1) with n:integer => 1 infers as integer (param type is integer) -import std.{Add}; +import {Add} from std; contract PolyLit { - function main() -> word { + function main() returns (word) { let s : word = 0; // 1 inferred as word via Add.add constraint let s2 : word = Add.add(s, 1); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.sol index 4eef8d7b..98bed62e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-safe.sol @@ -1,4 +1,4 @@ -import std.{*}; +import * from std; // Safety: verify literals pick up the correct type from context, no spurious coercions. // @@ -9,16 +9,16 @@ import std.{*}; // let z : word = 5 — explicit word annotation, wordFromInteger coercion inserted contract IntegerLitSafe { - function main() -> word { + function main() returns (word) { // word arithmetic: 1 and 2 must stay as word literals let a : word = addWord(1, 2); // already-explicit coercions: no double-wrapping of the inner 42 - let ok : comptime bool = integerEq(wordToInteger(42), wordToInteger(42)); + let ok : comptime = integerEq(wordToInteger(42), wordToInteger(42)); // wordFromInteger param is integer, but wordToInteger(10) is a Call not a // literal, so no double-wrap; b folds to 10 - let b : comptime word = wordFromInteger(wordToInteger(10)); + let b : comptime = wordFromInteger(wordToInteger(10)); // word-annotated let: annotation is word, not integer -> no coercion let z : word = 5; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.sol index 8b52fbc9..37970467 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit-word-site.sol @@ -5,7 +5,7 @@ // passing literal to word parameter contract WordSite { - function main() -> word { + function main() returns (word) { let a : word = 42; let b : word = 0; return a; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.sol index db376d78..96f827bd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/integer-lit.sol @@ -6,7 +6,7 @@ // // Expected: main() folds to word literal 55 (fib(10)). -function fib(comptime n : integer) -> comptime integer { +function fib(comptime n: integer) returns (comptime) { if (integerLt(n, 2)) { return n; } else { @@ -18,9 +18,9 @@ function fib(comptime n : integer) -> comptime integer { } contract IntegerLit { - function main() -> word { - let x : comptime integer = 10; - let res : comptime word = wordFromInteger(fib(x)); + function main() returns (word) { + let x : comptime = 10; + let res : comptime = wordFromInteger(fib(x)); return res; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.sol index f88edeaa..5231ac7b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/match_labels.sol @@ -3,21 +3,27 @@ Covers: keccakLit of a literal, keccakLit of a concatenation, wildcard. */ -import std.{*}; +import * from std; contract MatchLabels { - function dispatch(selector : word) -> word { - match selector { - | comptime keccakLit("transfer(address,uint256)") => return 1; - | comptime keccakLit("balanceOf" + "(" + "address" + ")") => return 2; - | _ => return 0; - } + function dispatch(selector: word) returns (word) { + match (selector) { +case comptime keccakLit("transfer(address,uint256)") { +return 1; +} +case comptime keccakLit("balanceOf" + "(" + "address" + ")") { +return 2; +} +default { +return 0; +} +} } - function main() -> word { - let t : comptime word = keccakLit("transfer(address,uint256)"); - let b : comptime word = keccakLit("balanceOf(address)"); + function main() returns (word) { + let t : comptime = keccakLit("transfer(address,uint256)"); + let b : comptime = keccakLit("balanceOf(address)"); return dispatch(t) + dispatch(b) + dispatch(0); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.sol index aaab6c37..7aba662e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-concat-mem.sol @@ -11,19 +11,19 @@ // d — A2: a `string`-typed let, then convert (dead-let substitution) import std; -import std.{*}; +import * from std; contract StringConcat { - function viaLet() -> memory(string) { + function viaLet() returns (memory) { let s : string = "Hello, " + "world!"; return Str.fromString(s); } - public function main() -> word { - let a : memory(string) = Str.fromString("Hello, " + "world!"); - let b : memory(string) = concatLit("Hello, ", "world!"); - let c : memory(string) = concatLit(concatLit("Hello", ", "), "world!"); - let d : memory(string) = viaLet(); + function main() public returns (word) { + let a : memory = Str.fromString("Hello, " + "world!"); + let b : memory = concatLit("Hello, ", "world!"); + let c : memory = concatLit(concatLit("Hello", ", "), "world!"); + let d : memory = viaLet(); return strlen(a) + strlen(b) + strlen(c) + strlen(d); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.sol index 777838c2..a4aefe18 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-dedup.sol @@ -3,13 +3,13 @@ // generated hull must contain exactly two __strlit_* allocators. import std; -import std.{*}; +import * from std; contract StringDedup { - public function main() -> word { - let x : memory(string) = "alpha"; - let y : memory(string) = "beta"; - let z : memory(string) = "alpha"; + function main() public returns (word) { + let x : memory = "alpha"; + let y : memory = "beta"; + let z : memory = "alpha"; return strlen(x) + strlen(y) + strlen(z); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol index 5d950e41..6dfd3caf 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol @@ -4,7 +4,7 @@ pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract StringLitKeccak { - public function main() -> word { + function main() public returns (word) { // keccakLit folds to a 256-bit word (EVM/Yul semantics) return std.keccakLit("abc"); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.sol index 06a1a8e1..88a72daa 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-len.sol @@ -4,7 +4,7 @@ pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract StringLitLen { - public function main() -> word { + function main() public returns (word) { // strlenLit folds to a word return std.strlenLit("hello"); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.sol index 73a2c89c..c7c730ed 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-mem.sol @@ -5,10 +5,10 @@ // Expected: compiles; main() returns a memory(string) for "abcd". import std; -import std.{*}; +import * from std; contract StringLitMem { - public function main() -> memory(string) { + function main() public returns (memory) { return "abcd"; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.sol index 95dad668..1639eec7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-ops.sol @@ -1,5 +1,5 @@ import std; -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -7,9 +7,9 @@ pragma no-bounded-variable-condition ; // These functions are intended to be folded by MastEval at compile time. contract StringLitOps { - public function main() -> () { + function main() public { // concatLit folds to a string literal, enabling revertLit("...") lowering - let s : comptime string = concatLit("ab", "cd"); + let s : comptime = concatLit("ab", "cd"); std.revertLit(s); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.sol index ff64932d..943ffa0a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-param-erasure.sol @@ -13,24 +13,26 @@ // main returns strlen("abcd") + strlen("abcd") = 8. import std; -import std.{*}; +import * from std; -data Wrapped = Wrapped(memory(string)); +enum Wrapped { Wrapped(memory) } -instance Wrapped : Str { - function fromString(s: string) -> Wrapped { +impl Str { + function fromString(s: string) returns (Wrapped) { return Wrapped(Str.fromString(s)); } } -function unwrap(w: Wrapped) -> memory(string) { - match w { - | Wrapped(m) => return m; - } +function unwrap(w: Wrapped) returns (memory) { + match (w) { +case Wrapped(m) { +return m; +} +} } contract StringParamErasure { - function main() -> word { + function main() returns (word) { let direct : Wrapped = "abcd"; let folded : Wrapped = concatLit("ab", "cd"); return strlen(unwrap(direct)) + strlen(unwrap(folded)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.sol index a1747cf1..0b8c0ac3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-user-instance.sol @@ -9,24 +9,26 @@ // comptime: main returns strlen("abcd") = 4. import std; -import std.{*}; +import * from std; -data Tag = Tag(word); +enum Tag { Tag(word) } -instance Tag : Str { - function fromString(s: string) -> Tag { +impl Str { + function fromString(s: string) returns (Tag) { return Tag(strlenLit(s)); } } -function tagLength(t: Tag) -> word { - match t { - | Tag(n) => return n; - } +function tagLength(t: Tag) returns (word) { + match (t) { +case Tag(n) { +return n; +} +} } contract StringUserInstance { - function main() -> word { + function main() returns (word) { let t : Tag = "abcd"; return tagLength(t); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.sol index 6eed609f..56e1a256 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/uint256-lit.sol @@ -1,10 +1,10 @@ // Bare integer literals at uint256-typed sites use `instance uint256 : Int`. // The instance's fromInteger wraps `wordFromInteger`, so an out-of-range // literal is truncated mod 2^256, matching the `word` site behaviour. -import std.{*}; +import * from std; contract Uint256Lit { - function main() -> word { + function main() returns (word) { let a : uint256 = 3; // 2^256 + 5 must truncate to 5. let b : uint256 = 0x10000000000000000000000000000000000000000000000000000000000000005; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.sol index 88e8229d..e0962961 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/Revert.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -function my_revert() -> word { +function my_revert() returns (word) { revertLit("regression"); return 0; } @@ -9,11 +9,11 @@ function my_revert() -> word { contract Foo { constructor() {} - public function noAnswer() -> uint256 { + function noAnswer() public returns (uint256) { return uint256(my_revert()); } - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.sol index f7449701..fd7b92aa 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_address_array.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // calldata(array(address)) — a dynamic array of a STATIC value type. Unlike // bytes[] (dynamic elements, offset table), address is static, so elements sit @@ -12,12 +12,12 @@ contract AddressArr { constructor() {} // The i-th address. - public function at(items : calldata(array(address)), i : uint256) -> address { + function at(items: calldata>, i: uint256) public returns (address) { return items[i]; } // Number of elements. - public function count(items : calldata(array(address))) -> uint256 { + function count(items: calldata>) public returns (uint256) { return items.length(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol index c6a790f6..32916355 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // ABI-decoding a dynamic array whose element is a sum-typed ADT. // @@ -10,18 +10,18 @@ import std.ABIGeneric.{*}; // wire element is therefore two words — a tag word then the payload — which the // word-per-slot memory(DynArray(...)) representation cannot hold. The array is // instead decoded lazily from calldata: the parameter becomes a -// `calldata(array(Operation))` handle to the length word, and elements are +// `calldata>` handle to the length word, and elements are // decoded on demand. Indexing uses the ordinary `ops[i]` sugar (calldata-array -// RValueIdxAccess) and `ops.length()` uses the Length-class UFCS — the same +// RValueIdxAccess) and `ops.length()` uses the Length-trait UFCS — the same // surface syntax as storage arrays. `ops` is a parameter, so this relies on // value-receiver UFCS (NameResolution), not just the field-receiver form. -data Operation = Approve(uint256) | Reject(uint256); +enum Operation { Approve(uint256), Reject(uint256) } contract Batch { constructor() {} // Number of operations in the array. - public function count(ops : calldata(array(Operation))) -> uint256 { + function count(ops: calldata>) public returns (uint256) { return ops.length(); } @@ -29,7 +29,7 @@ contract Batch { // 32 for Reject. Deliberately not 0/1 — those coincide with the on-wire sum // tag (inl=0, inr=1), so non-trivial values prove the match actually // discriminates the constructor rather than echoing the raw tag word. - public function tagOf(ops : calldata(array(Operation)), i : uint256) -> uint256 { + function tagOf(ops: calldata>, i: uint256) public returns (uint256) { let op : Operation = ops[i]; match op { | Operation.Approve(_) => return uint256(16); From 2908962d1c68a4422a62a6e1100bbdb74620ee85 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 072/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../test/examples/dispatch/abi_array_sum.sol | 26 +++-- .../test/examples/dispatch/abi_batch_adt.sol | 72 ++++++++------ .../examples/dispatch/abi_bytes_array.sol | 12 +-- .../ok/test/examples/dispatch/abi_dyn_sum.sol | 40 ++++---- .../examples/dispatch/abi_dyn_sum_return.sol | 30 +++--- .../test/examples/dispatch/abi_encode_adt.sol | 28 +++--- .../examples/dispatch/abi_encode_types.sol | 22 ++--- .../examples/dispatch/abi_sum_roundtrip.sol | 20 ++-- .../ok/test/examples/dispatch/array_copy.sol | 24 ++--- .../test/examples/dispatch/array_nested.sol | 30 +++--- .../ok/test/examples/dispatch/array_ops.sol | 16 ++-- .../test/examples/dispatch/array_string.sol | 22 ++--- .../ok/test/examples/dispatch/arraylit.sol | 34 +++---- .../dispatch/asm_break_continue_leave.sol | 8 +- .../ok/test/examples/dispatch/assembly.sol | 6 +- .../ok/test/examples/dispatch/basic.sol | 90 +++++++++--------- .../ok/test/examples/dispatch/concat.sol | 22 ++--- .../ok/test/examples/dispatch/counter.sol | 6 +- .../ok/test/examples/dispatch/deposit.sol | 28 +++--- .../dispatch/derive_contract_local.sol | 94 ++++++++++++------- .../ok/test/examples/dispatch/derive_ord.sol | 94 ++++++++++++------- .../ok/test/examples/dispatch/ecrecover.sol | 10 +- .../ok/test/examples/dispatch/eip712.sol | 24 ++--- .../ok/test/examples/dispatch/empty.sol | 4 +- .../dispatch/empty_no_constructor.sol | 4 +- .../ok/test/examples/dispatch/fallback.sol | 8 +- .../ok/test/examples/dispatch/forloops.sol | 22 ++--- .../examples/dispatch/generic_product.sol | 46 +++++---- .../ok/test/examples/dispatch/generic_sum.sol | 58 +++++++----- 29 files changed, 502 insertions(+), 398 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol index 32916355..49cdd1a8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_array_sum.sol @@ -31,18 +31,26 @@ contract Batch { // discriminates the constructor rather than echoing the raw tag word. function tagOf(ops: calldata>, i: uint256) public returns (uint256) { let op : Operation = ops[i]; - match op { - | Operation.Approve(_) => return uint256(16); - | Operation.Reject(_) => return uint256(32); - } + match (op) { +case Operation.Approve(_) { +return uint256(16); +} +case Operation.Reject(_) { +return uint256(32); +} +} } // Payload (the uint256) of element i, regardless of constructor. - public function amountOf(ops : calldata(array(Operation)), i : uint256) -> uint256 { + function amountOf(ops: calldata>, i: uint256) public returns (uint256) { let op : Operation = ops[i]; - match op { - | Operation.Approve(v) => return v; - | Operation.Reject(v) => return v; - } + match (op) { +case Operation.Approve(v) { +return v; +} +case Operation.Reject(v) { +return v; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.sol index 74390c27..d704cb67 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_batch_adt.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Complex nested-ADT ABI decode over a calldata dynamic array. The element is a // three-level algebraic type built from sums *and* products: @@ -27,24 +27,32 @@ import std.ABIGeneric.{*}; // real calldata) needs the exact solcore-generated selector for the nested-ADT // signature, which has to be captured from a local sol-core run. -data Operation = AddSigner(address) | RemoveSigner(address); -data Signature = ECDSA(bytes32, bytes32) | Contract(address); -data Batch = Queue(Operation, Signature) | Execute(uint256, memory(bytes)); +enum Operation { AddSigner(address), RemoveSigner(address) } +enum Signature { ECDSA(bytes32, bytes32), Contract(address) } +enum Batch { Queue(Operation, Signature), Execute(uint256, memory) } // Address added by an AddSigner op (address(0) for a RemoveSigner). -function addedSigner(op : Operation) -> address { - match op { - | Operation.AddSigner(a) => return a; - | Operation.RemoveSigner(_) => return address(0); - } +function addedSigner(op: Operation) returns (address) { + match (op) { +case Operation.AddSigner(a) { +return a; +} +case Operation.RemoveSigner(_) { +return address(0); +} +} } // Verifying contract address of a Contract signature (address(0) for ECDSA). -function contractVerifier(sig : Signature) -> address { - match sig { - | Signature.Contract(a) => return a; - | Signature.ECDSA(_, _) => return address(0); - } +function contractVerifier(sig: Signature) returns (address) { + match (sig) { +case Signature.Contract(a) { +return a; +} +case Signature.ECDSA(_, _) { +return address(0); +} +} } contract BatchDecoder { @@ -52,22 +60,30 @@ contract BatchDecoder { // From a Queue(AddSigner(a), Contract(c)) element, return (a, c): the signer // being added and the contract that verifies the queued action. - public function queueSigner(items : calldata(array(Batch)), i : uint256) -> (address, address) { + function queueSigner(items: calldata>, i: uint256) public returns (address, address) { let b : Batch = items[i]; - match b { - | Batch.Queue(op, sig) => return (addedSigner(op), contractVerifier(sig)); - | Batch.Execute(_, _) => return (address(0), address(0)); - } + match (b) { +case Batch.Queue(op, sig) { +return (addedSigner(op), contractVerifier(sig)); +} +case Batch.Execute(_, _) { +return (address(0), address(0)); +} +} } // The payload bytes carried by an Execute element. - public function execPayload(items : calldata(array(Batch)), i : uint256) -> memory(bytes) { + function execPayload(items: calldata>, i: uint256) public returns (memory) { let b : Batch = items[i]; - let out : memory(bytes); - match b { - | Batch.Execute(_, payload) => out = payload; - | Batch.Queue(_, _) => revertEmpty(); - } + let out : memory; + match (b) { +case Batch.Execute(_, payload) { +out = payload; +} +case Batch.Queue(_, _) { +revertEmpty(); +} +} return out; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.sol index 694c8f75..e84854d1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_bytes_array.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // calldata(array(bytes)) — a dynamic array whose element is itself dynamic, the // canonical Solidity `bytes[]`. After the length word the region is a table of @@ -14,12 +14,12 @@ contract BytesArray { constructor() {} // The i-th bytes element. - public function at(items : calldata(array(memory(bytes))), i : uint256) -> memory(bytes) { + function at(items: calldata>>, i: uint256) public returns (memory) { return items[i]; } // Number of elements. - public function count(items : calldata(array(memory(bytes)))) -> uint256 { + function count(items: calldata>>) public returns (uint256) { return items.length(); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.sol index d1c0f66b..3c2c7fce 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Minimal dynamic sum in a calldata array — like abi_batch_adt but with NO // nested ADTs: the constructors carry primitive / bytes fields directly. This @@ -10,28 +10,36 @@ import std.ABIGeneric.{*}; // which abi_batch_adt also has and this test does not). // // DynSum : sum(uint256, bytes) -- dynamic (Blob carries memory(bytes)) -data DynSum = Small(uint256) | Blob(memory(bytes)); +enum DynSum { Small(uint256), Blob(memory) } contract DynSumArr { constructor() {} // The uint256 in a Small element (0 for a Blob). - public function smallOf(items : calldata(array(DynSum)), i : uint256) -> uint256 { + function smallOf(items: calldata>, i: uint256) public returns (uint256) { let d : DynSum = items[i]; - match d { - | DynSum.Small(x) => return x; - | DynSum.Blob(_) => return uint256(0); - } + match (d) { +case DynSum.Small(x) { +return x; +} +case DynSum.Blob(_) { +return uint256(0); +} +} } // The bytes payload of a Blob element. - public function blobOf(items : calldata(array(DynSum)), i : uint256) -> memory(bytes) { + function blobOf(items: calldata>, i: uint256) public returns (memory) { let d : DynSum = items[i]; - let out : memory(bytes); - match d { - | DynSum.Blob(b) => out = b; - | DynSum.Small(_) => revertEmpty(); - } + let out : memory; + match (d) { +case DynSum.Blob(b) { +out = b; +} +case DynSum.Small(_) { +revertEmpty(); +} +} return out; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.sol index 1e7c9531..09c72fcc 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_dyn_sum_return.sol @@ -1,12 +1,12 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Return a *dynamic sum by value* from a dispatched function — the case the // generic ABI encoder used to get wrong (it wrote only the top-level tag word, // collapsing the whole value to a single 0x00…0 head). The companion -// `abi_dyn_sum.solc` deliberately avoids this by returning `memory(bytes)` / +// `abi_dyn_sum.sol` deliberately avoids this by returning `memory(bytes)` / // individual words; here we exercise the fixed `sum(f,g):ABIEncode` head-offset // path head-on. // @@ -19,9 +19,9 @@ import std.ABIGeneric.{*}; // word, so a deeply nested variant encodes as nested offsets, not flat tags. // A static sum stays inline as [tag][branch] with no leading offset — its wire // form is unchanged by the fix. -data D2 = L(uint256) | R(memory(bytes)); -data D3 = X(uint256) | Y(uint256) | Z(memory(bytes)); -data S2 = P(uint256) | Q(uint256); +enum D2 { L(uint256), R(memory) } +enum D3 { X(uint256), Y(uint256), Z(memory) } +enum S2 { P(uint256), Q(uint256) } contract DynSumRet { constructor() {} @@ -29,39 +29,39 @@ contract DynSumRet { // ── shallow dynamic sum ──────────────────────────────────────────────── // inl branch (static uint256 payload) of a dynamic sum: still takes the // dynamic encode path (offset word + inline [tag][value] in the tail). - public function makeL(n : uint256) -> D2 { + function makeL(n: uint256) public returns (D2) { return D2.L(n); } // inr branch carrying a dynamic bytes payload: [off][1][off][len][data]. - public function makeR(b : memory(bytes)) -> D2 { + function makeR(b: memory) public returns (D2) { return D2.R(b); } // ── deeply right-nested dynamic sum ──────────────────────────────────── // outer inl: [off][0][value] - public function makeX(n : uint256) -> D3 { + function makeX(n: uint256) public returns (D3) { return D3.X(n); } // inr(inl …): two dynamic-sum levels, so two nested offsets: [off][1][off][0][value] - public function makeY(n : uint256) -> D3 { + function makeY(n: uint256) public returns (D3) { return D3.Y(n); } // inr(inr bytes): nested offsets down to the bytes leaf: // [off][1][off][1][off][len][data] - public function makeZ(b : memory(bytes)) -> D3 { + function makeZ(b: memory) public returns (D3) { return D3.Z(b); } // ── static sum control ───────────────────────────────────────────────── // Byte-identical to the pre-fix output: inline [tag][value], no offset word. - public function makeP(n : uint256) -> S2 { + function makeP(n: uint256) public returns (S2) { return S2.P(n); } - public function makeQ(n : uint256) -> S2 { + function makeQ(n: uint256) public returns (S2) { return S2.Q(n); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.sol index 51621d85..eed61df3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_adt.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -9,7 +9,7 @@ pragma no-bounded-variable-condition ; // Direct tests for `abi_encode` over user-defined algebraic data types (ADTs). // // An ADT reaches `abi_encode` through its auto-derived `Generic` representation -// and the ABIGeneric bridges (std/ABIGeneric.solc): a product constructor +// and the ABIGeneric bridges (std/ABIGeneric.sol): a product constructor // represents as the primitive tuple of its fields, and a sum represents as the // binary `sum(f, g)` type (inl = first constructor, inr = second). Each method // encodes an ADT value and returns the `memory(bytes)` result, which the @@ -33,41 +33,41 @@ pragma no-bounded-variable-condition ; // tail — even the static (Empty) branch keeps that offset wrapper. // static product -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } // static sum -data Choice = First(uint256) | Second(uint256); +enum Choice { First(uint256), Second(uint256) } // dynamic sum (the Text branch carries a dynamic string) -data StrBox = Empty(uint256) | Text(memory(string)); +enum StrBox { Empty(uint256), Text(memory) } contract AbiEncodeAdt { constructor() {} // Static product: encodes as the tuple (a, b) — two inline head words. - public function encPoint(a : uint256, b : uint256) -> memory(bytes) { + function encPoint(a: uint256, b: uint256) public returns (memory) { return abi_encode(Point(a, b)); } // Static sum, left constructor: [tag = 0][x]. - public function encFirst(x : uint256) -> memory(bytes) { + function encFirst(x: uint256) public returns (memory) { return abi_encode(Choice.First(x)); } // Static sum, right constructor: [tag = 1][x]. - public function encSecond(x : uint256) -> memory(bytes) { + function encSecond(x: uint256) public returns (memory) { return abi_encode(Choice.Second(x)); } // Dynamic sum, static branch: still offset-wrapped — [0x20] -> [tag = 0][n]. - public function encEmpty(n : uint256) -> memory(bytes) { + function encEmpty(n: uint256) public returns (memory) { return abi_encode(StrBox.Empty(n)); } // Dynamic sum, dynamic branch: [0x20] -> [tag = 1][branch offset][len][data]. - public function encText() -> memory(bytes) { + function encText() public returns (memory) { let raw : string = "abc"; - let s : memory(string) = Str.fromString(raw); + let s : memory = Str.fromString(raw); return abi_encode(StrBox.Text(s)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.sol index 0628338e..df93783e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_encode_types.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -// Direct tests for the top-level `abi_encode` function (std.solc) across both +// Direct tests for the top-level `abi_encode` function (std.sol) across both // static and dynamic types. // // Each method encodes a value with `abi_encode` and returns the resulting @@ -26,37 +26,37 @@ contract AbiEncodeTypes { // --- static --- // uint256 is written directly into the head as one word. - public function encUint(x : uint256) -> memory(bytes) { + function encUint(x: uint256) public returns (memory) { return abi_encode(x); } // bool encodes as a single 0/1 word. - public function encBool(x : bool) -> memory(bytes) { + function encBool(x: bool) public returns (memory) { return abi_encode(x); } // address is left-padded into a single word. - public function encAddr(x : address) -> memory(bytes) { + function encAddr(x: address) public returns (memory) { return abi_encode(x); } // A fully static tuple has both words in the head, with no offset. - public function encPair(a : uint256, b : uint256) -> memory(bytes) { + function encPair(a: uint256, b: uint256) public returns (memory) { return abi_encode((a, b)); } // --- dynamic --- // A string gets a head offset word pointing at a `[len][data]` tail. - public function encStr() -> memory(bytes) { + function encStr() public returns (memory) { let raw : string = "abc"; - let s : memory(string) = Str.fromString(raw); + let s : memory = Str.fromString(raw); return abi_encode(s); } // A dynamic array gets a head offset word pointing at a `[len][elems]` tail. - public function encArr() -> memory(bytes) { - let a : memory(DynArray(uint256)) = [11, 22, 33]; + function encArr() public returns (memory) { + let a : memory> = [11, 22, 33]; return abi_encode(a); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.sol index dc13caf6..074225be 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/abi_sum_roundtrip.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Roundtrip tests for sum ABI coding: `roundtrip(x) -> x` makes the dispatcher // DECODE the argument from calldata and then ENCODE it straight back into the @@ -16,26 +16,26 @@ import std.ABIGeneric.{*}; // The dynamic direction is what the sum(f,g):ABIEncode fix restores: before it, // encoding a decoded dynamic sum dropped everything but the tag, so the return // bytes could not match the input. -data D2 = L(uint256) | R(memory(bytes)); // dynamic (shallow) -data D3 = X(uint256) | Y(uint256) | Z(memory(bytes)); // dynamic (deeply nested) -data S2 = P(uint256) | Q(uint256); // static +enum D2 { L(uint256), R(memory) } // dynamic (shallow) +enum D3 { X(uint256), Y(uint256), Z(memory) } // dynamic (deeply nested) +enum S2 { P(uint256), Q(uint256) } // static contract SumRoundtrip { constructor() {} // dynamic, shallow: decode a sum(uint256, bytes) then re-encode it. - public function rtD2(x : D2) -> D2 { + function rtD2(x: D2) public returns (D2) { return x; } // dynamic, deeply right-nested: each nested dynamic level round-trips its own // offset word. - public function rtD3(x : D3) -> D3 { + function rtD3(x: D3) public returns (D3) { return x; } // static control: inline layout must round-trip unchanged. - public function rtS2(x : S2) -> S2 { + function rtS2(x: S2) public returns (S2) { return x; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.sol index 6d359c79..9b275758 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_copy.sol @@ -1,46 +1,46 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Whole-array assignment `a = b` follows Solidity: it is a deep copy, not an // alias; assigning an array to itself is a no-op; and a copy that shrinks the // destination clears the slots it abandons, so regrowing yields zeros. contract ArrayCopy { - a : array(uint256); - b : array(uint256); + a : array; + b : array; constructor() {} - public function pushA(v : uint256) -> () { + function pushA(v: uint256) public { ArrayPush.push(a, v); } - public function pushB(v : uint256) -> () { + function pushB(v: uint256) public { ArrayPush.push(b, v); } // a = b - public function copyBintoA() -> () { + function copyBintoA() public { a = b; } // a = a (must be a no-op, not a self-clobbering copy) - public function copyAintoA() -> () { + function copyAintoA() public { a = a; } - public function setB(i : uint256, v : uint256) -> () { + function setB(i: uint256, v: uint256) public { b[i] = v; } - public function growA(n : uint256) -> () { + function growA(n: uint256) public { Array.setLength(a, n); } - public function lenA() -> uint256 { + function lenA() public returns (uint256) { return Length.length(a); } - public function getA(i : uint256) -> uint256 { + function getA(i: uint256) public returns (uint256) { return a[i]; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.sol index 81662976..3fe2d26b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_nested.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Nested storage arrays and aliasing, on the EVM. // @@ -10,48 +10,48 @@ import std.dispatch.{*}; // Binding an array field to a local is an alias (Solidity's `T[] storage p`), not // a copy: mutating through the local must be visible through the field. contract NestedArray { - grid : array(array(uint256)); - flat : array(uint256); + grid : array>; + flat : array; constructor() {} - public function growOuter(n : uint256) -> () { + function growOuter(n: uint256) public { Array.setLength(grid, n); } // grid[i].push(v) -- the inner handle comes straight out of the index - public function pushInner(i : uint256, v : uint256) -> () { + function pushInner(i: uint256, v: uint256) public { ArrayPush.push(grid[i], v); } - public function innerLen(i : uint256) -> uint256 { + function innerLen(i: uint256) public returns (uint256) { return Length.length(grid[i]); } - public function get2(i : uint256, j : uint256) -> uint256 { + function get2(i: uint256, j: uint256) public returns (uint256) { return grid[i][j]; } - public function set2(i : uint256, j : uint256, v : uint256) -> () { + function set2(i: uint256, j: uint256, v: uint256) public { grid[i][j] = v; } // Mutate `flat` through a local alias; the field must observe it. - public function aliasPush(v : uint256) -> () { - let p : storage(array(uint256)) = flat; + function aliasPush(v: uint256) public { + let p : storage> = flat; ArrayPush.push(p, v); } - public function aliasSet(i : uint256, v : uint256) -> () { - let p : storage(array(uint256)) = flat; + function aliasSet(i: uint256, v: uint256) public { + let p : storage> = flat; p[i] = v; } - public function flatLen() -> uint256 { + function flatLen() public returns (uint256) { return Length.length(flat); } - public function getFlat(i : uint256) -> uint256 { + function getFlat(i: uint256) public returns (uint256) { return flat[i]; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.sol index 5a162dbc..29347bfd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_ops.sol @@ -1,33 +1,33 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage-array primitives end to end: push / pop / length / indexed read, // the two revert paths (index out of range, pop on empty), and the guarantee // that abandoned slots are zeroed -- so regrowing an array never resurrects the // values that `pop` or a shrinking `setLength` dropped. contract ArrayOps { - xs : array(uint256); + xs : array; constructor() {} // NOTE: not named `add` -- that collides with the Yul builtin of the same name. - public function pushVal(v : uint256) -> () { + function pushVal(v: uint256) public { ArrayPush.push(xs, v); } - public function popArr() -> () { + function popArr() public { Array.pop(xs); } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(xs); } - public function get(i : uint256) -> uint256 { + function get(i: uint256) public returns (uint256) { return xs[i]; } - public function grow(n : uint256) -> () { + function grow(n: uint256) public { Array.setLength(xs, n); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.sol index 6bdac8f3..d66564db 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/array_string.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage arrays of a *dynamic* element type. `push` stores a `memory(string)` // through `storage(string):CanStore(memory(string))`, `arr[i]` reads one back, @@ -8,37 +8,37 @@ import std.dispatch.{*}; // Both the short (<32 bytes, inline) and long (>=32 bytes, keccak tail) string // encodings are exercised. contract ArrayString { - names : array(string); - backup : array(string); + names : array; + backup : array; constructor() {} - public function pushName(s : memory(string)) -> () { + function pushName(s: memory) public { ArrayPush.push(names, s); } - public function setName(i : uint256, s : memory(string)) -> () { + function setName(i: uint256, s: memory) public { names[i] = s; } - public function getName(i : uint256) -> memory(string) { + function getName(i: uint256) public returns (memory) { return names[i]; } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(names); } // backup = names - public function saveBackup() -> () { + function saveBackup() public { backup = names; } - public function getBackup(i : uint256) -> memory(string) { + function getBackup(i: uint256) public returns (memory) { return backup[i]; } - public function lenBackup() -> uint256 { + function lenBackup() public returns (uint256) { return Length.length(backup); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.sol index db34347f..86c450e3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/arraylit.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Array literals, end to end. // @@ -7,7 +7,7 @@ import std.dispatch.{*}; // Solidity's memory -> storage copy: it resizes the field and clears the // abandoned tail, so shrinking must not leave old elements reachable. contract ArrayLit { - xs : array(uint256); + xs : array; constructor() {} @@ -15,13 +15,13 @@ contract ArrayLit { // Reads back an element of a memory literal. Element 0 must be the first // element, not the length word stored ahead of it. - public function memAt(i : uint256) -> uint256 { - let m : memory(DynArray(uint256)) = [11, 22, 33]; + function memAt(i: uint256) public returns (uint256) { + let m : memory> = [11, 22, 33]; return m[i]; } - public function memSum() -> uint256 { - let m : memory(DynArray(uint256)) = [1, 2, 3, 4]; + function memSum() public returns (uint256) { + let m : memory> = [1, 2, 3, 4]; let acc : uint256 = uint256(0); let i : uint256; for (i = uint256(0); i < uint256(4); i = i + uint256(1)) { @@ -31,41 +31,41 @@ contract ArrayLit { } // Nested literal: the element type is itself a memory array. - public function nested() -> uint256 { - let g : memory(DynArray(memory(DynArray(uint256)))) = [[1, 2], [3, 4]]; - let row : memory(DynArray(uint256)) = g[uint256(1)]; + function nested() public returns (uint256) { + let g : memory>>> = [[1, 2], [3, 4]]; + let row : memory> = g[uint256(1)]; return row[uint256(0)]; } // --- storage literals --- - public function setThree() -> () { + function setThree() public { xs = [10, 20, 30]; } - public function setFive() -> () { + function setFive() public { xs = [1, 2, 3, 4, 5]; } - public function setTwo() -> () { + function setTwo() public { xs = [7, 8]; } - public function clear() -> () { + function clear() public { xs = []; } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(xs); } - public function get(i : uint256) -> uint256 { + function get(i: uint256) public returns (uint256) { return xs[i]; } // Grow the array back without writing elements. Anything the shrink abandoned // must read as zero, not as the old value. - public function grow(n : uint256) -> () { + function grow(n: uint256) public { Array.setLength(xs, n); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.sol index 8b689c2d..6690d4c3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/asm_break_continue_leave.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // End-to-end (runs on evmone via the testrunner) check that Yul `break`, // `continue` and `leave` in inline assembly don't just parse, but actually @@ -12,7 +12,7 @@ contract C { // 2 + 3 + 4 + 5 = 14 // A miscompiled `continue` would also add 0 and 1 (=> 15); a broken `break` // would keep going and add 6..9 as well. - public function loopSum() -> uint256 { + function loopSum() public returns (uint256) { let result : word; assembly { result := 0 @@ -34,7 +34,7 @@ contract C { // clamp(2) = 102, clamp(9) = 3 => 102 + 3 = 105 // A broken `leave` would fall through and add 100 to the x > 3 branch too // (clamp(9) => 103 => total 205). - public function clampSum() -> uint256 { + function clampSum() public returns (uint256) { let result : word; assembly { function clamp(x) -> y { diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.sol index a39e7cdd..dfa492ca 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/assembly.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor() {} @@ -7,7 +7,7 @@ contract C { // Exercises a Yul block that declares an uninitialized `let y`, assigns the // boolean literal `true` to it, and writes it back to the surrounding // `word` local `x`. `true` is the word `1`, so this returns uint256(1). - public function asmBool() -> uint256 { + function asmBool() public returns (uint256) { let x : word; assembly { let y diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol index ac747855..4f4832c4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol @@ -1,180 +1,184 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{address as address_}; +import * from std; +import * from std.dispatch; +import {address as address_} from std.opcodes; -function self() -> address { +function self() returns (address) { return address(address_()); } contract C { constructor() {} - public function nothing() -> () {} + function nothing() public {} // Re-enters this very contract via raw_call(address(this), ...). The payload // is the 4-byte selector of an existing entry point (something(), 0xa7a0d537), // built by left-aligning it in a bytes32 and truncating to 4 bytes. The inner // call succeeds, so raw_call reports ok == true and returns its returndata // (the abi-encoded uint256(1)). - public function callSelf() -> (bool, memory(bytes)) { + function callSelf() public returns (bool, memory) { let sel: bytes32 = bytes32(0xa7a0d53700000000000000000000000000000000000000000000000000000000); let payload = truncate(to_bytes(sel), 4); - match raw_call(self(), uint256(0), payload) { - | (ok, ret) => return (ok, ret); - } + match (raw_call(self(), uint256(0), payload)) { +case (ok, ret) { +return (ok, ret); +} +} } // Same shape, but the selector (0xdeadc0de) matches no entry point, so dispatch // reverts (there is no fallback). raw_call swallows the inner revert and reports // ok == false; this outer call itself still succeeds and returns the revert // returndata (the 4-byte NoFallback error selector). - public function callSelfInvalid() -> (bool, memory(bytes)) { + function callSelfInvalid() public returns (bool, memory) { let sel: bytes32 = bytes32(0xdeadc0de00000000000000000000000000000000000000000000000000000000); let payload = truncate(to_bytes(sel), 4); - match raw_call(self(), uint256(0), payload) { - | (ok, ret) => return (ok, ret); - } + match (raw_call(self(), uint256(0), payload)) { +case (ok, ret) { +return (ok, ret); +} +} } - public function something() -> (uint256) { + function something() public returns (uint256) { return uint256(1); } - public function add2(x : uint256, y : uint256) -> uint256 { + function add2(x: uint256, y: uint256) public returns (uint256) { return Add.add(x,y); } - public function add3(x : uint256, y : uint256, z : uint256) -> uint256 { + function add3(x: uint256, y: uint256, z: uint256) public returns (uint256) { return Add.add(z, Add.add(x,y)); } - public function addmod3(x : uint256, y : uint256, k : uint256) -> uint256 { + function addmod3(x: uint256, y: uint256, k: uint256) public returns (uint256) { return addmod(x, y, k); } - public function mulmod3(x : uint256, y : uint256, k : uint256) -> uint256 { + function mulmod3(x: uint256, y: uint256, k: uint256) public returns (uint256) { return mulmod(x, y, k); } - // Bitwise / modulo via the syntactic sugar only (no explicit class calls): + // Bitwise / modulo via the syntactic sugar only (no explicit trait calls): // `^` -> BitXor.bxor, `|` -> BitOr.bor, `&` -> BitAnd.band, `%` -> Mod.mod. - public function bxor2(x : uint256, y : uint256) -> uint256 { + function bxor2(x: uint256, y: uint256) public returns (uint256) { return x ^ y; } - public function bor2(x : uint256, y : uint256) -> uint256 { + function bor2(x: uint256, y: uint256) public returns (uint256) { return x | y; } - public function band2(x : uint256, y : uint256) -> uint256 { + function band2(x: uint256, y: uint256) public returns (uint256) { return x & y; } // Unary bitwise NOT via the sugar only: `~` -> BitNot.bnot. - public function bnot1(x : uint256) -> uint256 { + function bnot1(x: uint256) public returns (uint256) { return ~x; } - public function mod2(x : uint256, y : uint256) -> uint256 { + function mod2(x: uint256, y: uint256) public returns (uint256) { return x % y; } // `*` -> Mul.mul, `/` -> Div.div (completing the binary-operator sugar // set alongside bxor2 / bor2 / band2 / mod2). - public function mul2(x : uint256, y : uint256) -> uint256 { + function mul2(x: uint256, y: uint256) public returns (uint256) { return x * y; } - public function div2(x : uint256, y : uint256) -> uint256 { + function div2(x: uint256, y: uint256) public returns (uint256) { return x / y; } // Compound assignment statement sugar: each `acc op= y` desugars to // `acc := acc op y`, so these must agree with the binary operators above. - public function pluseq(x : uint256, y : uint256) -> uint256 { + function pluseq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc += y; return acc; } - public function minuseq(x : uint256, y : uint256) -> uint256 { + function minuseq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc -= y; return acc; } - public function timeseq(x : uint256, y : uint256) -> uint256 { + function timeseq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc *= y; return acc; } - public function divideeq(x : uint256, y : uint256) -> uint256 { + function divideeq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc /= y; return acc; } - public function modeq(x : uint256, y : uint256) -> uint256 { + function modeq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc %= y; return acc; } - public function bxoreq(x : uint256, y : uint256) -> uint256 { + function bxoreq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc ^= y; return acc; } - public function bandeq(x : uint256, y : uint256) -> uint256 { + function bandeq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc &= y; return acc; } - public function boreq(x : uint256, y : uint256) -> uint256 { + function boreq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc |= y; return acc; } // In-place unary bitwise NOT: `acc ~=` desugars to `acc := ~acc`. - public function bnoteq(x : uint256) -> uint256 { + function bnoteq(x: uint256) public returns (uint256) { let acc : uint256 = x; acc ~=; return acc; } - public function id_bytes(b: memory(bytes)) -> memory(bytes) { + function id_bytes(b: memory) public returns (memory) { return b; } - public function id_string(b: memory(string)) -> memory(string) { + function id_string(b: memory) public returns (memory) { return b; } - public function id_bytes32(b: bytes32) -> bytes32 { + function id_bytes32(b: bytes32) public returns (bytes32) { return b; } - public function id_bytes4(b: bytes4) -> bytes4 { + function id_bytes4(b: bytes4) public returns (bytes4) { return b; } - public function id_address(a: address) -> address { + function id_address(a: address) public returns (address) { return a; } // Exercises bool:ABIDecode (argument) and bool:ABIEncode (return). - public function id_bool(b: bool) -> bool { + function id_bool(b: bool) public returns (bool) { return b; } - public function id_pair() -> (uint256, uint256) { + function id_pair() public returns (uint256, uint256) { return (uint256(7), uint256(11)); } - function hidden() -> (uint256) { + function hidden() returns (uint256) { return uint256(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.sol index 4d0b59bf..ce5ac428 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/concat.sol @@ -1,42 +1,42 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor() {} - public function concat_b32_b32(a: bytes32, b: bytes32) -> memory(bytes) { + function concat_b32_b32(a: bytes32, b: bytes32) public returns (memory) { return concat(a, b); } - public function concat_b32_bytes(a: bytes32, b: memory(bytes)) -> memory(bytes) { + function concat_b32_bytes(a: bytes32, b: memory) public returns (memory) { return concat(a, b); } - public function concat_bytes_bytes(a: memory(bytes), b: memory(bytes)) -> memory(bytes) { + function concat_bytes_bytes(a: memory, b: memory) public returns (memory) { return concat(a, b); } - public function to_bytes_b32(a: bytes32) -> memory(bytes) { + function to_bytes_b32(a: bytes32) public returns (memory) { return to_bytes(a); } - public function to_bytes_bytes(a: memory(bytes)) -> memory(bytes) { + function to_bytes_bytes(a: memory) public returns (memory) { return to_bytes(a); } - public function empty_area(n: uint256) -> memory(bytes) { + function empty_area(n: uint256) public returns (memory) { return to_bytes(empty(Typedef.rep(n))); } - public function concat_b32_empty(a: bytes32, n: uint256) -> memory(bytes) { + function concat_b32_empty(a: bytes32, n: uint256) public returns (memory) { return concat(a, empty(Typedef.rep(n))); } - public function concat_nested_b32(a: bytes32, b: bytes32, c: bytes32) -> memory(bytes) { + function concat_nested_b32(a: bytes32, b: bytes32, c: bytes32) public returns (memory) { return concat(a, concat(b, c)); } - public function concat_nested_empty(a: bytes32, n: uint256, c: bytes32) -> memory(bytes) { + function concat_nested_empty(a: bytes32, n: uint256, c: bytes32) public returns (memory) { return concat(a, concat(empty(Typedef.rep(n)), c)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.sol index 5b795699..699c8612 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/counter.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Counter { counter : uint256; @@ -7,7 +7,7 @@ contract Counter { counter = 41; } - public function test() -> uint256 { + function test() public returns (uint256) { counter = counter + 1; return counter; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.sol index 9656d84d..7df57487 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/deposit.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{callvalue}; +import * from std; +import * from std.dispatch; +import {callvalue} from std.opcodes; // TODO: Should use uint64. // Assumes 64-bit input. -function to_little_endian_64(v: uint256) -> memory(bytes) { +function to_little_endian_64(v: uint256) returns (memory) { let res: word = allocate_memory(32 + 8); let value: word = Typedef.rep(v); assembly { @@ -23,11 +23,11 @@ function to_little_endian_64(v: uint256) -> memory(bytes) { // No constants are supported yet, using this as a workaround. // Defining variables outside of contract/function is not supported. -function DEPOSIT_CONTRACT_TREE_DEPTH() -> uint256 { +function DEPOSIT_CONTRACT_TREE_DEPTH() returns (uint256) { return 32; } -function MAX_DEPOSIT_COUNT() -> uint256 { +function MAX_DEPOSIT_COUNT() returns (uint256) { // uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1; // TODO: Could use Bounded(uint32).maxVal() return 0xFFFFFFFF; @@ -36,8 +36,8 @@ function MAX_DEPOSIT_COUNT() -> uint256 { contract DepositContract { deposit_count : uint256; // TODO: use fixed-size arrays of DEPOSIT_CONTRACT_TREE_DEPTH() length - branch : array(bytes32); - zero_hashes : array(bytes32); + branch : array; + zero_hashes : array; constructor() { // Dynamic storage arrays start empty and indexed access is bounds-checked, @@ -55,11 +55,11 @@ contract DepositContract { } // TODO: this is for testing only - public function get_zero_hash(index: uint256) -> bytes32 { + function get_zero_hash(index: uint256) public returns (bytes32) { return zero_hashes[index]; } - public function get_deposit_root() -> bytes32 { + function get_deposit_root() public returns (bytes32) { let node: bytes32; let size = deposit_count; for (let height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH(); height += 1) { @@ -79,13 +79,13 @@ contract DepositContract { )); } - public function get_deposit_count() -> memory(bytes) { + function get_deposit_count() public returns (memory) { return to_little_endian_64(deposit_count); } // TODO: once string literals are properly supported, change errors to messages // matching the deposit contract, full 100% identical behaviour. - public payable function deposit(pubkey: memory(bytes), withdrawal_credentials: memory(bytes), signature: memory(bytes), deposit_data_root: bytes32) -> () { + function deposit(pubkey: memory, withdrawal_credentials: memory, signature: memory, deposit_data_root: bytes32) public payable { // Extended ABI length checks since dynamic types are used. require(MemorySize.len(pubkey) == 48, Error(0x9ca717ed)); // InvalidPubkeyLength() require(MemorySize.len(withdrawal_credentials) == 32, Error(0x3debbf1e)); // InvalidWithdrawalCredentialsLength() @@ -101,7 +101,7 @@ contract DepositContract { // <= type(uint64).max require(deposit_amount <= 0xffffffffffffffff, Error(0x2aa66734)); // DepositValueTooHigh() - let amount: memory(bytes) = to_little_endian_64(uint256(deposit_amount)); + let amount: memory = to_little_endian_64(uint256(deposit_amount)); // TODO: emit DepositEvent /* event DepositEvent( @@ -159,7 +159,7 @@ contract DepositContract { assert(false); } - public function supportsInterface(interfaceId: bytes4) -> bool { + function supportsInterface(interfaceId: bytes4) public returns (bool) { unimplemented(); return false; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.sol index c48fb312..6af4fa78 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_contract_local.sol @@ -4,65 +4,89 @@ // - Color (a contract-local enum) exercises the () and sum(f, g) instances; // - Point (a contract-local product) exercises the pair (f, g) instance. -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; contract DeriveContractLocal { #[derive(Eq, Ord)] - data Color = Red | Green | Blue; + enum Color { Red, Green, Blue } #[derive(Eq, Ord)] - data Point = Point(uint256, uint256); + enum Point { Point(uint256, uint256) } constructor() {} // enum equality (reaches the () and sum universe instances) - public function eqRedRed() -> uint256 { - match Eq.eq(Color.Red, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedRed() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function eqRedBlue() -> uint256 { - match Eq.eq(Color.Red, Color.Blue) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedBlue() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Blue)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // enum ordering follows declaration order: Red < Green < Blue - public function gtGreenRed() -> uint256 { - match Ord.gt(Color.Green, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtGreenRed() public returns (uint256) { + match (Ord.gt(Color.Green, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function gtRedGreen() -> uint256 { - match Ord.gt(Color.Red, Color.Green) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtRedGreen() public returns (uint256) { + match (Ord.gt(Color.Red, Color.Green)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product equality (reaches the pair universe instance) - public function eqPointSame() -> uint256 { - match Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2))) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqPointSame() public returns (uint256) { + match (Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product ordering is lexicographic: the second field breaks the tie - public function gtPointLex() -> uint256 { - match Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50))) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtPointLex() public returns (uint256) { + match (Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.sol index 6535e55e..dd801111 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/derive_ord.sol @@ -4,65 +4,89 @@ // - Color (an enum) exercises the unit () and sum(f, g) instances; // - Point (a product) exercises the pair (f, g) instance. -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq, Ord)] -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } #[derive(Eq, Ord)] -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } contract DeriveOrd { constructor() {} // enum equality (reaches the () and sum universe instances) - public function eqRedRed() -> uint256 { - match Eq.eq(Color.Red, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedRed() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function eqRedBlue() -> uint256 { - match Eq.eq(Color.Red, Color.Blue) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedBlue() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Blue)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // enum ordering follows declaration order: Red < Green < Blue - public function gtGreenRed() -> uint256 { - match Ord.gt(Color.Green, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtGreenRed() public returns (uint256) { + match (Ord.gt(Color.Green, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function gtRedGreen() -> uint256 { - match Ord.gt(Color.Red, Color.Green) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtRedGreen() public returns (uint256) { + match (Ord.gt(Color.Red, Color.Green)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product equality (reaches the pair universe instance) - public function eqPointSame() -> uint256 { - match Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2))) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqPointSame() public returns (uint256) { + match (Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product ordering is lexicographic: the second field breaks the tie - public function gtPointLex() -> uint256 { - match Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50))) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtPointLex() public returns (uint256) { + match (Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.sol index e66122a1..412fec69 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ecrecover.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract EcrecoverTest { - public function recover() -> address { + function recover() public returns (address) { let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(27); let r: bytes32 = bytes32(0xb3ba6dd3757d18f28736e84b1296af85362b7bdf4548710733c6325abf95311d); @@ -14,7 +14,7 @@ contract EcrecoverTest { // but recovers nothing, so it returns empty output and `res` stays 0. This // exercises the `ECRecoverFailed()` (0x4fbfae63) revert path. `v` and `s` // are kept well-formed so neither the malleability nor call-failed guards fire. - public function recoverFail() -> address { + function recoverFail() public returns (address) { let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(27); let r: bytes32 = bytes32(0x0); @@ -29,7 +29,7 @@ contract EcrecoverTest { // 0 and hit the `ECRecoverFailed()` (0x4fbfae63) revert path — without the // clear a stale non-zero word would be returned as a bogus address. `r` and // `s` are the well-formed values from `recover()` so only `v` is at fault. - public function recoverFailBadV() -> address { + function recoverFailBadV() public returns (address) { let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(1); let r: bytes32 = bytes32(0xb3ba6dd3757d18f28736e84b1296af85362b7bdf4548710733c6325abf95311d); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.sol index a292b5b9..0408655b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/eip712.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; -import std.eip712.{*}; +import * from std; +import * from std.dispatch; +import * from std.eip712; // Canonical EIP-712 example from the specification // (https://eips.ethereum.org/EIPS/eip-712): a `Mail` sent from one `Person` to @@ -22,7 +22,7 @@ import std.eip712.{*}; // with `keccak256_`, exactly as in the slices example. // hashStruct(Person) = keccak256(PERSON_TYPEHASH ‖ keccak256(name) ‖ wallet) -function hashPerson(nameHash: bytes32, wallet: address) -> bytes32 { +function hashPerson(nameHash: bytes32, wallet: address) returns (bytes32) { let typeHash = bytes32(keccakLit("Person(string name,address wallet)")); return keccak256_( concat(typeHash, concat(nameHash, bytes32(Typedef.rep(wallet)))) @@ -32,7 +32,7 @@ function hashPerson(nameHash: bytes32, wallet: address) -> bytes32 { // hashStruct(Mail) = keccak256(MAIL_TYPEHASH ‖ hashStruct(from) ‖ hashStruct(to) ‖ keccak256(contents)) // The Mail type hash embeds the referenced Person type per the EIP-712 rule for // nested structs (referenced types are appended, sorted by name). -function hashMail(fromHash: bytes32, toHash: bytes32, contentsHash: bytes32) -> bytes32 { +function hashMail(fromHash: bytes32, toHash: bytes32, contentsHash: bytes32) returns (bytes32) { let typeHash = bytes32( keccakLit("Mail(Person from,Person to,string contents)Person(string name,address wallet)") ); @@ -43,7 +43,7 @@ function hashMail(fromHash: bytes32, toHash: bytes32, contentsHash: bytes32) -> // Domain separator for name "Ether Mail", version "1", chainId 1 and the fixed // verifying contract from the spec. Uses the std EIP712Domain helper. -function mailDomainSeparator() -> bytes32 { +function mailDomainSeparator() returns (bytes32) { return eip712DomainSeparator( bytes32(keccakLit("Ether Mail")), bytes32(keccakLit("1")), @@ -53,7 +53,7 @@ function mailDomainSeparator() -> bytes32 { } // hashStruct of the fixed Mail message. -function mailStructHash() -> bytes32 { +function mailStructHash() returns (bytes32) { let fromHash = hashPerson( bytes32(keccakLit("Cow")), address(0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826) @@ -66,7 +66,7 @@ function mailStructHash() -> bytes32 { return hashMail(fromHash, toHash, contentsHash); } -function mailDigest() -> bytes32 { +function mailDigest() returns (bytes32) { return eip712Digest(mailDomainSeparator(), mailStructHash()); } @@ -74,21 +74,21 @@ contract EIP712Mail { constructor() {} // Intermediate hashes, exposed so each EIP-712 layer can be asserted. - public function domainSeparator() -> bytes32 { + function domainSeparator() public returns (bytes32) { return mailDomainSeparator(); } - public function structHash() -> bytes32 { + function structHash() public returns (bytes32) { return mailStructHash(); } - public function digest() -> bytes32 { + function digest() public returns (bytes32) { return mailDigest(); } // Recovers the signer of the fixed Mail message using the published // signature. Returns the "Cow" wallet 0xCD2a3d…D826. - public function verify() -> address { + function verify() public returns (address) { let v: uint256 = uint256(28); let r: bytes32 = bytes32(0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d); let s: bytes32 = bytes32(0x07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b91562); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.sol index 87b82bbf..4e012055 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor() {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol index 66a42685..ea5cab07 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/empty_no_constructor.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.sol index 9bf22452..32bb5827 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/fallback.sol @@ -1,14 +1,14 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract WithFallback { constructor() {} - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } - fallback() -> () { + fallback() { revertLit("fallback-was-called"); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.sol index f2086ae4..23605b9d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/forloops.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { counter : uint256; @@ -8,17 +8,17 @@ contract C { counter = uint256(0); } - function bump() -> uint256 { + function bump() returns (uint256) { counter = counter + uint256(1); return counter; } - public function getCounter() -> uint256 { + function getCounter() public returns (uint256) { return counter; } // Sum of 0..4 with early `break` at i == 5. - public function break_sum() -> uint256 { + function break_sum() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(0); i < uint256(10); i = i + uint256(1)) { if (i == uint256(5)) { @@ -32,7 +32,7 @@ contract C { // Sum of 5..9 using `continue` to skip the iterations where i < 5. // The post-statement (i = i + 1) must still run on `continue`, otherwise // the loop would never terminate. - public function continue_sum() -> uint256 { + function continue_sum() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(0); i < uint256(10); i = i + uint256(1)) { if (i < uint256(5)) { @@ -44,7 +44,7 @@ contract C { } // Empty initializer: `i` is declared/initialised outside the loop. - public function empty_init() -> uint256 { + function empty_init() public returns (uint256) { let i : uint256 = uint256(3); let s : uint256 = uint256(0); for (; i < uint256(7); i = i + uint256(1)) { @@ -54,7 +54,7 @@ contract C { } // Empty post-body: the increment is done in the loop body. - public function empty_post() -> uint256 { + function empty_post() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(0); i < uint256(4); ) { s = s + i; @@ -66,7 +66,7 @@ contract C { // Side effect in the condition: `bump()` increments storage on every // probe (including the failing one), so observing `counter` afterwards // proves the condition ran the expected number of times. - public function cond_side_effect() -> uint256 { + function cond_side_effect() public returns (uint256) { counter = uint256(0); for (let i : uint256 = uint256(0); bump() < uint256(5); i = i + uint256(1)) {} return counter; @@ -74,7 +74,7 @@ contract C { // Side effect in the post-body: `bump()` runs once per completed // iteration, so `counter` ends equal to the iteration count. - public function post_side_effect() -> uint256 { + function post_side_effect() public returns (uint256) { counter = uint256(0); for (let i : uint256 = uint256(0); i < uint256(3); bump()) { i = i + uint256(1); @@ -83,7 +83,7 @@ contract C { } // Nested `for` -- sum of i*j for i,j in 1..3. - public function double_loop() -> uint256 { + function double_loop() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(1); i < uint256(4); i = i + uint256(1)) { for (let j : uint256 = uint256(1); j < uint256(4); j = j + uint256(1)) { diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.sol index 5a2ce10f..5a6b0a72 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_product.sol @@ -1,21 +1,29 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-generic-instance-for Point; -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } -// Only requirement: Generic instance using the primitive pair type. +// Only requirement: a Generic impl using the primitive pair type. // rep = (uint256, uint256) — primitive Solcore pair -instance Point : Generic((uint256, uint256)) { - function from(p : Point) -> (uint256, uint256) { - match p { | Point(x, y) => return (x, y); } +impl Generic { + function from(p: Point) returns (uint256, uint256) { + match (p) { +case Point(x, y) { +return (x, y); +} +} } - function to(t : (uint256, uint256)) -> Point { - match t { | (x, y) => return Point(x, y); } + function to(t: (uint256, uint256)) returns (Point) { + match (t) { +case (x, y) { +return Point(x, y); +} +} } } @@ -23,7 +31,7 @@ contract GenericProduct { constructor() {} // Calls encode; returns word at offset 0 (the x field). - public function encodeX(a : uint256, b : uint256) -> uint256 { + function encodeX(a: uint256, b: uint256) public returns (uint256) { let p : Point = Point(a, b); let buf = allocate_zeroed_memory(64); encode(p, buf, 0, 64); @@ -31,7 +39,7 @@ contract GenericProduct { } // Calls encode; returns word at offset 32 (the y field). - public function encodeY(a : uint256, b : uint256) -> uint256 { + function encodeY(a: uint256, b: uint256) public returns (uint256) { let p : Point = Point(a, b); let buf = allocate_zeroed_memory(64); encode(p, buf, 0, 64); @@ -39,13 +47,17 @@ contract GenericProduct { } // Writes [a][b] into memory, calls decode, returns the x field. - public function decodeX(a : uint256, b : uint256) -> uint256 { + function decodeX(a: uint256, b: uint256) public returns (uint256) { let buf = allocate_zeroed_memory(64); mstore(buf, Typedef.rep(a)); mstore(buf + 32, Typedef.rep(b)); let rdr : MemoryWordReader = MemoryWordReader(buf); - let dec : ABIDecoder(Point, MemoryWordReader) = ABIDecoder(rdr); + let dec : ABIDecoder = ABIDecoder(rdr); let p : Point = decode(dec, 0); - match p { | Point(x, _) => return x; } + match (p) { +case Point(x, _) { +return x; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol index 164f7bc7..1fa67bb0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol @@ -1,27 +1,35 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-generic-instance-for Option; -data Option(a) = None | Some(a); +enum Option { None, Some(a) } -// Only requirement: Generic instance using the primitive sum type. +// Only requirement: a Generic impl using the primitive sum type. // rep = sum((), uint256): inl(()) = None, inr(v) = Some(v) -instance Option(uint256) : Generic(sum((), uint256)) { - function from(x : Option(uint256)) -> sum((), uint256) { - match x { - | Option.None => return inl(()); - | Option.Some(v) => return inr(v); - } +impl Generic, sum<(), uint256>> { + function from(x: Option) returns (sum<(), uint256>) { + match (x) { +case Option.None { +return inl(()); +} +case Option.Some(v) { +return inr(v); +} +} } - function to(r : sum((), uint256)) -> Option(uint256) { - match r { - | inl(_) => return Option.None; - | inr(v) => return Option.Some(v); - } + function to(r: sum<(), uint256>) returns (Option) { + match (r) { +case inl(_) { +return Option.None; +} +case inr(v) { +return Option.Some(v); +} +} } } @@ -30,8 +38,8 @@ contract GenericSum { // Calls encode; returns the tag word (first 32 bytes). // None → 0 - public function encodeNone() -> uint256 { - let x : Option(uint256) = Option.None; + function encodeNone() public returns (uint256) { + let x : Option = Option.None; let buf = allocate_zeroed_memory(64); encode(x, buf, 0, 64); return Typedef.abs(mload(buf)); @@ -39,23 +47,23 @@ contract GenericSum { // Calls encode; returns the tag word (first 32 bytes). // Some(n) → 1 - public function encodeSomeTag(n : uint256) -> uint256 { - let x : Option(uint256) = Option.Some(n); + function encodeSomeTag(n: uint256) public returns (uint256) { + let x : Option = Option.Some(n); let buf = allocate_zeroed_memory(64); encode(x, buf, 0, 64); return Typedef.abs(mload(buf)); } // Calls encode; returns the payload word (bytes 32-63). - public function encodePayload(n : uint256) -> uint256 { - let x : Option(uint256) = Option.Some(n); + function encodePayload(n: uint256) public returns (uint256) { + let x : Option = Option.Some(n); let buf = allocate_zeroed_memory(64); encode(x, buf, 0, 64); return Typedef.abs(mload(buf + 32)); } // Writes [tag][value] into memory, calls decode, returns the value or 0. - public function decodeAndGet(tag : uint256, value : uint256) -> uint256 { + function decodeAndGet(tag: uint256, value: uint256) public returns (uint256) { let buf = allocate_zeroed_memory(64); mstore(buf, Typedef.rep(tag)); mstore(buf + 32, Typedef.rep(value)); From df4af5d9b959985922fc808e009a40255ec5cc38 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 073/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../ok/test/examples/dispatch/generic_sum.sol | 16 ++- .../ok/test/examples/dispatch/hashes.sol | 22 ++-- .../ok/test/examples/dispatch/memory.sol | 10 +- .../ok/test/examples/dispatch/miniERC20.sol | 38 +++---- .../corpus/ok/test/examples/dispatch/neg.sol | 92 +++++++-------- .../examples/dispatch/nonpayable_ctor.sol | 6 +- .../ok/test/examples/dispatch/ownable.sol | 10 +- .../ok/test/examples/dispatch/p256verify.sol | 10 +- .../ok/test/examples/dispatch/payable.sol | 10 +- .../test/examples/dispatch/payable_ctor.sol | 8 +- .../ok/test/examples/dispatch/slices.sol | 26 ++--- .../dispatch/specialise_sum_of_product.sol | 73 +++++++----- .../ok/test/examples/dispatch/storage.sol | 8 +- .../examples/dispatch/storage_adt_abi.sol | 50 +++++---- .../examples/dispatch/storage_adt_bool.sol | 78 +++++++------ .../examples/dispatch/storage_adt_enum.sol | 85 ++++++++------ .../examples/dispatch/storage_adt_field.sol | 105 +++++++++++------- .../examples/dispatch/storage_adt_mapping.sol | 95 +++++++++------- .../test/examples/dispatch/storage_array.sol | 18 +-- .../dispatch/storage_dynamic_field.sol | 46 ++++---- .../ok/test/examples/dispatch/stringid.sol | 12 +- .../ok/test/examples/dispatch/stringlit.sol | 10 +- .../examples/dispatch/sum_wide_product.sol | 20 ++-- .../ok/test/examples/dispatch/ufcs_array.sol | 24 ++-- .../ok/test/examples/dispatch/weth9.sol | 28 ++--- 25 files changed, 501 insertions(+), 399 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol index 1fa67bb0..34d9b128 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/generic_sum.sol @@ -68,11 +68,15 @@ contract GenericSum { mstore(buf, Typedef.rep(tag)); mstore(buf + 32, Typedef.rep(value)); let rdr : MemoryWordReader = MemoryWordReader(buf); - let dec : ABIDecoder(Option(uint256), MemoryWordReader) = ABIDecoder(rdr); - let opt : Option(uint256) = decode(dec, 0); - match opt { - | Option.None => return uint256(0); - | Option.Some(v) => return v; - } + let dec : ABIDecoder, MemoryWordReader> = ABIDecoder(rdr); + let opt : Option = decode(dec, 0); + match (opt) { +case Option.None { +return uint256(0); +} +case Option.Some(v) { +return v; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.sol index 53912a49..2b54a846 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/hashes.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mstore}; +import * from std; +import * from std.dispatch; +import {mstore} from std.opcodes; // Build a memory(bytes) holding the three-byte string "abc". -function abcBytes() -> memory(bytes) { +function abcBytes() returns (memory) { let p = allocate_memory(64); mstore(p, 3); mstore(p + 32, 0x6162630000000000000000000000000000000000000000000000000000000000); @@ -13,35 +13,35 @@ function abcBytes() -> memory(bytes) { contract C { constructor() {} - public function keccak() -> bytes32 { + function keccak() public returns (bytes32) { return keccak256_(abcBytes()); } - public function sha() -> bytes32 { + function sha() public returns (bytes32) { return sha256(abcBytes()); } - public function ripemd() -> bytes32 { + function ripemd() public returns (bytes32) { return ripemd160(abcBytes()); } // keccakWordLit folds keccak256 of a word's 32-byte big-endian form at // compile time; keccakWordLit(0) == keccak256(bytes32(0)). - public function keccakWord() -> bytes32 { + function keccakWord() public returns (bytes32) { return bytes32(keccakWordLit(0)); } // ERC-7201 namespaced storage slots, folded to constants at compile time // from the string-literal namespace (no runtime keccak of the id). - public function erc7201Example() -> bytes32 { + function erc7201Example() public returns (bytes32) { return erc7201("example.main"); } - public function erc7201Ownable() -> bytes32 { + function erc7201Ownable() public returns (bytes32) { return erc7201("openzeppelin.storage.Ownable"); } - public function erc7201Empty() -> bytes32 { + function erc7201Empty() public returns (bytes32) { return erc7201(""); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.sol index eec43817..6f79c9cd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/memory.sol @@ -1,16 +1,16 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mstore}; +import * from std; +import * from std.dispatch; +import {mstore} from std.opcodes; contract C { - public function dirty_allocate() -> memory(bytes) { + function dirty_allocate() public returns (memory) { mstore(get_free_memory() + 32, 0xdeadc0de); let ptr = allocate_memory(32 + 32); mstore(ptr, 32); return memory(ptr); } - public function clear_allocate() -> memory(bytes) { + function clear_allocate() public returns (memory) { mstore(get_free_memory() + 32, 0xdeadc0de); let ptr = allocate_zeroed_memory(32 + 32); mstore(ptr, 32); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.sol index a5eb3554..bf23b85e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/miniERC20.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -15,10 +15,10 @@ contract MiniERC20 { owner : address; decimals : uint256; // should be uint8 when we get to it totalSupply : uint256; - balances : mapping(address,uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); - constructor(name_ : memory(string), symbol_ : memory(string), totalSupply_:uint256) { + constructor(name_ : memory, symbol_ : memory, totalSupply_:uint256) { name = name_; symbol = symbol_; owner = caller(); @@ -26,45 +26,45 @@ contract MiniERC20 { mint(totalSupply_); } - public function name() -> memory(string) { + function name() public returns (memory) { return name; } - public function symbol() -> memory(string) { + function symbol() public returns (memory) { return symbol; } - public function decimals() -> uint256 { + function decimals() public returns (uint256) { return decimals; } - public function allowance(owner_ : address, spender: address) -> uint256 { + function allowance(owner_: address, spender: address) public returns (uint256) { return allowance[owner_][spender]; // don't use "owner" here } - public function balanceOf(account : address) -> uint256 { + function balanceOf(account: address) public returns (uint256) { return balances[account]; } - public function totalSupply() -> uint256 { + function totalSupply() public returns (uint256) { return totalSupply; } // Note that this is not access guarded — the minting always goes to the owner - public function mint(amount:uint256) -> () { + function mint(amount: uint256) public { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } - public function transfer(dst : address, amt : uint256) -> bool { + function transfer(dst: address, amt: uint256) public returns (bool) { return transferFrom(caller(), dst, amt); } - public function transferFrom(src:address, dst:address, amt:uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) public returns (bool) { let msg_sender = caller(); require(balances[src] >= amt, "transferFrom: insufficient balance"); - if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal():uint256)) { + if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal())) { require(allowance[src][msg_sender] >= amt, "transferFrom: insufficient allowance"); allowance[src][msg_sender] -= amt; } @@ -74,7 +74,7 @@ contract MiniERC20 { return true; } - public function approve(usr: address, amt: uint256) -> bool { + function approve(usr: address, amt: uint256) public returns (bool) { let msg_sender = caller(); allowance[msg_sender][usr] = amt; // emit Approval(msg.sender, usr, amt); @@ -83,11 +83,11 @@ contract MiniERC20 { // testing - public function getMyBalance() -> uint256 { + function getMyBalance() public returns (uint256) { return balances[caller()]; } - public function test() -> uint256 { + function test() public returns (uint256) { approve(address(0), 10); transferFrom(caller(), address(0), 958); return getMyBalance(); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.sol index b04d0a8a..09356af6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/neg.sol @@ -1,69 +1,73 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -forall a. -class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; -data Pair(a,b) = Pair(a,b); +enum B { F, T } +enum Pair { Pair(a, b) } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } -forall a b . function pairfst (p : Pair(a,b)) -> a { - match p { - | Pair(x,y) => return x; - } +function pairfst(p: Pair) returns (a) { + match (p) { +case Pair(x,y) { +return x; +} +} } -forall a b . function pairsnd(p : Pair(a,b)) -> b { - match p { - | Pair(x,y) => return y; - } +function pairsnd(p: Pair) returns (b) { + match (p) { +case Pair(x,y) { +return y; +} +} } -forall a b. -a:Neg,b:Neg => instance Pair(a,b):Neg { - function neg(p:Pair(a,b)) -> Pair(a,b) { +impl Neg> where a: Neg, b: Neg { + function neg(p: Pair) returns (Pair) { return Pair(Neg.neg (pairfst(p)), Neg.neg(pairsnd(p))); } } -/* -instance (a:Neg,b:Neg) => Pair(a,b):Neg { - function neg(p) { - match p { - | Pair(a,b) => return Pair(neg(a), neg(b)); - } - } + function bnot(x: B) returns (B) { + match (x) { +case B.T { +return B.F; +} +case B.F { +return B.T; +} } -*/ - - function bnot(x:B) -> B { - match x { - | B.T => return B.F; - | B.F => return B.T; - } } - function fromB(b:B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } contract NegPair { constructor() {} - public function negPair() -> uint256 { return uint256(fromB(pairfst(Neg.neg(Pair(B.F,B.T))))); } + function negPair() public returns (uint256) { return uint256(fromB(pairfst(Neg.neg(Pair(B.F,B.T))))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol index c19c104b..4eebca06 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/nonpayable_ctor.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // A contract whose constructor is NOT marked `payable`. Deploying it with an // incoming value transfer must revert with the NonPayableReceivedValue error @@ -7,7 +7,7 @@ import std.dispatch.{*}; contract NonPayableCtor { constructor() {} - public function balance() -> uint256 { + function balance() public returns (uint256) { let value; assembly { value := selfbalance() diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.sol index b20be59b..c3c2fb65 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ownable.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // caller() is not in the std library yet, // so every contract must define its own -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -20,11 +20,11 @@ contract Ownable { } // named getOwner() instead of owner() to avoid collision with the field name - public function getOwner() -> address { + function getOwner() public returns (address) { return owner; } - public function changeOwner(newOwner : address) -> () { + function changeOwner(newOwner: address) public { require(caller() == owner, Error(0x12b0c500)); // OwnableUnauthorizedAccount() owner = newOwner; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.sol index e1ddc4f0..af8d978c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/p256verify.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; -import std.eip7951.{p256verify}; +import * from std; +import * from std.dispatch; +import {p256verify} from std.eip7951; // Exercises the P256VERIFY (secp256r1) precompile at address 0x100, introduced // by EIP-7951, through the std `p256verify` helper. It returns true for a valid @@ -8,7 +8,7 @@ import std.eip7951.{p256verify}; contract P256Test { constructor() {} - public function verifyValid() -> bool { + function verifyValid() public returns (bool) { return p256verify( bytes32(0xabcdef00112233445566778899aabbccddeeff00112233445566778899aabbcc), bytes32(0xa29295460e251beea1bdc9b84b2f3fe8e3a3e4d872baa3c55b78c9e448190ea9), @@ -18,7 +18,7 @@ contract P256Test { ); } - public function verifyInvalid() -> bool { + function verifyInvalid() public returns (bool) { return p256verify( bytes32(0xabcdef00112233445566778899aabbccddeeff00112233445566778899aabbcd), bytes32(0xa29295460e251beea1bdc9b84b2f3fe8e3a3e4d872baa3c55b78c9e448190ea9), diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.sol index 553275b1..a8d15a88 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PayableTest { constructor() {} - public payable function deposit() -> uint256 { + function deposit() public payable returns (uint256) { let value; assembly { value := callvalue() @@ -12,7 +12,7 @@ contract PayableTest { return uint256(value); } - public function balance() -> uint256 { + function balance() public returns (uint256) { let value; assembly { value := selfbalance() @@ -20,7 +20,7 @@ contract PayableTest { return uint256(value); } - payable fallback() -> () { + fallback() payable { let value; assembly { value := callvalue() diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol index ce2d3ce1..93c6813a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/payable_ctor.sol @@ -1,13 +1,13 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // A contract whose constructor is explicitly marked `payable`. // Deploying it with an incoming value transfer must succeed and the // transferred value is retained by the newly created contract. contract PayableCtor { - payable constructor() {} + constructor() payable {} - public function balance() -> uint256 { + function balance() public returns (uint256) { let value; assembly { value := selfbalance() diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.sol index a44d6b38..7d6025f4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/slices.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Exercises slice_/truncate (memory_slice) composed with concat, to_bytes, // and the hashing precompiles (keccak256_, sha256). memory_slice implements @@ -8,58 +8,58 @@ import std.dispatch.{*}; contract C { // --- slice_/truncate on a memory(bytes), materialized with to_bytes --- - public function slice_bytes(a: memory(bytes), start: uint256) -> memory(bytes) { + function slice_bytes(a: memory, start: uint256) public returns (memory) { return to_bytes(slice_(a, Typedef.rep(start))); } - public function truncate_bytes(a: memory(bytes), end: uint256) -> memory(bytes) { + function truncate_bytes(a: memory, end: uint256) public returns (memory) { return to_bytes(truncate(a, Typedef.rep(end))); } // --- slice_/truncate over the result of a concat --- - public function slice_of_concat(a: bytes32, b: bytes32, start: uint256) -> memory(bytes) { + function slice_of_concat(a: bytes32, b: bytes32, start: uint256) public returns (memory) { return to_bytes(slice_(concat(a, b), Typedef.rep(start))); } - public function truncate_of_concat(a: bytes32, b: bytes32, end: uint256) -> memory(bytes) { + function truncate_of_concat(a: bytes32, b: bytes32, end: uint256) public returns (memory) { return to_bytes(truncate(concat(a, b), Typedef.rep(end))); } // to_bytes(truncate(slice_(concat(a, b), start), end)) -- the headline nesting: // drop `start` bytes, then keep `end` of what remains (re-slicing a memory_slice). - public function window_of_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) -> memory(bytes) { + function window_of_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) public returns (memory) { return to_bytes(truncate(slice_(concat(a, b), Typedef.rep(start)), Typedef.rep(end))); } // --- a slice used as a concat operand --- - public function concat_slice_b32(a: memory(bytes), start: uint256, c: bytes32) -> memory(bytes) { + function concat_slice_b32(a: memory, start: uint256, c: bytes32) public returns (memory) { return concat(slice_(a, Typedef.rep(start)), c); } - public function concat_two_slices(a: memory(bytes), sa: uint256, b: memory(bytes), eb: uint256) -> memory(bytes) { + function concat_two_slices(a: memory, sa: uint256, b: memory, eb: uint256) public returns (memory) { return concat(slice_(a, Typedef.rep(sa)), truncate(b, Typedef.rep(eb))); } // --- re-slicing a memory_slice --- - public function slice_of_slice(a: memory(bytes), s1: uint256, s2: uint256) -> memory(bytes) { + function slice_of_slice(a: memory, s1: uint256, s2: uint256) public returns (memory) { return to_bytes(slice_(slice_(a, Typedef.rep(s1)), Typedef.rep(s2))); } // --- hashing a slice directly (no intermediate copy) --- - public function keccak_slice(a: memory(bytes), start: uint256) -> bytes32 { + function keccak_slice(a: memory, start: uint256) public returns (bytes32) { return keccak256_(slice_(a, Typedef.rep(start))); } - public function sha_truncate(a: memory(bytes), end: uint256) -> bytes32 { + function sha_truncate(a: memory, end: uint256) public returns (bytes32) { return sha256(truncate(a, Typedef.rep(end))); } // keccak256_(truncate(slice_(concat(a, b), start), end)) -- nested chain, hash endpoint. - public function keccak_window_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) -> bytes32 { + function keccak_window_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) public returns (bytes32) { return keccak256_(truncate(slice_(concat(a, b), Typedef.rep(start)), Typedef.rep(end))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.sol index 22d60064..b28de52b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/specialise_sum_of_product.sol @@ -20,50 +20,65 @@ // class and its instances are defined locally and exercised directly, so the // program must now lower end-to-end and return the expected value. -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-patterson-condition; pragma no-bounded-variable-condition; // total(x, y) sums every leaf word of both arguments. -forall a. -class a : Total { - function total(x : a, y : a) -> word; +trait Total { + function total(x: a, y: a) returns (word) ; } -instance word : Total { - function total(x : word, y : word) -> word { +impl Total { + function total(x: word, y: word) returns (word) { return x + y; } } // product: recurse into both components (this is the shape inl carries). -forall f g . f : Total, g : Total => instance (f, g) : Total { - function total(x : (f, g), y : (f, g)) -> word { - match x { - | (xa, xb) => match y { - | (ya, yb) => return Total.total(xa, ya) + Total.total(xb, yb); - } - } +impl Total<(f, g)> where f: Total, g: Total { + function total(x: (f, g), y: (f, g)) returns (word) { + match (x) { +case (xa, xb) { +match (y) { +case (ya, yb) { +return Total.total(xa, ya) + Total.total(xb, yb); +} +} +} +} } } // sum: the buggy shape. The inl branch recurses at f (a product here), the inr // branch recurses at g (a word here); specializing one must not pollute the // other's nested `match y`. -forall f g . f : Total, g : Total => instance sum(f, g) : Total { - function total(x : sum(f, g), y : sum(f, g)) -> word { - match x { - | inl(xa) => match y { - | inl(ya) => return Total.total(xa, ya); - | inr(yb) => return 0; - } - | inr(xb) => match y { - | inl(ya) => return 0; - | inr(yb) => return Total.total(xb, yb); - } - } +impl Total> where f: Total, g: Total { + function total(x: sum, y: sum) returns (word) { + match (x) { +case inl(xa) { +match (y) { +case inl(ya) { +return Total.total(xa, ya); +} +case inr(yb) { +return 0; +} +} +} +case inr(xb) { +match (y) { +case inl(ya) { +return 0; +} +case inr(yb) { +return Total.total(xb, yb); +} +} +} +} } } @@ -73,9 +88,9 @@ contract SpecialiseSumOfProduct { // inl carries a product (word, word); the two sum sides differ in shape // (pair vs word), which is what the specializer mishandled. // total(inl((1,2)), inl((1,2))) = total((1,2),(1,2)) = (1+1)+(2+2) = 6. - public function probe() -> uint256 { - let x : sum((word, word), word) = inl((1, 2)); - let y : sum((word, word), word) = inl((1, 2)); + function probe() public returns (uint256) { + let x : sum<(word, word), word> = inl((1, 2)); + let y : sum<(word, word), word> = inl((1, 2)); return uint256(Total.total(x, y)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol index a1a53781..f7ff51e2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage support for a `memory(bytes)` contract field: assigning to the // field copies the byte array into storage, reading it back loads it into @@ -7,11 +7,11 @@ import std.dispatch.{*}; contract C { content: bytes; - public function set(value: memory(bytes)) -> () { + function set(value: memory) public { content = value; } - public function get() -> memory(bytes) { + function get() public returns (memory) { return content; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.sol index 2dcdc0ba..35e8cbcc 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_abi.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; +import * from std.StorageGeneric; // An ADT crossing the ABI boundary AND living in storage at the same time. // @@ -18,42 +18,50 @@ import std.StorageGeneric.{*}; // at +32. So `Some(42)` is 0x...01 followed by 0x...2a, and `None` is 0x...00 // followed by a don't-care word. -data Option(a) = None | Some(a); +enum Option { None, Some(a) } contract C { - stored : Option(uint256); + stored : Option; constructor() { stored = Option.None; - assert(StorageSize.size(Proxy : Proxy(Option(uint256))) == 2); + assert(StorageSize.size(@Option) == 2); } // ADT as a parameter: decoded from calldata, then written to storage. - public function setOpt(o : Option(uint256)) -> () { + function setOpt(o: Option) public { stored = o; } // ADT as a return value: loaded from storage, then encoded into returndata. - public function getOpt() -> Option(uint256) { + function getOpt() public returns (Option) { return stored; } // Round-trip in one call, without touching storage. - public function echo(o : Option(uint256)) -> Option(uint256) { + function echo(o: Option) public returns (Option) { return o; } - public function isSome() -> bool { - match stored { - | Option.None => return false; - | Option.Some(_) => return true; - } + function isSome() public returns (bool) { + match (stored) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } - public function unwrapOr(d : uint256) -> uint256 { - match stored { - | Option.None => return d; - | Option.Some(v) => return v; - } + function unwrapOr(d: uint256) public returns (uint256) { + match (stored) { +case Option.None { +return d; +} +case Option.Some(v) { +return v; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.sol index 5d1a80b6..ee7a810e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_bool.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // `bool` in storage, bare and inside an ADT. // @@ -16,10 +16,10 @@ import std.StorageGeneric.{*}; // instance, so it cannot appear in a public parameter position. It can appear // in a return position, which is what the getters below exercise. -data Flags = Flags(bool, bool); -data Toggle = Off | On(bool); +enum Flags { Flags(bool, bool) } +enum Toggle { Off, On(bool) } -function toBool(v : uint256) -> bool { +function toBool(v: uint256) returns (bool) { return v != uint256(0); } @@ -32,58 +32,70 @@ contract C { bare = false; flags = Flags(false, false); toggle = Toggle.Off; - assert(StorageSize.size(Proxy : Proxy(bool)) == 1); + assert(StorageSize.size(@bool) == 1); // product of two bools - assert(StorageSize.size(Proxy : Proxy(Flags)) == 2); + assert(StorageSize.size(@Flags) == 2); // 1 tag + max(size (), size bool) - assert(StorageSize.size(Proxy : Proxy(Toggle)) == 2); + assert(StorageSize.size(@Toggle) == 2); } - public function setBare(v : uint256) -> () { + function setBare(v: uint256) public { bare = toBool(v); } - public function getBare() -> bool { + function getBare() public returns (bool) { return bare; } - public function setFlags(a : uint256, b : uint256) -> () { + function setFlags(a: uint256, b: uint256) public { flags = Flags(toBool(a), toBool(b)); } - public function firstFlag() -> bool { - match flags { - | Flags(a, _) => return a; - } + function firstFlag() public returns (bool) { + match (flags) { +case Flags(a, _) { +return a; +} +} } - public function secondFlag() -> bool { - match flags { - | Flags(_, b) => return b; - } + function secondFlag() public returns (bool) { + match (flags) { +case Flags(_, b) { +return b; +} +} } - public function turnOn(v : uint256) -> () { + function turnOn(v: uint256) public { toggle = Toggle.On(toBool(v)); } - public function turnOff() -> () { + function turnOff() public { toggle = Toggle.Off; } // Distinguishes Off from On(false): both leave a zero payload slot, so only // the tag can tell them apart. - public function isOn() -> bool { - match toggle { - | Toggle.Off => return false; - | Toggle.On(_) => return true; - } + function isOn() public returns (bool) { + match (toggle) { +case Toggle.Off { +return false; +} +case Toggle.On(_) { +return true; +} +} } - public function toggleValue() -> bool { - match toggle { - | Toggle.Off => revertEmpty(); return false; - | Toggle.On(b) => return b; - } + function toggleValue() public returns (bool) { + match (toggle) { +case Toggle.Off { +revertEmpty(); return false; +} +case Toggle.On(b) { +return b; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.sol index 732d6036..5f721fe2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_enum.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // An enumeration with more than two constructors. // @@ -17,15 +17,12 @@ import std.StorageGeneric.{*}; // // `Green` is the only constructor that exercises the `inr(inl(...))` path, // which is exactly the sum nesting that CanStore.load has to reconstruct. -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } // A three-constructor sum whose branches carry payloads of different widths. // rep = sum(uint256, sum((uint256, uint256), ())), so // size = 1 + max(1, 1 + max(2, 0)) = 4. -data Shape = - Dot(uint256) - | Seg(uint256, uint256) - | Nothing; +enum Shape { Dot(uint256), Seg(uint256, uint256), Nothing } contract C { color : Color; @@ -35,58 +32,76 @@ contract C { color = Color.Red; shape = Shape.Nothing; // 1 tag + max(size (), 1 tag + max(size (), size ())) = 1 + 1 + 0 = 2 - assert(StorageSize.size(Proxy : Proxy(Color)) == 2); + assert(StorageSize.size(@Color) == 2); // 1 tag + max(size uint256, 1 tag + max(size (uint256,uint256), size ())) = 1 + 1 + 2 = 4 - assert(StorageSize.size(Proxy : Proxy(Shape)) == 4); + assert(StorageSize.size(@Shape) == 4); } - public function setRed() -> () { + function setRed() public { color = Color.Red; } // inr(inl(())) — the nested-tag branch. - public function setGreen() -> () { + function setGreen() public { color = Color.Green; } - public function setBlue() -> () { + function setBlue() public { color = Color.Blue; } - public function tag() -> uint256 { - match color { - | Color.Red => return uint256(0); - | Color.Green => return uint256(1); - | Color.Blue => return uint256(2); - } + function tag() public returns (uint256) { + match (color) { +case Color.Red { +return uint256(0); +} +case Color.Green { +return uint256(1); +} +case Color.Blue { +return uint256(2); +} +} } - public function setDot(a : uint256) -> () { + function setDot(a: uint256) public { shape = Shape.Dot(a); } // inr(inl(...)) again, this time with a product payload. - public function setSeg(a : uint256, b : uint256) -> () { + function setSeg(a: uint256, b: uint256) public { shape = Shape.Seg(a, b); } - public function setNothing() -> () { + function setNothing() public { shape = Shape.Nothing; } - public function shapeSum() -> uint256 { - match shape { - | Shape.Dot(a) => return a; - | Shape.Seg(a, b) => return a + b; - | Shape.Nothing => return uint256(0); - } + function shapeSum() public returns (uint256) { + match (shape) { +case Shape.Dot(a) { +return a; +} +case Shape.Seg(a, b) { +return a + b; +} +case Shape.Nothing { +return uint256(0); +} +} } - public function shapeTag() -> uint256 { - match shape { - | Shape.Dot(_) => return uint256(0); - | Shape.Seg(_, _) => return uint256(1); - | Shape.Nothing => return uint256(2); - } + function shapeTag() public returns (uint256) { + match (shape) { +case Shape.Dot(_) { +return uint256(0); +} +case Shape.Seg(_, _) { +return uint256(1); +} +case Shape.Nothing { +return uint256(2); +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.sol index d1b68cb2..c9bc2ef5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_field.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // Algebraic data types used directly as contract storage fields, including a // nested ADT (Option(Triple)). @@ -10,78 +10,97 @@ import std.StorageGeneric.{*}; // - triple : Triple (product, rep (uint256,(uint256,uint256)) -> 3 slots) // - someTriple : Option(Triple) (sum of product, rep sum((), Triple) -> 4 slots) -data Option(a) = None | Some(a); -data Triple = Triple(uint256, uint256, uint256); +enum Option { None, Some(a) } +enum Triple { Triple(uint256, uint256, uint256) } contract C { - someValue : Option(uint256); + someValue : Option; triple : Triple; - someTriple : Option(Triple); + someTriple : Option; constructor() { // sum: 1 tag + max(size (), size uint256) = 1 + 1 = 2 - assert(StorageSize.size(Proxy : Proxy(Option(uint256))) == 2); + assert(StorageSize.size(@Option) == 2); // product: size uint256 * 3 = 3 - assert(StorageSize.size(Proxy : Proxy(Triple)) == 3); + assert(StorageSize.size(@Triple) == 3); // sum of product: 1 tag + max(size (), size Triple) = 1 + 3 = 4 - assert(StorageSize.size(Proxy : Proxy(Option(Triple))) == 4); + assert(StorageSize.size(@Option) == 4); } - public function setValue(v : uint256) -> () { + function setValue(v: uint256) public { someValue = Option.Some(v); } - public function clearValue() -> () { + function clearValue() public { someValue = Option.None; } - public function getValue() -> uint256 { - match someValue { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(v) => return v; - } + function getValue() public returns (uint256) { + match (someValue) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(v) { +return v; +} +} } - public function isSome() -> bool { - match someValue { - | Option.None => return false; - | Option.Some(_) => return true; - } + function isSome() public returns (bool) { + match (someValue) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } - public function setTriple(a : uint256, b : uint256, c : uint256) -> () { + function setTriple(a: uint256, b: uint256, c: uint256) public { triple = Triple(a, b, c); } - public function tripleSum() -> uint256 { - match triple { - | Triple(a, b, c) => return a + b + c; - } + function tripleSum() public returns (uint256) { + match (triple) { +case Triple(a, b, c) { +return a + b + c; +} +} } // Nested ADT: Option(Triple). - public function setSomeTriple(a : uint256, b : uint256, c : uint256) -> () { + function setSomeTriple(a: uint256, b: uint256, c: uint256) public { someTriple = Option.Some(Triple(a, b, c)); } - public function clearSomeTriple() -> () { + function clearSomeTriple() public { someTriple = Option.None; } - public function someTripleSum() -> uint256 { - match someTriple { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(t) => - match t { - | Triple(a, b, c) => return a + b + c; - } - } + function someTripleSum() public returns (uint256) { + match (someTriple) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(t) { +match (t) { +case Triple(a, b, c) { +return a + b + c; +} +} +} +} } - public function hasSomeTriple() -> bool { - match someTriple { - | Option.None => return false; - | Option.Some(_) => return true; - } + function hasSomeTriple() public returns (bool) { + match (someTriple) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.sol index ad2f4df8..4cb752ac 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_adt_mapping.sol @@ -1,82 +1,97 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // An ADT used as the VALUE of a storage mapping. // // This is the path opened by routing mapping reads through CanStore instead of -// StorageType (std.solc: readStorage / ridx / RValueIdxAccess). The write side +// StorageType (std.sol: readStorage / ridx / RValueIdxAccess). The write side // already went through Assign -> CanStore.store. // // A multi-slot value in a mapping occupies hash2(slot, key) .. + size(v) - 1, // exactly as Solidity lays out a struct behind a mapping. -data Option(a) = None | Some(a); -data Pair = Pair(uint256, uint256); +enum Option { None, Some(a) } +enum Pair { Pair(uint256, uint256) } contract C { // 2 slots per entry: tag + payload - opts : mapping(uint256, Option(uint256)); + opts : mapping(uint256 => Option); // 2 slots per entry: no tag, two words - pairs : mapping(uint256, Pair); + pairs : mapping(uint256 => Pair); // 3 slots per entry: tag + max(0, 2) - optPairs : mapping(uint256, Option(Pair)); + optPairs : mapping(uint256 => Option); constructor() { - assert(StorageSize.size(Proxy : Proxy(Option(uint256))) == 2); - assert(StorageSize.size(Proxy : Proxy(Pair)) == 2); - assert(StorageSize.size(Proxy : Proxy(Option(Pair))) == 3); + assert(StorageSize.size(@Option) == 2); + assert(StorageSize.size(@Pair) == 2); + assert(StorageSize.size(@Option) == 3); } - public function putOpt(k : uint256, v : uint256) -> () { + function putOpt(k: uint256, v: uint256) public { opts[k] = Option.Some(v); } - public function clearOpt(k : uint256) -> () { + function clearOpt(k: uint256) public { opts[k] = Option.None; } // Unset keys read back as the zero slot pattern, i.e. tag 0 = None. - public function hasOpt(k : uint256) -> bool { - match opts[k] { - | Option.None => return false; - | Option.Some(_) => return true; - } + function hasOpt(k: uint256) public returns (bool) { + match (opts[k]) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } - public function getOpt(k : uint256) -> uint256 { - match opts[k] { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(v) => return v; - } + function getOpt(k: uint256) public returns (uint256) { + match (opts[k]) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(v) { +return v; +} +} } - public function putPair(k : uint256, a : uint256, b : uint256) -> () { + function putPair(k: uint256, a: uint256, b: uint256) public { pairs[k] = Pair(a, b); } - public function pairSum(k : uint256) -> uint256 { - match pairs[k] { - | Pair(a, b) => return a + b; - } + function pairSum(k: uint256) public returns (uint256) { + match (pairs[k]) { +case Pair(a, b) { +return a + b; +} +} } - public function putOptPair(k : uint256, a : uint256, b : uint256) -> () { + function putOptPair(k: uint256, a: uint256, b: uint256) public { optPairs[k] = Option.Some(Pair(a, b)); } - public function clearOptPair(k : uint256) -> () { + function clearOptPair(k: uint256) public { optPairs[k] = Option.None; } - public function optPairSum(k : uint256) -> uint256 { - match optPairs[k] { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(p) => - match p { - | Pair(a, b) => return a + b; - } - } + function optPairSum(k: uint256) public returns (uint256) { + match (optPairs[k]) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(p) { +match (p) { +case Pair(a, b) { +return a + b; +} +} +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.sol index f652f8d5..65057965 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_array.sol @@ -1,18 +1,18 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; contract MemberRegistry { - members : array(address); + members : array
; constructor() {} - public function addMember(addr : address) -> () { + function addMember(addr: address) public { ArrayPush.push(members, addr); } // MemberNotFound() selector - public function removeMember(addr : address) -> () { + function removeMember(addr: address) public { // foundIdx == length() acts as the "not found" sentinel. let foundIdx : uint256 = Length.length(members); let i : uint256; @@ -32,11 +32,11 @@ contract MemberRegistry { Array.pop(members); } - public function numberOfMembers() -> uint256 { + function numberOfMembers() public returns (uint256) { return Length.length(members); } - public function getMembers() -> memory(DynArray(address)) { + function getMembers() public returns (memory>) { let count : word = Typedef.rep(Length.length(members)); let totalBytes : word = (count + 1) * 32; let ptr : word = allocate_memory(totalBytes); @@ -47,6 +47,6 @@ contract MemberRegistry { let addr : address = members[uint256(i)]; mstore(ptr + 32 + i * 32, Typedef.rep(addr)); } - return Typedef.abs(ptr) : memory(DynArray(address)); + return Typedef.abs(ptr) ; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.sol index fa863452..7ab845fe 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage_dynamic_field.sol @@ -1,11 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; -data Blob = - NoBlob - | SomeBytes(memory(bytes)); +enum Blob { NoBlob, SomeBytes(memory) } contract C { blob : Blob; @@ -13,31 +11,39 @@ contract C { constructor() { blob = Blob.NoBlob; // A dynamic field occupies one slot, so the sum is 1 (tag) + max(0, 1). - assert(StorageSize.size(Proxy : Proxy(Blob)) == 2); + assert(StorageSize.size(@Blob) == 2); } - public function clear() -> () { + function clear() public { blob = Blob.NoBlob; } // Stores the memory(bytes) payload into the ADT field (round-trips the // dynamic leaf through storage(bytes)). - public function setBytes(b: memory(bytes)) -> () { + function setBytes(b: memory) public { blob = Blob.SomeBytes(b); } - public function getBytes() -> memory(bytes) { - match blob { - | Blob.NoBlob => revertEmpty(); return memory(0); - | Blob.SomeBytes(b) => return b; - } + function getBytes() public returns (memory) { + match (blob) { +case Blob.NoBlob { +revertEmpty(); return memory(0); +} +case Blob.SomeBytes(b) { +return b; +} +} } // Loads the whole ADT back from storage and inspects its tag. - public function isEmpty() -> bool { - match blob { - | Blob.NoBlob => return true; - | Blob.SomeBytes(_) => return false; - } + function isEmpty() public returns (bool) { + match (blob) { +case Blob.NoBlob { +return true; +} +case Blob.SomeBytes(_) { +return false; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.sol index 6e5c1d8a..298d7312 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringid.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mstore, mload}; +import * from std; +import * from std.dispatch; +import {mstore, mload} from std.opcodes; contract C { constructor() {} - public function id(x:memory(string)) -> (memory(string)) { + function id(x: memory) public returns (memory) { let ptr : word = Typedef.rep(x); let len : word; let n1 : word; @@ -18,14 +18,14 @@ contract C { return x; } - public function const_a() -> (memory(string)) { + function const_a() public returns (memory) { let resPtr = allocate_memory(64); let payload : word = 0x7777777777777777777777777777777777777777777777777777777777777777; mstore(resPtr, 3); mstore(resPtr+32, payload); return memory(resPtr); } - public function mylen(x:memory(string)) -> uint256 { + function mylen(x: memory) public returns (uint256) { let ptr : word = Typedef.rep(x); let l : word; let n1 : word; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.sol index 6136d366..31d4260e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/stringlit.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.{memory, string, uint256}; -import std.dispatch.{*}; +import * from std; +import {memory, string, uint256} from std; +import * from std.dispatch; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -11,14 +11,14 @@ contract C { constructor() {} // terse: concatLit wrapped in Str.fromString by the desugarer - public function greeting() -> memory(string) { + function greeting() public returns (memory) { return concatLit("Hello, ", "world!"); // fromString inserted automatically when using concatLit // later we may have an operator for that e.g. <> } // A2: via an intermediate string-typed let (dead-let substitution path) - public function greetLet() -> memory(string) { + function greetLet() public returns (memory) { let s : string = "Hello, " + "world!"; return Str.fromString(s); // here fromString needs to be inserted manually diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.sol index 259047a9..50a9ce58 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/sum_wide_product.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Regression test for a yule backend bug, independent of the storage/Generic // work: matching a sum constructor whose payload is a product of arity >= 3. @@ -12,18 +12,22 @@ import std.dispatch.{*}; // No storage and no Generic derivation involved — just constructing and matching // an ordinary algebraic data type. -data Shape = Dot | Tri(uint256, uint256, uint256); +enum Shape { Dot, Tri(uint256, uint256, uint256) } contract C { constructor() {} // Build Tri(a,b,c) then match it back out: exercises a sum whose payload is // a 3-field product. - public function triSum(a : uint256, b : uint256, c : uint256) -> uint256 { + function triSum(a: uint256, b: uint256, c: uint256) public returns (uint256) { let s : Shape = Shape.Tri(a, b, c); - match s { - | Shape.Dot => return uint256(0); - | Shape.Tri(x, y, z) => return x + y + z; - } + match (s) { +case Shape.Dot { +return uint256(0); +} +case Shape.Tri(x, y, z) { +return x + y + z; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.sol index 53d7855e..afbe95ca 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/ufcs_array.sol @@ -1,13 +1,13 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; -// UFCS counterpart of storage_array.solc. +// UFCS counterpart of storage_array.sol. // // This contract is byte-for-byte equivalent in behaviour to -// dispatch/storage_array.solc, but exercises the receiver-style method-call +// dispatch/storage_array.sol, but exercises the receiver-style method-call // sugar resolved by NameResolution: when the receiver of recv.method(args) -// is an (unqualified) contract field and a unique class exposes method, the +// is an (unqualified) contract field and a unique trait exposes the method, the // call is rewritten to Class.method(recv, args). So: // // members.push(addr) ==> ArrayPush.push(members, addr) @@ -19,16 +19,16 @@ import std.opcodes.{mload, mstore}; // the same runtime behaviour. Indexed access members[i] is unaffecte: it // is handled by field-access desugaring, not UFCS. contract MemberRegistry { - members : array(address); + members : array
; constructor() {} - public function addMember(addr : address) -> () { + function addMember(addr: address) public { members.push(addr); } // MemberNotFound() selector - public function removeMember(addr : address) -> () { + function removeMember(addr: address) public { // foundIdx == length() acts as the "not found" sentinel. let foundIdx : uint256 = members.length(); let i : uint256; @@ -48,11 +48,11 @@ contract MemberRegistry { members.pop(); } - public function numberOfMembers() -> uint256 { + function numberOfMembers() public returns (uint256) { return members.length(); } - public function getMembers() -> memory(DynArray(address)) { + function getMembers() public returns (memory>) { let count : word = Typedef.rep(members.length()); let totalBytes : word = (count + 1) * 32; let ptr : word = allocate_memory(totalBytes); @@ -63,6 +63,6 @@ contract MemberRegistry { let addr : address = members[uint256(i)]; mstore(ptr + 32 + i * 32, Typedef.rep(addr)); } - return Typedef.abs(ptr) : memory(DynArray(address)); + return Typedef.abs(ptr) ; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol index bd3125ea..80b7bbc5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol @@ -1,37 +1,37 @@ -import std.{*}; -import std.opcodes.{caller as caller_, callvalue as callvalue_, selfbalance, gas, call}; -import std.dispatch.{*}; +import * from std; +import {caller as caller_, callvalue as callvalue_, selfbalance, gas, call} from std.opcodes; +import * from std.dispatch; // Forward `wad` wei to `dst` via a zero-data CALL and revert on failure. -function sendValue(dst: address, wad: uint256) -> () { +function sendValue(dst: address, wad: uint256) { let ret = call(gas(), Typedef.rep(dst), Typedef.rep(wad), 0, 0, 0, 0); require(ret != 0, Error(0x90b8ec18)); // TransferFailed() } -function caller() -> address { +function caller() returns (address) { return address(caller_()); } -function callvalue() -> uint256 { +function callvalue() returns (uint256) { return uint256(callvalue_()); } // Based on https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol // That code is written WITHOUT checked arithmetic. contract WETH9 { - balances : mapping(address, uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); constructor() {} // --- ETH <-> WETH --- - public payable function deposit() -> () { + function deposit() public payable { let sender = caller(); balances[sender] = balances[sender] + callvalue(); } - public function withdraw(wad: uint256) -> () { + function withdraw(wad: uint256) public { let sender = caller(); require(balances[sender] >= wad, Error(0xf4d678b8)); // InsufficientBalance() balances[sender] = balances[sender] - wad; @@ -39,21 +39,21 @@ contract WETH9 { } // totalSupply == ETH held by this contract (matches canonical WETH9). - public function totalSupply() -> uint256 { + function totalSupply() public returns (uint256) { return uint256(selfbalance()); } // --- ERC20 surface --- - public function balanceOf(account: address) -> uint256 { + function balanceOf(account: address) public returns (uint256) { return balances[account]; } - public function allowance(owner_: address, spender: address) -> uint256 { + function allowance(owner_: address, spender: address) public returns (uint256) { return allowance[owner_][spender]; } - public function approve(usr: address, wad: uint256) -> bool { + function approve(usr: address, wad: uint256) public returns (bool) { let sender = caller(); allowance[sender][usr] = wad; return true; From 91532ec1c0cd73e127b40074c8d9daf6e8931333 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 074/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../ok/test/examples/dispatch/weth9.sol | 8 +- .../ok/test/examples/opcodes/all-shapes.sol | 10 +-- .../ok/test/examples/opcodes/terminators.sol | 12 +-- .../ok/test/examples/pragmas/coverage.sol | 8 +- .../ok/test/examples/pragmas/patterson.sol | 18 ++--- .../corpus/ok/test/examples/spec/00answer.sol | 2 +- .../corpus/ok/test/examples/spec/01id.sol | 8 +- .../corpus/ok/test/examples/spec/021not.sol | 32 +++++--- .../corpus/ok/test/examples/spec/022add.sol | 4 +- .../corpus/ok/test/examples/spec/024arith.sol | 16 ++-- .../corpus/ok/test/examples/spec/02nid.sol | 8 +- .../corpus/ok/test/examples/spec/031maybe.sol | 20 +++-- .../ok/test/examples/spec/032simplejoin.sol | 62 +++++++++------ .../corpus/ok/test/examples/spec/033join.sol | 34 +++++---- .../ok/test/examples/spec/034cojoin.sol | 58 +++++++++----- .../ok/test/examples/spec/035padding.sol | 18 +++-- .../ok/test/examples/spec/036wildcard.sol | 18 +++-- .../ok/test/examples/spec/037dwarves.sol | 34 ++++++--- .../corpus/ok/test/examples/spec/038food0.sol | 26 ++++--- .../corpus/ok/test/examples/spec/039food.sol | 42 ++++++---- .../corpus/ok/test/examples/spec/041pair.sol | 12 +-- .../ok/test/examples/spec/042triple.sol | 12 +-- .../ok/test/examples/spec/043fstsnd.sol | 30 ++++---- .../corpus/ok/test/examples/spec/047rgb.sol | 20 +++-- .../corpus/ok/test/examples/spec/048rgb2.sol | 22 ++++-- .../corpus/ok/test/examples/spec/049rgb3.sol | 22 ++++-- .../corpus/ok/test/examples/spec/06comp.sol | 6 +- .../corpus/ok/test/examples/spec/09not.sol | 32 +++++--- .../ok/test/examples/spec/10negBool.sol | 38 ++++++---- .../ok/test/examples/spec/11negPair.sol | 76 +++++++++++-------- .../ok/test/examples/spec/120basicCounter.sol | 4 +- .../ok/test/examples/spec/121counter.sol | 2 +- .../ok/test/examples/spec/122counters.sol | 4 +- .../test/examples/spec/123stackAndStorage.sol | 4 +- .../ok/test/examples/spec/126nanoerc20.sol | 43 ++++++----- .../ok/test/examples/spec/127microerc20.sol | 60 +++++++++------ .../ok/test/examples/spec/128minierc20.sol | 26 +++---- .../ok/test/examples/spec/129arraystorage.sol | 6 +- .../ok/test/examples/spec/130arrayfield.sol | 6 +- .../ok/test/examples/spec/131localindex.sol | 8 +- .../ok/test/examples/spec/132nestedarray.sol | 6 +- .../ok/test/examples/spec/133arraystring.sol | 8 +- .../ok/test/examples/spec/135aliaspush.sol | 8 +- .../ok/test/examples/spec/136arraylit.sol | 6 +- 44 files changed, 531 insertions(+), 368 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol index 80b7bbc5..b4a25395 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/weth9.sol @@ -59,15 +59,15 @@ contract WETH9 { return true; } - public function transfer(dst: address, wad: uint256) -> bool { + function transfer(dst: address, wad: uint256) public returns (bool) { return transferFrom(caller(), dst, wad); } - public function transferFrom(src: address, dst: address, wad: uint256) -> bool { + function transferFrom(src: address, dst: address, wad: uint256) public returns (bool) { let sender = caller(); require(balances[src] >= wad, Error(0xf4d678b8)); // InsufficientBalance() - if (src != sender && allowance[src][sender] != (maxVal():uint256)) { + if (src != sender && allowance[src][sender] != (maxVal())) { require(allowance[src][sender] >= wad, Error(0x13be252b)); // InsufficientAllowance() allowance[src][sender] -= wad; } @@ -77,7 +77,7 @@ contract WETH9 { } // Plain ETH transfers (no calldata, just value) auto-wrap into WETH. - payable fallback() -> () { + fallback() payable { let sender = caller(); balances[sender] = balances[sender] + callvalue(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.sol index c09bb469..efde6dbe 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/all-shapes.sol @@ -1,30 +1,30 @@ -import std.opcodes.{*}; +import * from std.opcodes; // Compilation test for the std/opcodes wrappers. // Picks two opcodes from each of the four shape categories so the // pipeline exercises every wrapper signature. // no inputs, no return -function shape_void_void() -> () { +function shape_void_void() { stop(); invalid(); } // no inputs, returns a word -function shape_void_word() -> word { +function shape_void_word() returns (word) { let a = address(); let t = timestamp(); return a; } // inputs, no return -function shape_word_void(x: word) -> () { +function shape_word_void(x: word) { pop(x); mstore(0, x); } // inputs, returns a word -function shape_word_word(a: word, b: word) -> word { +function shape_word_word(a: word, b: word) returns (word) { let s = add(a, b); let m = mload(0); return s; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.sol index 4c16adfd..59da9fb3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/opcodes/terminators.sol @@ -4,34 +4,34 @@ // type. Regression test for stop/invalid/selfdestruct being made polymorphic // like revert/return (see Primitives.hs 'yulPrimOps'). -forall a.function viaStop() -> a { +function viaStop() returns (a) { assembly { stop() } } -forall a.function viaInvalid() -> a { +function viaInvalid() returns (a) { assembly { invalid() } } -forall a.function viaSelfdestruct(beneficiary: word) -> a { +function viaSelfdestruct(beneficiary: word) returns (a) { assembly { selfdestruct(beneficiary) } } -forall a.function viaRevert() -> a { +function viaRevert() returns (a) { assembly { revert(0, 0) } } -function useWord(w: word) -> () {} +function useWord(w: word) {} contract Terminators { - public function main() -> () { + function main() public { useWord(viaStop()); useWord(viaInvalid()); useWord(viaSelfdestruct(0)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.sol index c412dc91..802699e2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/coverage.sol @@ -1,8 +1,8 @@ pragma no-coverage-condition ; -data List(a) = Nil | Cons(a,List(a)); -data Bool = True | False ; +enum List { Nil, Cons(a, List) } +enum Bool { True, False } -forall a b c . class a : C(b,c) {} +trait C {} -forall a b . instance List(b) : C (a, List(a)) {} +impl C, a, List> {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.sol index f66a88f5..0d59a7a0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/pragmas/patterson.sol @@ -1,16 +1,16 @@ -forall self . class self:A {} -forall self . class self:B {} -forall self . class self:C {} -forall self . class self:D {} +trait A {} +trait B {} +trait C {} +trait D {} -data Uint256 = U; -data T(x) = T; -data S(x) = SCons; +enum Uint256 { U } +enum T { T } +enum S { SCons } // This works. -forall U . U : A => instance T(U):D {} +impl D> where U: A {} // This should also work, but reports a violation of the Paterson condition. -forall U . U : A, U : B, U : C => instance S(U):D {} +impl D> where U: A, U: B, U: C {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol index ba55aa25..48c89978 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/00answer.sol @@ -1,5 +1,5 @@ contract Answer { - public function main() -> word { + function main() public returns (word) { return 42; } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol index 7e286843..9ab26b43 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/01id.sol @@ -1,14 +1,14 @@ contract Id1 { - data Bool = False | True; + enum Bool { False, True } - public function id(x : word) -> word { + function id(x: word) public returns (word) { return x ; } - public function const(x : word, y : Bool) -> word { return x; } + function const(x: word, y: Bool) public returns (word) { return x; } - public function main() -> word { + function main() public returns (word) { return const(id(42), Bool.False); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.sol index df5b9377..aeeb720c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/021not.sol @@ -1,21 +1,29 @@ contract Not { - data Bool = False | True; + enum Bool { False, True } - public function main() -> word { + function main() public returns (word) { return fromBool(bnot(Bool.False)); } - public function fromBool(b : Bool) -> word { - match(b) { - | Bool.False => return 0; - | Bool.True => return 1; - } + function fromBool(b: Bool) public returns (word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } - public function bnot(b : Bool) -> Bool { - match b { - | Bool.False => return Bool.True; - | Bool.True => return Bool.False; - } + function bnot(b: Bool) public returns (Bool) { + match (b) { +case Bool.False { +return Bool.True; +} +case Bool.True { +return Bool.False; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol index 3ef65f35..85258483 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/022add.sol @@ -1,4 +1,4 @@ -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -7,7 +7,7 @@ function add(x : word, y : word) -> word { } contract Add1 { - public function main() -> word { + function main() public returns (word) { return add(40, 2); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol index a79ab49c..4043007d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/024arith.sol @@ -1,6 +1,6 @@ -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -8,7 +8,7 @@ function add(x : word, y : word) -> word { return res; } -function sub(x : word, y : word) -> word { +function sub(x: word, y: word) returns (word) { let res: word; assembly { res := sub(x, y) @@ -16,7 +16,7 @@ function sub(x : word, y : word) -> word { return res; } -function div(x : word, y: word) -> word { +function div(x: word, y: word) returns (word) { let res: word; assembly { res := div(x, y) @@ -24,7 +24,7 @@ function div(x : word, y: word) -> word { return res; } -function sdiv(x : word, y: word) -> word { +function sdiv(x: word, y: word) returns (word) { let res: word; assembly { res := sdiv(x, y) @@ -32,7 +32,7 @@ function sdiv(x : word, y: word) -> word { return res; } -function mod(x : word, y: word) -> word { +function mod(x: word, y: word) returns (word) { let res: word; assembly { res := mod(x, y) @@ -40,7 +40,7 @@ function mod(x : word, y: word) -> word { return res; } -function smod(x : word, y: word) -> word { +function smod(x: word, y: word) returns (word) { let res: word; assembly { res := smod(x, y) @@ -48,7 +48,7 @@ function smod(x : word, y: word) -> word { return res; } -function exp(x : word, y: word) -> word { +function exp(x: word, y: word) returns (word) { let res: word; assembly { res := exp(x, y) @@ -58,7 +58,7 @@ function exp(x : word, y: word) -> word { contract Arith { - public function main() -> word { + function main() public returns (word) { return add(mod(sub(div(exp(2,18),4), 1), 16), 27); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.sol index 166d01e2..320943c0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/02nid.sol @@ -1,15 +1,15 @@ contract Id1 { - public function id(x : word) -> word { + function id(x: word) public returns (word) { return x ; } - public function nid(x : word) -> word { + function nid(x: word) public returns (word) { return id(x); } - public function const(x : word, y : word) -> word { return x; } + function const(x: word, y: word) public returns (word) { return x; } - public function main() -> word { + function main() public returns (word) { return const(nid(42), id(1)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol index d1de1135..379bb9a1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/031maybe.sol @@ -1,16 +1,20 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(0, Option.Some(42)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.sol index 074e2100..303add65 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/032simplejoin.sol @@ -1,35 +1,53 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.None => return Option.None; - | Option.Some(Option.None) => return Option.None; - | Option.Some(Option.Some(x)) => return Option.Some(x); - } + function join(mmx: Option>) public returns (Option) { + match (mmx) { +case Option.None { +return Option.None; +} +case Option.Some(Option.None) { +return Option.None; +} +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +} } - public function join2(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.Some(m) => match m { - | Option.None => return Option.None; - | Option.Some(x) => return Option.Some(x); - } - | _ => return Option.None; - } + function join2(mmx: Option>) public returns (Option) { + match (mmx) { +case Option.Some(m) { +match (m) { +case Option.None { +return Option.None; +} +case Option.Some(x) { +return Option.Some(x); +} +} +} +default { +return Option.None; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(0, join(Option.Some(Option.Some(42)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.sol index d6664528..6d68f60e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/033join.sol @@ -1,23 +1,31 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.Some(Option.Some(x)) => return Option.Some(x); - | _ => return Option.None; - } + function join(mmx: Option>) public returns (Option) { + match (mmx) { +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +default { +return Option.None; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(0, join(Option.Some(Option.Some(42)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.sol index f31954db..3fdd1422 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/034cojoin.sol @@ -1,41 +1,57 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { + function join(mmx: Option>) public returns (Option) { let result = Option.None; - match mmx { - | Option.Some(Option.Some(x)) => result = Option.Some(x); - | Option.None => result = Option.None; - | Option.Some(Option.None) => result = Option.None; - | _ => result = Option.None; - } + match (mmx) { +case Option.Some(Option.Some(x)) { +result = Option.Some(x); +} +case Option.None { +result = Option.None; +} +case Option.Some(Option.None) { +result = Option.None; +} +default { +result = Option.None; +} +} return result; } - public function extract(mx : Option(word)) -> word { - match mx { - | Option.Some(x) => return x; - | Option.None => return 0; - } + function extract(mx: Option) public returns (word) { + match (mx) { +case Option.Some(x) { +return x; +} +case Option.None { +return 0; +} +} } - public function cojoin(x : Option(word)) -> Option(Option(word)) { // Test that sum types can grow + function cojoin(x: Option) public returns (Option>) { // Test that sum types can grow let result = Option.None; result = Option.Some(x); return result; } - public function main() -> word { + function main() public returns (word) { return maybe(0, join(cojoin(Option.Some(42)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.sol index c7b687c9..f6c07c19 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/035padding.sol @@ -1,14 +1,18 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.Some(x) => return x; - | Option.None => return n; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.Some(x) { +return x; +} +case Option.None { +return n; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(7, Option.None); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.sol index 1e83f44f..635bfe52 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/036wildcard.sol @@ -1,14 +1,18 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.Some(x) => return x; - | _ => return n; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.Some(x) { +return x; +} +default { +return n; +} +} } - public function main() -> word { + function main() public returns (word) { return maybe(7, Option.None); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.sol index 94c72529..9e9a3e06 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/037dwarves.sol @@ -1,17 +1,29 @@ contract Dwarves { - data Dwarf = Doc | Grumpy | Sleepy | Bashful | Happy | Sneezy | Dopey; + enum Dwarf { Doc, Grumpy, Sleepy, Bashful, Happy, Sneezy, Dopey } - public function fromEnum(c : Dwarf) -> word { - match c { - | Dwarf.Doc => return 1; - | Dwarf.Grumpy => return 2; - | Dwarf.Sleepy => return 3; - | Dwarf.Bashful => return 4; - | Dwarf.Happy => return 5; - | _ => return 0; - } + function fromEnum(c: Dwarf) public returns (word) { + match (c) { +case Dwarf.Doc { +return 1; +} +case Dwarf.Grumpy { +return 2; +} +case Dwarf.Sleepy { +return 3; +} +case Dwarf.Bashful { +return 4; +} +case Dwarf.Happy { +return 5; +} +default { +return 0; +} +} } - public function main() -> word { return fromEnum(Dwarf.Happy); } + function main() public returns (word) { return fromEnum(Dwarf.Happy); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.sol index 9d7d33a9..867de77c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/038food0.sol @@ -1,23 +1,29 @@ -data Food = Curry | Beans | Other; -data CFood = Red(Food) | Green(Food) | Nocolor; +enum Food { Curry, Beans, Other } +enum CFood { Red(Food), Green(Food), Nocolor } - function fromEnum(x : CFood) -> word { - match x { - | CFood.Red(Food.Curry) => return 1; - | CFood.Green(Food.Beans) => return 42; - | _ => return 3; - } + function fromEnum(x: CFood) returns (word) { + match (x) { +case CFood.Red(Food.Curry) { +return 1; +} +case CFood.Green(Food.Beans) { +return 42; +} +default { +return 3; +} +} } contract FoodContract { - public function id(x : CFood) -> CFood { + function id(x: CFood) public returns (CFood) { return(x); } - public function main() -> word { + function main() public returns (word) { return fromEnum(id(CFood.Green(Food.Beans))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.sol index ef63da67..0d1225a7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/039food.sol @@ -1,29 +1,41 @@ -data Food = Curry | Beans | Other; -data CFood = Red(Food) | Green(Food) | Nocolor; +enum Food { Curry, Beans, Other } +enum CFood { Red(Food), Green(Food), Nocolor } - function fromEnum(x : Food) -> word { - match x { - | Food.Curry => return 1; - | Food.Beans => return 42; - | Food.Other => return 3; - } + function fromEnum(x: Food) returns (word) { + match (x) { +case Food.Curry { +return 1; +} +case Food.Beans { +return 42; +} +case Food.Other { +return 3; +} +} } contract FoodContract { - public function eat(x : CFood) -> Food { - match x { - | CFood.Red(f) => return f; - | CFood.Green(f) => return f; - | _ => return Food.Other; - } + function eat(x: CFood) public returns (Food) { + match (x) { +case CFood.Red(f) { +return f; +} +case CFood.Green(f) { +return f; +} +default { +return Food.Other; +} +} } - public function main() -> word { + function main() public returns (word) { return fromEnum(eat(CFood.Green(Food.Beans))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.sol index b8180a0a..f0f1e963 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/041pair.sol @@ -1,12 +1,14 @@ contract Pair { - public function fst(p : (word, word)) -> word { - match p { - | (a,b) => return a; - } + function fst(p: (word, word)) public returns (word) { + match (p) { +case (a,b) { +return a; +} +} } - public function main() -> word { + function main() public returns (word) { return fst((1,0)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.sol index 10c3724c..d2013eca 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/042triple.sol @@ -1,12 +1,14 @@ contract Triple { - public function asel(t : (word, word, word)) -> word { - match t { - | (a,b,c) => return c; - } + function asel(t: (word, word, word)) public returns (word) { + match (t) { +case (a,b,c) { +return c; +} +} } - public function main() -> word { + function main() public returns (word) { return asel((1,21,42)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.sol index 62db7ccf..ad05b49b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/043fstsnd.sol @@ -1,21 +1,25 @@ -data B = F | T; -data Pair(a,b) = Pair(a,b); +enum B { F, T } +enum Pair { Pair(a, b) } -forall a b . function fst (p : Pair(a, b)) -> a { - match p { - | Pair(x,y) => return x; - } +function fst(p: Pair) returns (a) { + match (p) { +case Pair(x,y) { +return x; +} +} } -forall a b . function snd(p : Pair(a, b)) -> b { - match p { - | Pair(x,y) => return y; - } +function snd(p: Pair) returns (b) { + match (p) { +case Pair(x,y) { +return y; +} +} } -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -24,10 +28,10 @@ function add(x : word, y : word) -> word { } -function addPair(p : Pair(word, word)) -> word { +function addPair(p: Pair) returns (word) { return add(fst(p), snd(p)); } contract FstSnd { - public function main() -> word { return addPair(Pair(41,1)); } + function main() public returns (word) { return addPair(Pair(41,1)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol index 576182e5..87529c81 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol @@ -1,10 +1,16 @@ contract RGB { - data Color = R | G | B; - public function main() -> word { - match Color.B { - | Color.R => return 4; - | Color.G => return 2; - | Color.B => return 42; - } + enum Color { R, G, B } + function main() public returns (word) { + match (Color.B) { +case Color.R { +return 4; +} +case Color.G { +return 2; +} +case Color.B { +return 42; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.sol index 5e33af5d..063a823e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/048rgb2.sol @@ -1,13 +1,19 @@ contract RGB { - data Color = R | G | B; + enum Color { R, G, B } - public function fromEnum(c : Color) -> word { - match c { - | Color.R => return 4; - | Color.G => return 2; - | Color.B => return 42; - } + function fromEnum(c: Color) public returns (word) { + match (c) { +case Color.R { +return 4; +} +case Color.G { +return 2; +} +case Color.B { +return 42; +} +} } - public function main() -> word { return fromEnum(Color.B); } + function main() public returns (word) { return fromEnum(Color.B); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.sol index 8cfbaeca..2a7293b2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/049rgb3.sol @@ -1,17 +1,23 @@ -data RGB = Red(word) | Green(word) | Blue(word); +enum RGB { Red(word), Green(word), Blue(word) } contract RGB3 { - public function choose(c:RGB) -> word { + function choose(c: RGB) public returns (word) { let res : word; - match c { - | .Red(x) => assembly { res := add(x,1) } - | .Green(x) => assembly { res := add(x,2) } - | .Blue(x) => assembly { res := add(x,3) } - } + match (c) { +case .Red(x) { +assembly { res := add(x,1) } +} +case .Green(x) { +assembly { res := add(x,2) } +} +case .Blue(x) { +assembly { res := add(x,3) } +} +} return res; } - public function main() -> word { + function main() public returns (word) { choose(RGB.Green(42)) } } \ No newline at end of file diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol index 301615d7..d0bc6f82 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol @@ -1,9 +1,9 @@ contract Compose { - public function id(x : word) -> word { return x; } + function id(x: word) public returns (word) { return x; } - public function idid(x : word) -> word { return id(id(x)); } + function idid(x: word) public returns (word) { return id(id(x)); } - public function main() -> word { + function main() public returns (word) { return idid(42); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.sol index df5b9377..aeeb720c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/09not.sol @@ -1,21 +1,29 @@ contract Not { - data Bool = False | True; + enum Bool { False, True } - public function main() -> word { + function main() public returns (word) { return fromBool(bnot(Bool.False)); } - public function fromBool(b : Bool) -> word { - match(b) { - | Bool.False => return 0; - | Bool.True => return 1; - } + function fromBool(b: Bool) public returns (word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } - public function bnot(b : Bool) -> Bool { - match b { - | Bool.False => return Bool.True; - | Bool.True => return Bool.False; - } + function bnot(b: Bool) public returns (Bool) { + match (b) { +case Bool.False { +return Bool.True; +} +case Bool.True { +return Bool.False; +} +} } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.sol index af8297a9..cf23be57 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/10negBool.sol @@ -1,29 +1,37 @@ -forall a . class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } contract NegBool { - public function fromB(b : B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) public returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } - public function main() -> word { return fromB(Neg.neg(B.F)); } + function main() public returns (word) { return fromB(Neg.neg(B.F)); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.sol index c18c0272..895624bb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/11negPair.sol @@ -1,53 +1,69 @@ -forall a . class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } -forall a b . function fst (p : (a, b)) -> a { - match p { - | (x,y) => return x; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (x,y) { +return x; +} +} } -forall a b . function snd(p : (a, b)) -> b { - match p { - | (x,y) => return y; - } +function snd(p: (a, b)) returns (b) { + match (p) { +case (x,y) { +return y; +} +} } -forall a b . a : Neg, b : Neg => instance (a,b):Neg { - function neg(p : (a,b)) -> (a,b) { +impl Neg<(a, b)> where a: Neg, b: Neg { + function neg(p: (a, b)) returns (a, b) { return (Neg.neg (fst(p)), Neg.neg(snd (p))); } } contract NegPair { - public function bnot(x : B) -> B { - match x { - | B.T => return B.F; - | B.F => return B.T; - } + function bnot(x: B) public returns (B) { + match (x) { +case B.T { +return B.F; +} +case B.F { +return B.T; +} +} } - public function fromB(b : B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) public returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } - public function main() -> word { return fromB(fst(Neg.neg((B.F,B.T)))); } + function main() public returns (word) { return fromB(fst(Neg.neg((B.F,B.T)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol index 026e1e03..6546c19b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/120basicCounter.sol @@ -1,8 +1,8 @@ -import std.{*}; +import * from std; contract Counter { counter : word; - public function main() -> word { + function main() public returns (word) { counter = Num.add(counter, 42); return counter; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.sol index 2908b6ef..7bb74c2b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/121counter.sol @@ -7,7 +7,7 @@ pragma no-bounded-variable-condition ; contract Counter { counter : word; - public function main() -> word { + function main() public returns (word) { counter = std.addWord(counter, 1); return counter; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.sol index 4b13c41d..d9ae193b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/122counters.sol @@ -1,5 +1,5 @@ // test multiple contract fields -import std.{*}; +import * from std; // import StorageLib; @@ -7,7 +7,7 @@ contract Counter { counter1 : word; counter2 : uint256; counter3 : word; - public function main() -> word { + function main() public returns (word) { counter1 += 1; counter3 += 2; return counter1 + counter3; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.sol index 8da859fa..9009c356 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/123stackAndStorage.sol @@ -1,12 +1,12 @@ // test multiple contract fields -import std.{*}; +import * from std; contract Counter { counter1 : word; counter2 : uint256; counter3 : word; - public function main() -> word { + function main() public returns (word) { let x: word; x = counter1 + 1; counter1 = x; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.sol index 865965a7..b5c06aa9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/126nanoerc20.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.{address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, not}; +import * from std; +import {address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, not} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -12,24 +12,25 @@ function caller() -> address { return address(res); } -function myrevert( msg: (word, word) ) -> () { - match msg { - | (str, len) => - let str1 = str; let len1 = len; +function myrevert(msg: (word, word)) { + match (msg) { +case (str, len) { +let str1 = str; let len1 = len; assembly { mstore(0, str1) revert(0, len1) } - } +} +} } -function myrequire(cond: bool, msg: (word, word) ) -> () { +function myrequire(cond: bool, msg: (word, word)) { if( not(cond) ) { myrevert(msg); } } -function require1(cond: bool) -> () { +function require1(cond: bool) { myrequire (cond, (0x72657175697265313a204641494c, 14) /* "require1: FAIL" */ ); } -function nop() -> () { return ();} +function nop() { return ();} contract Uint { reserved : word; @@ -37,15 +38,15 @@ contract Uint { owner : address; decimals : uint256; totalSupply : uint256; - balances : mapping(address,uint256); + balances : mapping(address => uint256); - public function mint(amount:uint256) -> () { + function mint(amount: uint256) public { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } // function transferFrom(address src, address dst, uint256 amt) public returns (bool) - public function transferFrom(src:address, dst:address, amt:uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) public returns (bool) { require1(ge(balances[src], amt)); /* @@ -58,26 +59,26 @@ contract Uint { } - public function withdraw(src:address, amt:uint256) -> () { - balances[src] = Num.sub(balances[src], amt):uint256; + function withdraw(src: address, amt: uint256) public { + balances[src] = Num.sub(balances[src], amt); } - public function deposit(dst:address, amt:uint256) -> () { - balances[dst] = Num.add(balances[dst], amt):uint256; + function deposit(dst: address, amt: uint256) public { + balances[dst] = Num.add(balances[dst], amt); } - public function init() -> () { + function init() public { owner = address(0x123456789abcdef); msg_sender = caller(); decimals = uint256(18); } - public function main() -> uint256 { + function main() public returns (uint256) { init(); mint(uint256(1000)); let src : address = owner; transferFrom(owner, msg_sender, uint256(42)); - return balances[msg_sender] : uint256; + return balances[msg_sender] ; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.sol index 33920581..5f1380d3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/127microerc20.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.{address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not}; +import * from std; +import {address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -12,7 +12,7 @@ function caller() -> address { return address(res); } -function require1fail() -> () { +function require1fail() { let res: word; assembly { mstore(0x0, 0x72657175697265313a204641494c) // "require1: FAIL" @@ -21,14 +21,18 @@ function require1fail() -> () { return (); // for the typechecker } -function require1(cond: bool) -> () { - match cond { - | false => return require1fail(); - | true => return (); - } +function require1(cond: bool) { + match (cond) { +case false { +return require1fail(); +} +case true { +return (); +} +} } -function nop() -> () { return ();} +function nop() { return ();} contract Mini { reserved : word; @@ -36,10 +40,10 @@ contract Mini { owner : address; decimals : uint256; totalSupply : uint256; - balances : mapping(address,uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); - public function mint(amount:uint256) -> () { + function mint(amount: uint256) public { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } @@ -60,16 +64,24 @@ contract Mini { */ // function transferFrom(src:address, dst:address, amt:uint256) -> bool { - public function transferFrom(src : address, dst : address, amt : uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) public returns (bool) { require1(ge(balances[src], amt)); match (Eq.eq(src, msg_sender)) { - | true => match ne(allowance[src][msg_sender], Num.maxVal():uint256) { - | true => require1(false); - | false => (); - } - | false => (); - } +case true { +match (ne(allowance[src][msg_sender], Num.maxVal())) { +case true { +require1(false); +} +case false { +(); +} +} +} +case false { +(); +} +} /* if ((src != msg_sender) && (allowance [src][msg_sender] != (Num.maxVal():uint256)) ) { @@ -77,7 +89,7 @@ contract Mini { } */ balances[src] = Num.sub(balances[src], amt); - balances[dst] = Num.add(balances[dst], amt):uint256; + balances[dst] = Num.add(balances[dst], amt); return true; } @@ -90,18 +102,18 @@ contract Mini { */ - public function init() -> () { + function init() public { owner = address(0x123456789abcdef); msg_sender = caller(); decimals = uint256(18); } - public function main() -> uint256 { + function main() public returns (uint256) { init(); mint(uint256(1000)); allowance[owner][msg_sender] = uint256(10000); transferFrom(owner, msg_sender, uint256(42)); - return balances[msg_sender] : uint256; + return balances[msg_sender] ; } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.sol index a3c21a15..ad32a7d6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/128minierc20.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.{address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not}; +import * from std; +import {address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -12,11 +12,11 @@ function caller() -> address { return address(res); } -function myrevert(msg: word) -> () { +function myrevert(msg: word) { assembly { mstore(0, msg) revert(0, 32) } } -function myrequire(cond: bool, msg: word ) -> () { +function myrequire(cond: bool, msg: word) { if( !cond ) { myrevert(msg); } } @@ -25,10 +25,10 @@ contract MiniERC20 { owner : address; decimals : uint256; totalSupply : uint256; - balances : mapping(address,uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); - public function mint(amount:uint256) -> () { + function mint(amount: uint256) public { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } @@ -48,13 +48,13 @@ contract MiniERC20 { } */ - public function transferFrom(src:address, dst:address, amt:uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) public returns (bool) { let msg_sender = caller(); myrequire( balances[src] >= amt /* "token/insufficient-balance" */ , 0x746f6b656e2f696e73756666696369656e742d62616c616e6365 ); - if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal():uint256)) { + if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal())) { myrequire( allowance[src][msg_sender] >= amt /* "token/insufficient-allowance" */ , 0x746f6b656e2f696e73756666696369656e742d616c6c6f77616e6365 ); @@ -73,7 +73,7 @@ contract MiniERC20 { } */ - public function approve(usr: address, amt: uint256) -> bool { + function approve(usr: address, amt: uint256) public returns (bool) { let msg_sender = caller(); allowance[msg_sender][usr] = amt; // emit Approval(msg.sender, usr, amt); @@ -81,12 +81,12 @@ contract MiniERC20 { } - public function init() -> () { + function init() public { owner = address(0x123456789abcdef); decimals = uint256(18); // Num.fromWord(18) fails, which may be a problem } - public function main() -> uint256 { + function main() public returns (uint256) { let msg_sender = caller(); init(); mint(uint256(1000)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.sol index 247bd2b2..8b244bcf 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/129arraystorage.sol @@ -1,5 +1,5 @@ // Exercises storage arrays (array(member)) modeled on storage mappings. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -7,10 +7,10 @@ pragma no-bounded-variable-condition ; contract ArrayStorage { reserved : word; // forge uses at least 1 storage slot - function main() -> uint256 { + function main() returns (uint256) { // A storage array sitting at a fixed slot. The slot itself stores the // length; elements live at keccak256(slot) + i. - let arr : storage(array(uint256)) = storage(0x100); + let arr : storage> = storage(0x100); // push appends and grows the length automatically. ArrayPush.push(arr, uint256(42)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.sol index 2a8f27e2..e02f5113 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/130arrayfield.sol @@ -1,14 +1,14 @@ // Storage array as a contract field: `arr : array(uint256)`. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract ArrayField { reserved : word; // forge uses at least 1 storage slot - arr : array(uint256); + arr : array; - function main() -> uint256 { + function main() returns (uint256) { // push appends and grows the length automatically. ArrayPush.push(arr, uint256(42)); ArrayPush.push(arr, uint256(100)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.sol index 98122c2e..6c75fedb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/131localindex.sol @@ -1,8 +1,8 @@ // `arr[i]` on a *local* storage-array reference, not a contract field. // The local already holds the storage reference, so the desugaring emits -// `ridx(arr, i)` / `lidx(arr, i)` directly (cf. 129arraystorage.solc, which +// `ridx(arr, i)` / `lidx(arr, i)` directly (cf. 129arraystorage.sol, which // had to spell out `ridx` by hand). -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -10,8 +10,8 @@ pragma no-bounded-variable-condition ; contract LocalIndex { reserved : word; // forge uses at least 1 storage slot - function main() -> uint256 { - let arr : storage(array(uint256)) = storage(0x100); + function main() returns (uint256) { + let arr : storage> = storage(0x100); ArrayPush.push(arr, uint256(42)); ArrayPush.push(arr, uint256(100)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.sol index 04abe1be..be7b0ca4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/132nestedarray.sol @@ -1,16 +1,16 @@ // Nested storage arrays: `array(array(uint256))` with `grid[i][j]` used as both // an l-value and an r-value. The inner index desugars as an l-value, yielding the // `storage(array(uint256))` handle that the outer index then consumes. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract NestedArray { reserved : word; // forge uses at least 1 storage slot - grid : array(array(uint256)); + grid : array>; - function main() -> uint256 { + function main() returns (uint256) { // Grow the outer array; the inner arrays start empty. Array.setLength(grid, uint256(2)); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.sol index d801d42f..34163a6a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/133arraystring.sol @@ -1,17 +1,17 @@ // Storage arrays whose element type is dynamic. Declaring the field and taking // its length must work even before `push` accepts dynamic values; the element // slot itself is what holds the length / short-string encoding. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract ArrayOfDynamic { reserved : word; // forge uses at least 1 storage slot - names : array(string); - blobs : array(bytes); + names : array; + blobs : array; - function main() -> uint256 { + function main() returns (uint256) { return Length.length(names) + Length.length(blobs); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.sol index 583efec3..df68cc49 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/135aliaspush.sol @@ -1,16 +1,16 @@ // Binding a storage array field to a local is an *alias*, not a copy: the local // holds the same slot, so growing it grows the field. (Solidity's `T[] storage p`.) -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract AliasPush { reserved : word; // forge uses at least 1 storage slot - xs : array(uint256); + xs : array; - function main() -> uint256 { - let p : storage(array(uint256)) = xs; + function main() returns (uint256) { + let p : storage> = xs; ArrayPush.push(p, uint256(1)); // The push went through the alias, so the field sees it. return Length.length(xs); diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.sol index dee3b4d8..bf236e28 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/136arraylit.sol @@ -1,13 +1,13 @@ // Array literal in memory: `[1,2,3]` builds a memory(DynArray(t)), whose // elements are then readable through `m[i]`. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract ArrayLit { - function main() -> uint256 { - let m : memory(DynArray(uint256)) = [1, 2, 3]; + function main() returns (uint256) { + let m : memory> = [1, 2, 3]; return m[uint256(0)] + m[uint256(2)]; } } From 61b74184e831e8954a014a0d7d2079d740cfd1ee Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 075/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test examples Co-authored-by: Codex --- .../test/examples/spec/137arraylitstorage.sol | 6 +-- .../ok/test/examples/spec/903badassign.sol | 42 ++++++++++++------- .../ok/test/examples/spec/939badfood.sol | 28 ++++++++----- .../ok/test/examples/spec/SimpleField.sol | 6 +-- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.sol index fec9f721..5cfe6fcb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/137arraylitstorage.sol @@ -1,15 +1,15 @@ // Assigning an array literal to a storage array field is Solidity's // memory -> storage copy: it resizes the field and clears any abandoned tail. -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; contract ArrayLitStorage { reserved : word; // forge uses at least 1 storage slot - xs : array(uint256); + xs : array; - function main() -> uint256 { + function main() returns (uint256) { xs = [10, 20, 30]; return xs[uint256(0)] + xs[uint256(2)]; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.sol index d3efe69b..9275c605 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/903badassign.sol @@ -1,27 +1,39 @@ contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - public function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) public returns (Option) { return Option.Some(x); } - public function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) public returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - public function join(mmx : Option(Option(word))) -> Option(word) { + function join(mmx: Option>) public returns (Option) { let result = Option.None; - match mmx { - | Option.Some(Option.Some(x)) => result = Option.Some(x); - | Option.None => result = Option.None; - | Option.Some(Option.None) => result = Option.None; - | _ => result = Option.None; - } + match (mmx) { +case Option.Some(Option.Some(x)) { +result = Option.Some(x); +} +case Option.None { +result = Option.None; +} +case Option.Some(Option.None) { +result = Option.None; +} +default { +result = Option.None; +} +} return result; } - public function main() -> word { + function main() public returns (word) { return maybe(0, join(Option.Some(Option.Some(42)))); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.sol index eb81d6b1..c7e91ccf 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/939badfood.sol @@ -1,21 +1,27 @@ -forall a . class a: Enum { - function fromEnum(x : a) -> word; +trait Enum { + function fromEnum(x: a) returns (word) ; } -data Food = Curry | Beans | Other; +enum Food { Curry, Beans, Other } -instance Food : Enum { - function fromEnum(x : Food) -> word { - match x { - | Food.Curry => return 1; - | Food.Beans => return 2; - | Food.Other => return 3; - } +impl Enum { + function fromEnum(x: Food) returns (word) { + match (x) { +case Food.Curry { +return 1; +} +case Food.Beans { +return 2; +} +case Food.Other { +return 3; +} +} } } contract FoodContract { - public function main() -> word { + function main() public returns (word) { return Enum.fromEnum(Food.Beans); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.sol b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.sol index 3aa1d3e4..2392e447 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/examples/spec/SimpleField.sol @@ -1,4 +1,4 @@ -import std.{*}; +import * from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -6,11 +6,11 @@ pragma no-bounded-variable-condition ; contract Simple { myval : word ; - public function getVal () -> word { + function getVal() public returns (word) { return myval ; } - public function main () -> word { + function main() public returns (word) { return getVal(); } } From 5a8d58e0a534e1fd7aa1a9d05e2fe87044646715 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 076/110] Switch the compiler and fixtures to canonical syntax: parser corpus ok test imports Co-authored-by: Codex --- .../corpus/ok/test/imports/alias_dup.sol | 6 ++--- .../imports/alias_hides_original_fail.sol | 4 +-- .../imports/alias_unqualified_constr_fail.sol | 4 +-- .../imports/alias_unqualified_fun_fail.sol | 4 +-- .../imports/alias_unqualified_type_fail.sol | 4 +-- .../fixtures/corpus/ok/test/imports/ambA.sol | 2 +- .../fixtures/corpus/ok/test/imports/ambB.sol | 2 +- .../corpus/ok/test/imports/amb_main.sol | 6 ++--- .../corpus/ok/test/imports/amb_ok.sol | 2 +- .../corpus/ok/test/imports/boolalias.sol | 4 +-- .../ok/test/imports/boolalias_open_fail.sol | 4 +-- .../corpus/ok/test/imports/boolaliastype.sol | 4 +-- .../ok/test/imports/boolconselect_fail.sol | 4 +-- .../ok/test/imports/boolconselect_ok.sol | 4 +-- .../corpus/ok/test/imports/booldef.sol | 26 +++++++++++-------- .../corpus/ok/test/imports/boolmain.sol | 2 +- .../corpus/ok/test/imports/boolqualified.sol | 2 +- .../ok/test/imports/boolqualifiedtype.sol | 2 +- .../corpus/ok/test/imports/boolselect.sol | 4 +-- .../corpus/ok/test/imports/cycleA.sol | 2 +- .../corpus/ok/test/imports/cycleB.sol | 2 +- .../corpus/ok/test/imports/cycle_main.sol | 2 +- .../ok/test/imports/dot_context_expr.sol | 16 +++++++----- .../corpus/ok/test/imports/dot_left.sol | 2 +- .../corpus/ok/test/imports/dot_right.sol | 2 +- .../corpus/ok/test/imports/dupqual_a.sol | 2 +- .../corpus/ok/test/imports/dupqual_b.sol | 2 +- .../corpus/ok/test/imports/dupqual_main.sol | 6 ++--- .../ok/test/imports/dupqual_module_main.sol | 2 +- .../ok/test/imports/export_item_dup_fail.sol | 2 +- .../test/imports/export_module_dup_fail.sol | 2 +- .../test/imports/external_lib_alias_main.sol | 4 +-- .../ok/test/imports/external_lib_main.sol | 2 +- .../ok/test/imports/extlib/math/api.sol | 2 +- .../imports/extlib/math/internals/add.sol | 4 +-- .../corpus/ok/test/imports/extlib/util.sol | 2 +- .../fixtures/corpus/ok/test/imports/foo.sol | 2 +- .../corpus/ok/test/imports/foo/bar.sol | 2 +- .../corpus/ok/test/imports/foo/bar/baz.sol | 2 +- .../corpus/ok/test/imports/glob_amb_a.sol | 2 +- .../corpus/ok/test/imports/glob_amb_b.sol | 2 +- .../ok/test/imports/glob_amb_main_fail.sol | 6 ++--- .../ok/test/imports/glob_export_mixed.sol | 2 +- .../ok/test/imports/glob_hiding_amb_ok.sol | 6 ++--- .../ok/test/imports/glob_import_dup.sol | 4 +-- .../ok/test/imports/glob_import_hiding.sol | 12 +++++---- .../glob_import_hiding_unknown_fail.sol | 4 +-- .../ok/test/imports/glob_import_mixed.sol | 4 +-- .../corpus/ok/test/imports/glob_import_ok.sol | 12 +++++---- .../corpus/ok/test/imports/globlib.sol | 6 ++--- .../ok/test/imports/hidden_ctor_dot_fail.sol | 4 +-- .../ok/test/imports/hidden_ctor_expr_fail.sol | 4 +-- .../ok/test/imports/hidden_ctor_lib.sol | 6 ++--- .../hidden_ctor_nonexhaustive_fail.sol | 12 +++++---- .../test/imports/hidden_ctor_pattern_fail.sol | 16 +++++++----- .../test/imports/hidden_ctor_wildcard_ok.sol | 16 +++++++----- .../ok/test/imports/import_std_minimal.sol | 2 +- .../corpus/ok/test/imports/leak_a.sol | 2 +- .../corpus/ok/test/imports/leak_b.sol | 2 +- .../corpus/ok/test/imports/leak_main.sol | 2 +- .../corpus/ok/test/imports/mirror/helper.sol | 2 +- .../ok/test/imports/module_name_shadow.sol | 6 ++--- .../imports/module_qualified_constructor.sol | 2 +- .../module_qualified_constructor_alias.sol | 4 +-- .../module_qualified_constructor_pattern.sol | 14 ++++++---- .../module_unqualified_constr_fail.sol | 2 +- .../imports/module_unqualified_fun_fail.sol | 2 +- .../imports/module_unqualified_type_fail.sol | 2 +- .../corpus/ok/test/imports/nested_alias.sol | 4 +-- .../ok/test/imports/nested_deep_qualifier.sol | 2 +- .../test/imports/nested_direct_qualifier.sol | 2 +- .../ok/test/imports/nested_foo_and_bar.sol | 4 +-- .../corpus/ok/test/imports/nested_select.sol | 4 +-- .../corpus/ok/test/imports/ns_constr_dup.sol | 6 ++--- .../corpus/ok/test/imports/ns_cross_ok.sol | 4 +-- .../test/imports/opaque_alias_leak_fail.sol | 4 +-- .../ok/test/imports/opaque_alias_main.sol | 4 +-- .../ok/test/imports/opaque_alias_mid.sol | 4 +-- .../opaque_alias_qualifier_leak_fail.sol | 4 +-- .../ok/test/imports/opaque_dep_base.sol | 4 +-- .../test/imports/opaque_select_alias_main.sol | 4 +-- .../test/imports/opaque_select_alias_mid.sol | 4 +-- .../opaque_select_direct_leak_fail.sol | 4 +-- .../test/imports/opaque_select_direct_mid.sol | 4 +-- .../ok/test/imports/pragma_scope_lib.sol | 2 +- .../ok/test/imports/pragma_scope_main.sol | 6 ++--- .../ok/test/imports/private_bad_lib.sol | 4 +-- .../ok/test/imports/private_bad_main.sol | 2 +- .../ok/test/imports/private_helper_a.sol | 4 +-- .../ok/test/imports/private_helper_main.sol | 2 +- .../reexport_ctor_expr_hidden_fail.sol | 2 +- .../ok/test/imports/reexport_ctor_expr_ok.sol | 2 +- .../ok/test/imports/reexport_ctor_pattern.sol | 14 ++++++---- .../test/imports/reexport_items/pkg/util.sol | 20 +++++++------- .../ok/test/imports/reexport_items_main.sol | 4 +-- .../test/imports/reexport_module/pkg/util.sol | 20 +++++++------- .../imports/reexport_module_alias_main.sol | 2 +- .../ok/test/imports/reexport_module_main.sol | 2 +- .../imports/reexport_select_alias_main.sol | 4 +-- .../imports/reexport_select_alias_wrapper.sol | 2 +- .../ok/test/imports/reexport_select_base.sol | 2 +- .../ok/test/imports/reexport_select_main.sol | 4 +-- .../test/imports/reexport_select_wrapper.sol | 2 +- .../ok/test/imports/rootcheck/nested/main.sol | 2 +- .../imports/rootcheck/nested/provider.sol | 2 +- .../nested/relative_and_lib_main.sol | 4 +-- .../ok/test/imports/rootcheck/provider.sol | 2 +- .../ok/test/imports/select_alias_item_ok.sol | 4 +-- .../ok/test/imports/select_alias_multi_ok.sol | 4 +-- .../ok/test/imports/select_dup_item.sol | 4 +-- .../corpus/ok/test/imports/select_fail.sol | 4 +-- .../ok/test/imports/select_hiding_fail.sol | 4 +-- .../ok/test/imports/select_hiding_ok.sol | 4 +-- .../corpus/ok/test/imports/select_ok.sol | 4 +-- .../ok/test/imports/select_shadow_local.sol | 6 ++--- .../test/imports/select_shadow_param_ok.sol | 4 +-- .../corpus/ok/test/imports/select_unknown.sol | 4 +-- .../imports/selective_unqualified_fun_ok.sol | 4 +-- .../corpus/ok/test/imports/selectlib.sol | 4 +-- .../corpus/ok/test/imports/selfcycle.sol | 2 +- .../ok/test/imports/strict_open_fail.sol | 2 +- .../ok/test/imports/symlink_identity_fail.sol | 6 ++--- .../ok/test/imports/transitive_dep_base.sol | 2 +- .../imports/transitive_dep_main_module.sol | 4 +-- .../imports/transitive_dep_main_select.sol | 4 +-- .../ok/test/imports/transitive_dep_mid.sol | 4 +-- .../ok/test/imports/type_collision_a.sol | 4 +-- .../ok/test/imports/type_collision_b.sol | 4 +-- .../ok/test/imports/type_collision_main.sol | 2 +- .../ok/test/imports/unordered_imports_lib.sol | 16 +++++++----- .../test/imports/unordered_imports_main.sol | 2 +- .../ok/test/imports/vendor/math/helper.sol | 2 +- .../fixtures/corpus/ok/test/imports/wildA.sol | 2 +- .../fixtures/corpus/ok/test/imports/wildB.sol | 2 +- .../corpus/ok/test/imports/wild_main.sol | 2 +- .../test/imports/wrapper_shadow_success.sol | 4 +-- 136 files changed, 318 insertions(+), 280 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.sol index f30b5a80..7eadac1d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_dup.sol @@ -1,6 +1,6 @@ -import ambA as M; -import ambB as M; +import * as M from ambA; +import * as M from ambB; -function main(x: word) -> word { +function main(x: word) returns (word) { return M.pick(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.sol index f3cc209b..5defac0d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_hides_original_fail.sol @@ -1,5 +1,5 @@ -import foo.bar as FB; +import * as FB from foo.bar; -function main() -> word { +function main() returns (word) { return foo.bar.value(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.sol index 1d03c05a..1128347d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_constr_fail.sol @@ -1,5 +1,5 @@ -import booldef as B; +import * as B from booldef; -function mkTrue() -> B.Bool { +function mkTrue() returns (B.Bool) { return True; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.sol index 58389b0e..41b8d3ba 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_fun_fail.sol @@ -1,5 +1,5 @@ -import foo as F; +import * as F from foo; -function main() -> word { +function main() returns (word) { return base(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.sol index 2105a670..04f7a96d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/alias_unqualified_type_fail.sol @@ -1,5 +1,5 @@ -import booldef as B; +import * as B from booldef; -function idBool(b: Bool) -> Bool { +function idBool(b: Bool) returns (Bool) { return b; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.sol index ce94f824..f3adceb8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/ambA.sol @@ -1,5 +1,5 @@ export { pick }; -function pick(x: word) -> word { +function pick(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.sol index ce94f824..f3adceb8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/ambB.sol @@ -1,5 +1,5 @@ export { pick }; -function pick(x: word) -> word { +function pick(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.sol index d20d1d42..c0e3d961 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_main.sol @@ -1,6 +1,6 @@ -import ambA.{pick}; -import ambB.{pick}; +import {pick} from ambA; +import {pick} from ambB; -function main(x: word) -> word { +function main(x: word) returns (word) { return pick(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.sol index 5ae3f26c..638e9d0b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/amb_ok.sol @@ -1,6 +1,6 @@ import ambA; import ambB; -function main(x: word) -> word { +function main(x: word) returns (word) { return ambA.pick(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.sol index fa094354..03a32680 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias.sol @@ -1,5 +1,5 @@ -import booldef as B; +import * as B from booldef; -function fromAlias(b: B.Bool) -> B.Bool { +function fromAlias(b: B.Bool) returns (B.Bool) { return B.not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.sol index ea50f8dd..69d5ce7a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolalias_open_fail.sol @@ -1,5 +1,5 @@ -import booldef as B; +import * as B from booldef; -function bad(b: Bool) -> Bool { +function bad(b: Bool) returns (Bool) { return not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.sol index bcf3e554..778718cf 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolaliastype.sol @@ -1,5 +1,5 @@ -import booldef as B; +import * as B from booldef; -function fromAliasType(b: B.Bool) -> B.Bool { +function fromAliasType(b: B.Bool) returns (B.Bool) { return B.not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.sol index f4143bbc..915aaf30 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_fail.sol @@ -1,5 +1,5 @@ -import booldef.{Bool}; +import {Bool} from booldef; -function mkTrue() -> Bool { +function mkTrue() returns (Bool) { return True; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.sol index 5b719037..2fbfea96 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolconselect_ok.sol @@ -1,5 +1,5 @@ -import booldef.{Bool}; +import {Bool} from booldef; -function mkTrue() -> Bool { +function mkTrue() returns (Bool) { return Bool.True; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.sol index 639d21eb..0013b368 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/booldef.sol @@ -1,22 +1,26 @@ export { Bool(*), not, C, D, id }; -data Bool = True | False; +enum Bool { True, False } -function not (b : Bool) -> Bool { - match b { - | Bool.True => return Bool.False; - | Bool.False => return Bool.True; - } +function not(b: Bool) returns (Bool) { + match (b) { +case Bool.True { +return Bool.False; +} +case Bool.False { +return Bool.True; +} +} } -forall a . class a : C { - function c (x : a, y : a) -> word ; +trait C { + function c(x: a, y: a) returns (word) ; } -forall a . class a : D { - function d() -> a ; +trait D { + function d() returns (a) ; } -forall a . a : C, a : D => function id (x : a) -> word { +function id(x: a) returns (word) where a: C, a: D { return C.c(x, D.d()); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.sol index a50de30f..d6b08815 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolmain.sol @@ -1,5 +1,5 @@ import booldef; -function and(b1: booldef.Bool, b2: booldef.Bool) -> booldef.Bool { +function and(b1: booldef.Bool, b2: booldef.Bool) returns (booldef.Bool) { return b1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.sol index 01bf3a3e..4ffcf72f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualified.sol @@ -1,5 +1,5 @@ import booldef; -function fromQualified(b: booldef.Bool) -> booldef.Bool { +function fromQualified(b: booldef.Bool) returns (booldef.Bool) { return booldef.not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.sol index 0b4d2b3c..5892f3cd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolqualifiedtype.sol @@ -1,5 +1,5 @@ import booldef; -function fromQualifiedType(b: booldef.Bool) -> booldef.Bool { +function fromQualifiedType(b: booldef.Bool) returns (booldef.Bool) { return booldef.not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.sol index 1041fc71..bc70b013 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/boolselect.sol @@ -1,5 +1,5 @@ -import booldef.{Bool, not}; +import {Bool, not} from booldef; -function fromSelect(b: Bool) -> Bool { +function fromSelect(b: Bool) returns (Bool) { return not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.sol index 1ce73fd6..30bca38e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleA.sol @@ -2,6 +2,6 @@ import cycleB; export { fromCycleA }; export cycleB.{fromCycleB}; -function fromCycleA() -> word { +function fromCycleA() returns (word) { return cycleB.fromCycleB(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.sol index 71fb1cf5..07d18774 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycleB.sol @@ -2,6 +2,6 @@ import cycleA; export { fromCycleB }; export cycleA.{fromCycleA}; -function fromCycleB() -> word { +function fromCycleB() returns (word) { return 2; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.sol index 77d87240..e8784d8a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/cycle_main.sol @@ -1,5 +1,5 @@ import cycleA; -function main() -> word { +function main() returns (word) { return cycleA.fromCycleB(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.sol index 02be5db6..28cd4f5d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_context_expr.sol @@ -1,14 +1,18 @@ import dot_left; import dot_right; -function mkLeft() -> dot_left.LeftOpt { +function mkLeft() returns (dot_left.LeftOpt) { let x: dot_left.LeftOpt = .Some(1); return x; } -function main() -> word { - match mkLeft() { - | .Some(v) => return v; - | .None => return 0; - } +function main() returns (word) { + match (mkLeft()) { +case .Some(v) { +return v; +} +case .None { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.sol index 5511a1c6..30203ed9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_left.sol @@ -1,3 +1,3 @@ export { LeftOpt(*) }; -data LeftOpt = None | Some(word); +enum LeftOpt { None, Some(word) } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.sol index 82f8f8af..8cc9becd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dot_right.sol @@ -1,3 +1,3 @@ export { RightOpt(*) }; -data RightOpt = None | Some(word); +enum RightOpt { None, Some(word) } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.sol index ed7f99ed..61eae222 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_a.sol @@ -1,5 +1,5 @@ export { foo }; -function foo(x: word) -> word { +function foo(x: word) returns (word) { return 1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.sol index 7ee6a4e5..87b4d50d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_b.sol @@ -1,5 +1,5 @@ export { foo }; -function foo(x: word) -> word { +function foo(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.sol index cbe4de15..e957ae83 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_main.sol @@ -1,7 +1,7 @@ -import dupqual_a as m1; -import dupqual_b as m2; +import * as m1 from dupqual_a; +import * as m2 from dupqual_b; -function main(x: word) -> word { +function main(x: word) returns (word) { let y = m1.foo(x); return m2.foo(y); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.sol index 5ef0d8eb..6a887247 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/dupqual_module_main.sol @@ -1,7 +1,7 @@ import dupqual_a; import dupqual_b; -function main(x: word) -> word { +function main(x: word) returns (word) { let y = dupqual_a.foo(x); return dupqual_b.foo(y); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.sol index 8d7a33f1..d6d7abb8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/export_item_dup_fail.sol @@ -1,6 +1,6 @@ export ambA.{pick}; export ambB.{pick}; -function main(x: word) -> word { +function main(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.sol index 118a875c..95cbdc5a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/export_module_dup_fail.sol @@ -1,6 +1,6 @@ export foo as M; export booldef as M; -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.sol index 7853c68c..7bc7882a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_alias_main.sol @@ -1,5 +1,5 @@ -import @extlib.math.api as MathApi; +import * as MathApi from @extlib.math.api; -function main() -> word { +function main() returns (word) { return MathApi.sum(39); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.sol index 5ffd122d..12bb126a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/external_lib_main.sol @@ -3,7 +3,7 @@ import @extlib.math.api; contract External { constructor() {} - public function main() -> word { + function main() public returns (word) { return math.api.sum(39); } } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.sol index 43dc18f7..3ff33e31 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/api.sol @@ -3,6 +3,6 @@ import lib.util; export {sum}; -function sum(x: word) -> word { +function sum(x: word) returns (word) { return add.inc(x) + util.offset(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.sol index 06449de7..dd5b16fd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/math/internals/add.sol @@ -1,7 +1,7 @@ -import std.{Add}; +import {Add} from std; export {inc}; -function inc(x: word) -> word { +function inc(x: word) returns (word) { return x + 1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.sol index 21a00682..de93f722 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/extlib/util.sol @@ -1,5 +1,5 @@ export {offset}; -function offset() -> word { +function offset() returns (word) { return 2; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo.sol index ca17ac81..ebef1581 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo.sol @@ -1,5 +1,5 @@ export { base }; -function base() -> word { +function base() returns (word) { return 3; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.sol index 4f2e503d..b0daa7d9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar.sol @@ -1,5 +1,5 @@ export { value }; -function value() -> word { +function value() returns (word) { return 7; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.sol index 73dd9ef1..aa7fac4b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/foo/bar/baz.sol @@ -1,5 +1,5 @@ export { deep }; -function deep() -> word { +function deep() returns (word) { return 9; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.sol index ccd8ec04..6970ebc0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_a.sol @@ -1,5 +1,5 @@ export {*}; -function shared(x: word) -> word { +function shared(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.sol index ccd8ec04..6970ebc0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_b.sol @@ -1,5 +1,5 @@ export {*}; -function shared(x: word) -> word { +function shared(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.sol index 168a2d20..5cb529f4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_amb_main_fail.sol @@ -1,6 +1,6 @@ -import glob_amb_a.{*}; -import glob_amb_b.{*}; +import * from glob_amb_a; +import * from glob_amb_b; -function main(x: word) -> word { +function main(x: word) returns (word) { return shared(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.sol index 0bed5cdc..28313d8b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_export_mixed.sol @@ -1,5 +1,5 @@ export {*, main}; -function main(x: word) -> word { +function main(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.sol index 89bb50ab..8f3eae7f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_hiding_amb_ok.sol @@ -1,6 +1,6 @@ -import glob_amb_a.{*} hiding {shared}; -import glob_amb_b.{*}; +import * from glob_amb_a hiding {shared}; +import * from glob_amb_b; -function main(x: word) -> word { +function main(x: word) returns (word) { return shared(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.sol index 100a698c..e94313b7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_dup.sol @@ -1,5 +1,5 @@ -import globlib.{*, *}; +import * from globlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.sol index 385dff72..b13b196f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding.sol @@ -1,8 +1,10 @@ -import globlib.{*} hiding {idWord}; +import * from globlib hiding {idWord}; -function main(x: word) -> word { +function main(x: word) returns (word) { let y: T = mkT(x); - match y { - | T.T(v) => return v; - } + match (y) { +case T.T(v) { +return v; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.sol index 7877da11..4c09071f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_hiding_unknown_fail.sol @@ -1,5 +1,5 @@ -import globlib.{*} hiding {missing}; +import * from globlib hiding {missing}; -function main(x: word) -> word { +function main(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.sol index aabb81aa..93f6f6f1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_mixed.sol @@ -1,5 +1,5 @@ -import globlib.{*, idWord}; +import * from globlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return idWord(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.sol index e87a4f80..61703a55 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/glob_import_ok.sol @@ -1,8 +1,10 @@ -import globlib.{*}; +import * from globlib; -function main(x: word) -> word { +function main(x: word) returns (word) { let y: T = mkT(x); - match y { - | T.T(v) => return idWord(v); - } + match (y) { +case T.T(v) { +return idWord(v); +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.sol index d433e74d..431b3dd2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/globlib.sol @@ -1,11 +1,11 @@ export {*, T(*)}; -data T = T(word); +enum T { T(word) } -function idWord(x: word) -> word { +function idWord(x: word) returns (word) { return x; } -function mkT(x: word) -> T { +function mkT(x: word) returns (T) { return T.T(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.sol index e6e2a41d..286cd96b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_dot_fail.sol @@ -1,5 +1,5 @@ -import hidden_ctor_lib.{Token}; +import {Token} from hidden_ctor_lib; -function main() -> Token { +function main() returns (Token) { return .Err(1); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.sol index 1515e1f7..c2df2197 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_expr_fail.sol @@ -1,5 +1,5 @@ -import hidden_ctor_lib.{Token}; +import {Token} from hidden_ctor_lib; -function main() -> Token { +function main() returns (Token) { return Token.Err(0); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.sol index 4ecb42b8..038b849d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_lib.sol @@ -1,11 +1,11 @@ export {Token(Ok), mkOk, mkErr}; -data Token = Ok(word) | Err(word); +enum Token { Ok(word), Err(word) } -function mkOk(x: word) -> Token { +function mkOk(x: word) returns (Token) { return Token.Ok(x); } -function mkErr(x: word) -> Token { +function mkErr(x: word) returns (Token) { return Token.Err(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.sol index d13d0167..6a0e9cda 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_nonexhaustive_fail.sol @@ -1,7 +1,9 @@ -import hidden_ctor_lib.{Token, mkOk}; +import {Token, mkOk} from hidden_ctor_lib; -function main() -> word { - match mkOk(1) { - | Token.Ok(v) => return v; - } +function main() returns (word) { + match (mkOk(1)) { +case Token.Ok(v) { +return v; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.sol index 3637f613..3865c58b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_pattern_fail.sol @@ -1,8 +1,12 @@ -import hidden_ctor_lib.{Token, mkErr}; +import {Token, mkErr} from hidden_ctor_lib; -function main() -> word { - match mkErr(1) { - | Token.Err(v) => return v; - | _ => return 0; - } +function main() returns (word) { + match (mkErr(1)) { +case Token.Err(v) { +return v; +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.sol index 25f93ee3..221d066a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/hidden_ctor_wildcard_ok.sol @@ -1,8 +1,12 @@ -import hidden_ctor_lib.{Token, mkErr}; +import {Token, mkErr} from hidden_ctor_lib; -function main() -> word { - match mkErr(1) { - | Token.Ok(v) => return v; - | _ => return 0; - } +function main() returns (word) { + match (mkErr(1)) { +case Token.Ok(v) { +return v; +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.sol index f54d9a7f..697fbd82 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/import_std_minimal.sol @@ -1,3 +1,3 @@ import std; -function main() -> () {} +function main() {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.sol index 560e4fbf..982d6b27 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_a.sol @@ -1,5 +1,5 @@ export { fromA }; -function fromA() -> word { +function fromA() returns (word) { return 1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.sol index 198768b2..3b997491 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_b.sol @@ -1,5 +1,5 @@ export { fromB }; -function fromB() -> word { +function fromB() returns (word) { return fromA(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.sol index 7a52277c..3efbc01b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/leak_main.sol @@ -1,6 +1,6 @@ import leak_a; import leak_b; -function main() -> word { +function main() returns (word) { return fromB(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.sol index d2d38ce7..f03838e7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/mirror/helper.sol @@ -1,3 +1,3 @@ export {T}; -data T = T; +enum T { T } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.sol index a22bc04b..303ec7db 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_name_shadow.sol @@ -1,9 +1,9 @@ -import foo as keep; +import * as keep from foo; -function keep() -> word { +function keep() returns (word) { return 1; } -function main() -> word { +function main() returns (word) { return keep(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.sol index 7f3d8640..f02f35ca 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor.sol @@ -1,5 +1,5 @@ import booldef; -function mk() -> booldef.Bool { +function mk() returns (booldef.Bool) { return booldef.Bool.True; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.sol index f3896448..83b06e50 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_alias.sol @@ -1,5 +1,5 @@ -import booldef as b; +import * as b from booldef; -function mk() -> b.Bool { +function mk() returns (b.Bool) { return b.Bool.True; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.sol index 84fb72dd..ca54b396 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_qualified_constructor_pattern.sol @@ -1,8 +1,12 @@ import booldef; -function main(x: booldef.Bool) -> word { - match x { - | booldef.Bool.True => return 1; - | _ => return 0; - } +function main(x: booldef.Bool) returns (word) { + match (x) { +case booldef.Bool.True { +return 1; +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.sol index cc250ccf..9e0d64d2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_constr_fail.sol @@ -1,5 +1,5 @@ import booldef; -function mkTrue() -> booldef.Bool { +function mkTrue() returns (booldef.Bool) { return True; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.sol index 9a4b3611..ff8ddb46 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_fun_fail.sol @@ -1,5 +1,5 @@ import foo; -function main() -> word { +function main() returns (word) { return base(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.sol index f8ddc777..0cd983cb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/module_unqualified_type_fail.sol @@ -1,5 +1,5 @@ import booldef; -function idBool(b: Bool) -> Bool { +function idBool(b: Bool) returns (Bool) { return b; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.sol index 0e8f0059..1e207504 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_alias.sol @@ -1,5 +1,5 @@ -import foo.bar as FB; +import * as FB from foo.bar; -function main() -> word { +function main() returns (word) { return FB.value(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.sol index 8c8d43b7..49770daa 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_deep_qualifier.sol @@ -1,5 +1,5 @@ import foo.bar.baz; -function main() -> word { +function main() returns (word) { return foo.bar.baz.deep(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.sol index 8d1b89fd..81a902b0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_direct_qualifier.sol @@ -1,5 +1,5 @@ import foo.bar; -function main() -> word { +function main() returns (word) { return foo.bar.value(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.sol index abe3fe99..72b98647 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_foo_and_bar.sol @@ -1,7 +1,7 @@ import foo; -import foo.bar as Bar; +import * as Bar from foo.bar; -function main() -> word { +function main() returns (word) { let x: word = foo.base(); let y: word = Bar.value(); return y; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.sol index 62047c36..b90ecff1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/nested_select.sol @@ -1,5 +1,5 @@ -import foo.bar.{value}; +import {value} from foo.bar; -function main() -> word { +function main() returns (word) { return value(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.sol index 8dbef8db..6099075c 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_constr_dup.sol @@ -1,6 +1,6 @@ -data Foo = Same; -data Bar = Same; +enum Foo { Same } +enum Bar { Same } -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.sol index 34b8a18f..ca4d7e96 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/ns_cross_ok.sol @@ -1,5 +1,5 @@ -data Foo = Foo; +enum Foo { Foo } -function main() -> Foo { +function main() returns (Foo) { return Foo.Foo; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.sol index c6f221a4..2db0ff03 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_leak_fail.sol @@ -1,5 +1,5 @@ -import opaque_alias_mid as M; +import * as M from opaque_alias_mid; -function bad(x: word) -> T { +function bad(x: word) returns (T) { return M.make(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.sol index a21644c3..d0c8f9f2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_main.sol @@ -1,6 +1,6 @@ -import opaque_alias_mid as M; +import * as M from opaque_alias_mid; -function main(x: word) -> word { +function main(x: word) returns (word) { let t = M.make(x); return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.sol index 75523351..2c071630 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_mid.sol @@ -1,7 +1,7 @@ -import opaque_dep_base as Base; +import * as Base from opaque_dep_base; export { make }; -function make(x: word) -> Base.T { +function make(x: word) returns (Base.T) { return Base.mkT(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.sol index fd0e0518..2646b7b2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_alias_qualifier_leak_fail.sol @@ -1,5 +1,5 @@ -import opaque_alias_mid as M; +import * as M from opaque_alias_mid; -function bad(x: word) -> Base.T { +function bad(x: word) returns (Base.T) { return M.make(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.sol index 95a10f3e..390f62d1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_dep_base.sol @@ -1,7 +1,7 @@ export { T(*), mkT }; -data T = T(word); +enum T { T(word) } -function mkT(x: word) -> T { +function mkT(x: word) returns (T) { return T.T(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.sol index 8ec20765..51e23026 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_main.sol @@ -1,6 +1,6 @@ -import opaque_select_alias_mid as M; +import * as M from opaque_select_alias_mid; -function main(x: word) -> word { +function main(x: word) returns (word) { let t = M.make(x); return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.sol index b8f71be7..9ca5df84 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_alias_mid.sol @@ -1,7 +1,7 @@ -import opaque_dep_base.{T as U, mkT}; +import {T as U, mkT} from opaque_dep_base; export { make }; -function make(x: word) -> U { +function make(x: word) returns (U) { return mkT(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.sol index 47a953ca..af1c1343 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_leak_fail.sol @@ -1,5 +1,5 @@ -import opaque_select_direct_mid as M; +import * as M from opaque_select_direct_mid; -function bad(x: word) -> T { +function bad(x: word) returns (T) { return M.make(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.sol index bdb833a7..dce75db0 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/opaque_select_direct_mid.sol @@ -1,7 +1,7 @@ -import opaque_dep_base.{T, mkT}; +import {T, mkT} from opaque_dep_base; export { make }; -function make(x: word) -> T { +function make(x: word) returns (T) { return mkT(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.sol index 035f940a..100259b8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_lib.sol @@ -2,6 +2,6 @@ export { helper }; pragma no-patterson-condition C; -function helper() -> word { +function helper() returns (word) { return 1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.sol index 0d4f0b22..ebaccf71 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/pragma_scope_main.sol @@ -1,7 +1,7 @@ import pragma_scope_lib; -data List(a) = Nil | Cons(a, List(a)); +enum List { Nil, Cons(a, List) } -forall a b c . class a : C(b, c) {} +trait C {} -forall a b . instance List(b) : C(a, List(a)) {} +impl C, a, List> {} diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.sol index f7f1d072..fd65036a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_lib.sol @@ -1,9 +1,9 @@ export {ok}; -function ok() -> word { +function ok() returns (word) { return 1; } -function broken() -> word { +function broken() returns (word) { return true; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.sol index 79e69d91..7a32366f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_bad_main.sol @@ -1,5 +1,5 @@ import private_bad_lib; -function main() -> word { +function main() returns (word) { return private_bad_lib.ok(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.sol index 9bfb5216..e002f7f4 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_a.sol @@ -1,9 +1,9 @@ export { foo }; -function helper(x: word) -> word { +function helper(x: word) returns (word) { return x; } -function foo(x: word) -> word { +function foo(x: word) returns (word) { return helper(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.sol index b6eee902..050cf3fb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/private_helper_main.sol @@ -1,5 +1,5 @@ import private_helper_a; -function main(x: word) -> word { +function main(x: word) returns (word) { return private_helper_a.foo(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.sol index 77bf9dd4..47cf70c6 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_hidden_fail.sol @@ -1,5 +1,5 @@ import reexport_ctor_mid; -function main() -> reexport_ctor_mid.Token { +function main() returns (reexport_ctor_mid.Token) { return reexport_ctor_mid.Token.Err(1); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.sol index 774ffd23..16fcaaaf 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_expr_ok.sol @@ -1,5 +1,5 @@ import reexport_ctor_mid; -function main() -> reexport_ctor_mid.Token { +function main() returns (reexport_ctor_mid.Token) { return reexport_ctor_mid.Token.Ok(1); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.sol index 3e474451..8bbc2bbc 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_ctor_pattern.sol @@ -1,8 +1,12 @@ import reexport_ctor_mid; -function main() -> word { - match reexport_ctor_mid.mkErr(1) { - | reexport_ctor_mid.Token.Ok(v) => return v; - | _ => return 0; - } +function main() returns (word) { + match (reexport_ctor_mid.mkErr(1)) { +case reexport_ctor_mid.Token.Ok(v) { +return v; +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.sol index af8af05d..2aad9851 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items/pkg/util.sol @@ -1,19 +1,21 @@ export {Wrap(*), unwrap, Unbox}; -data Wrap = Mk(word); +enum Wrap { Mk(word) } -forall self . class self:Unbox { - function unbox(x:self) -> word; +trait Unbox { + function unbox(x: self) returns (word) ; } -instance Wrap:Unbox { - function unbox(x:Wrap) -> word { - match x { - | Wrap.Mk(w) => return w; - } +impl Unbox { + function unbox(x: Wrap) returns (word) { + match (x) { +case Wrap.Mk(w) { +return w; +} +} } } -function unwrap(x:Wrap) -> word { +function unwrap(x: Wrap) returns (word) { return Unbox.unbox(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.sol index 54befbc3..c8bc5b42 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_items_main.sol @@ -1,5 +1,5 @@ -import reexport_items.pkg.api.{unwrap, Wrap}; +import {unwrap, Wrap} from reexport_items.pkg.api; -function main() -> word { +function main() returns (word) { return unwrap(Wrap.Mk(1)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.sol index af8af05d..2aad9851 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module/pkg/util.sol @@ -1,19 +1,21 @@ export {Wrap(*), unwrap, Unbox}; -data Wrap = Mk(word); +enum Wrap { Mk(word) } -forall self . class self:Unbox { - function unbox(x:self) -> word; +trait Unbox { + function unbox(x: self) returns (word) ; } -instance Wrap:Unbox { - function unbox(x:Wrap) -> word { - match x { - | Wrap.Mk(w) => return w; - } +impl Unbox { + function unbox(x: Wrap) returns (word) { + match (x) { +case Wrap.Mk(w) { +return w; +} +} } } -function unwrap(x:Wrap) -> word { +function unwrap(x: Wrap) returns (word) { return Unbox.unbox(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.sol index 55900f24..648e2e78 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_alias_main.sol @@ -1,5 +1,5 @@ import reexport_module.pkg.api_alias; -function main() -> word { +function main() returns (word) { return api_alias.Utils.unwrap(api_alias.Utils.Wrap.Mk(1)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.sol index 396eccaa..96c1e546 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_module_main.sol @@ -1,5 +1,5 @@ import reexport_module.pkg.api; -function main() -> word { +function main() returns (word) { return api.util.unwrap(api.util.Wrap.Mk(1)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.sol index b2754ef1..970c881d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_main.sol @@ -1,5 +1,5 @@ -import reexport_select_alias_wrapper.{keep_}; +import {keep_} from reexport_select_alias_wrapper; -function main(x: word) -> word { +function main(x: word) returns (word) { return keep_(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.sol index c3b5dc9d..fac4bf0f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_alias_wrapper.sol @@ -1,3 +1,3 @@ -import selectlib.{keep as keep_}; +import {keep as keep_} from selectlib; export { keep_ }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.sol index 3bafbc63..310722d5 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_base.sol @@ -1,5 +1,5 @@ export { mstore }; -function mstore(x: word) -> word { +function mstore(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.sol index 48476677..9a033021 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_main.sol @@ -1,5 +1,5 @@ -import reexport_select_wrapper.{mstore}; +import {mstore} from reexport_select_wrapper; -function main(x: word) -> word { +function main(x: word) returns (word) { return mstore(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.sol index a6ea114e..097fb4bd 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/reexport_select_wrapper.sol @@ -1,3 +1,3 @@ -import reexport_select_base.{mstore}; +import {mstore} from reexport_select_base; export { mstore }; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.sol index be1d2653..e525eaf1 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/main.sol @@ -1,5 +1,5 @@ import lib.rootcheck.provider; -function main() -> word { +function main() returns (word) { return provider.value(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.sol index a269930d..c49577b8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/provider.sol @@ -1,5 +1,5 @@ export {value}; -function value() -> word { +function value() returns (word) { return 11; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.sol index 37e0223b..f224a512 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/nested/relative_and_lib_main.sol @@ -1,7 +1,7 @@ import provider; -import lib.rootcheck.provider as RootProvider; +import * as RootProvider from lib.rootcheck.provider; -function main() -> word { +function main() returns (word) { let rootValue: word = RootProvider.value(); return provider.value(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.sol index 46073d4d..aaa99865 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/rootcheck/provider.sol @@ -1,5 +1,5 @@ export {value}; -function value() -> word { +function value() returns (word) { return 7; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.sol index 7a264705..38ab250e 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_item_ok.sol @@ -1,5 +1,5 @@ -import selectlib.{keep as keep_}; +import {keep as keep_} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return keep_(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.sol index f3bc28b4..33de2fb7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_alias_multi_ok.sol @@ -1,5 +1,5 @@ -import selectlib.{keep as keep_, drop as drop_}; +import {keep as keep_, drop as drop_} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return drop_(keep_(x)); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.sol index c61b1654..e87f1e4d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_dup_item.sol @@ -1,5 +1,5 @@ -import selectlib.{keep, keep}; +import {keep, keep} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return keep(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.sol index 02a1c4b7..a718ca67 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_fail.sol @@ -1,5 +1,5 @@ -import selectlib.{keep}; +import {keep} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return drop(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.sol index 901f7186..53f22966 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_fail.sol @@ -1,5 +1,5 @@ -import selectlib.{keep, drop} hiding {drop}; +import {keep, drop} from selectlib hiding {drop}; -function main(x: word) -> word { +function main(x: word) returns (word) { return drop(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.sol index 806aa125..bfc57cfb 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_hiding_ok.sol @@ -1,5 +1,5 @@ -import selectlib.{keep, drop} hiding {drop}; +import {keep, drop} from selectlib hiding {drop}; -function main(x: word) -> word { +function main(x: word) returns (word) { return keep(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.sol index 8d0ae999..13152352 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_ok.sol @@ -1,5 +1,5 @@ -import selectlib.{keep}; +import {keep} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return keep(x); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.sol index 4c854e33..276a1664 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_local.sol @@ -1,9 +1,9 @@ -import selectlib.{keep}; +import {keep} from selectlib; -function keep() -> word { +function keep() returns (word) { return 10; } -function main() -> word { +function main() returns (word) { return keep(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.sol index d619f498..e12cbea2 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_shadow_param_ok.sol @@ -1,5 +1,5 @@ -import selectlib.{keep}; +import {keep} from selectlib; -function main(keep: word) -> word { +function main(keep: word) returns (word) { return keep; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.sol index c4ed6b15..677074db 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/select_unknown.sol @@ -1,5 +1,5 @@ -import selectlib.{missing}; +import {missing} from selectlib; -function main(x: word) -> word { +function main(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.sol index f3b631bc..eb490d13 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/selective_unqualified_fun_ok.sol @@ -1,5 +1,5 @@ -import foo.{base}; +import {base} from foo; -function main() -> word { +function main() returns (word) { return base(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.sol index 60fe6f7c..0ef4bed9 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/selectlib.sol @@ -1,9 +1,9 @@ export { keep, drop }; -function keep(x: word) -> word { +function keep(x: word) returns (word) { return x; } -function drop(x: word) -> word { +function drop(x: word) returns (word) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.sol index 99aff9cc..69b8fc0f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/selfcycle.sol @@ -1,5 +1,5 @@ import selfcycle; -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.sol index 6561a3a1..18bfb93d 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/strict_open_fail.sol @@ -1,5 +1,5 @@ import booldef; -function bad(b: Bool) -> Bool { +function bad(b: Bool) returns (Bool) { return not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.sol index 56338bb2..eb2f260b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/symlink_identity_fail.sol @@ -1,6 +1,6 @@ -import vendor.math.api as Vendor; -import mirror.api as Mirror; +import * as Vendor from vendor.math.api; +import * as Mirror from mirror.api; -function bad(x: Vendor.T) -> Mirror.T { +function bad(x: Vendor.T) returns (Mirror.T) { return x; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.sol index 53690077..7f973e9a 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_base.sol @@ -1,5 +1,5 @@ export { g }; -function g() -> word { +function g() returns (word) { return 1; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.sol index 76736927..fbe4ea8b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_module.sol @@ -1,5 +1,5 @@ -import transitive_dep_mid as M; +import * as M from transitive_dep_mid; -function main() -> word { +function main() returns (word) { return M.f(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.sol index 87deb02b..cb0010df 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_main_select.sol @@ -1,5 +1,5 @@ -import transitive_dep_mid.{f}; +import {f} from transitive_dep_mid; -function main() -> word { +function main() returns (word) { return f(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.sol index 1164443e..8b1f863f 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/transitive_dep_mid.sol @@ -1,7 +1,7 @@ -import transitive_dep_base.{g}; +import {g} from transitive_dep_base; export { f }; -function f() -> word { +function f() returns (word) { return g(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.sol index cf8fc305..49de8fea 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_a.sol @@ -1,7 +1,7 @@ export { T(A), mk }; -data T = A; +enum T { A } -function mk() -> T { +function mk() returns (T) { return T.A; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.sol index 9a4857a1..26cdca89 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_b.sol @@ -1,7 +1,7 @@ export { T(B), mk }; -data T = B; +enum T { B } -function mk() -> T { +function mk() returns (T) { return T.B; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.sol index c190d2c7..68aaa5ce 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/type_collision_main.sol @@ -1,7 +1,7 @@ import type_collision_a; import type_collision_b; -function main() -> word { +function main() returns (word) { let x = type_collision_a.mk(); let y = type_collision_b.mk(); return 0; diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.sol index 0b596b69..c12a5f7b 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_lib.sol @@ -1,10 +1,14 @@ export { Bool(*), not }; -data Bool = True | False; +enum Bool { True, False } -function not(b : Bool) -> Bool { - match b { - | Bool.True => return Bool.False; - | Bool.False => return Bool.True; - } +function not(b: Bool) returns (Bool) { + match (b) { +case Bool.True { +return Bool.False; +} +case Bool.False { +return Bool.True; +} +} } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.sol index d9b608fb..0a4594f3 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/unordered_imports_main.sol @@ -2,7 +2,7 @@ export { main }; pragma no-patterson-condition; -function main(b : unordered_imports_lib.Bool) -> unordered_imports_lib.Bool { +function main(b: unordered_imports_lib.Bool) returns (unordered_imports_lib.Bool) { return unordered_imports_lib.not(b); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.sol index d2d38ce7..f03838e7 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/vendor/math/helper.sol @@ -1,3 +1,3 @@ export {T}; -data T = T; +enum T { T } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.sol index e9cc4661..eaf999ff 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/wildA.sol @@ -1,6 +1,6 @@ import wildB; export {wildB.*, *}; -function fromWildA() -> word { +function fromWildA() returns (word) { return wildB.fromWildB(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.sol index 2b4ed1c0..1f4903f8 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/wildB.sol @@ -1,6 +1,6 @@ import wildA; export {wildA.*, *}; -function fromWildB() -> word { +function fromWildB() returns (word) { return 3; } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.sol index 11bf7e23..70f90751 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/wild_main.sol @@ -1,5 +1,5 @@ import wildA; -function main() -> word { +function main() returns (word) { return wildA.fromWildB(); } diff --git a/crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.sol b/crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.sol index 2e516ded..809ec8ad 100644 --- a/crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.sol +++ b/crates/parser/tests/fixtures/corpus/ok/test/imports/wrapper_shadow_success.sol @@ -1,9 +1,9 @@ import booldef; -function not(x: word) -> word { +function not(x: word) returns (word) { return x; } -function main(b: booldef.Bool) -> booldef.Bool { +function main(b: booldef.Bool) returns (booldef.Bool) { return booldef.not(b); } From 34250e3b43d2fa62f6018594638a654d737036c7 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 077/110] Switch the compiler and fixtures to canonical syntax: parser corpus reference frontend.tsv Co-authored-by: Codex --- .../fixtures/corpus/reference-frontend.tsv | 900 +++++++++--------- 1 file changed, 450 insertions(+), 450 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/reference-frontend.tsv b/crates/parser/tests/fixtures/corpus/reference-frontend.tsv index c7f76e56..99ae9dfc 100644 --- a/crates/parser/tests/fixtures/corpus/reference-frontend.tsv +++ b/crates/parser/tests/fixtures/corpus/reference-frontend.tsv @@ -1,454 +1,454 @@ path status code -Convertible.solc fail SC0001 -cases/Ackermann.solc pass - -cases/Add1.solc pass - -cases/BadInstance.solc fail SC0102 -cases/BoolNot.solc pass - -cases/Compose.solc pass - -cases/Compose3.solc pass - -cases/CondExp.solc pass - -cases/DupFun.solc fail SC0108 -cases/DuplicateFun.solc pass - -cases/EitherModule.solc pass - -cases/Enum.solc fail SC0108 -cases/Eq.solc fail SC0102 -cases/EqQual.solc pass - -cases/EvenOdd.solc pass - -cases/Filter.solc fail SC0102 -cases/Foo.solc pass - -cases/GetSet.solc fail SC0103 -cases/GoodInstance.solc fail SC0102 -cases/Id.solc pass - -cases/IncompleteInstDef.solc fail SC0299 -cases/Invokable.solc fail SC0102 -cases/KindTest.solc fail SC0103 -cases/ListModule.solc pass - -cases/Logic.solc pass - -cases/MatchCall.solc pass - -cases/Memory1.solc pass - -cases/Memory2.solc pass - -cases/Mutuals.solc pass - -cases/NegPair.solc pass - -cases/Option.solc pass - -cases/Pair.solc pass - -cases/PairMatch1.solc fail SC0209 -cases/PairMatch2.solc fail SC0209 -cases/Peano.solc pass - -cases/PeanoMatch.solc pass - -cases/Ref.solc fail SC0102 -cases/RefDeref.solc pass - -cases/SillyReturn.solc fail SC0220 -cases/SimpleInvoke.solc fail SC0102 -cases/SimpleLambda.solc pass - -cases/SingleFun.solc pass - -cases/StructMembers.solc fail SC0001 -cases/Uncurry.solc pass - -cases/abigeneric.solc pass - -cases/add-moritz.solc fail SC0102 -cases/another-subst.solc pass - -cases/app.solc pass - -cases/array-elem-no-storagecopy.solc fail SC0223 -cases/array-push-no-canstore.solc fail SC0223 -cases/array.solc pass - -cases/arraylit-bad-target.solc fail SC0201 -cases/arraylit-mixed-types.solc fail SC0201 -cases/asm-assign-no-return.solc fail SC0220 -cases/asm-assign-non-word.solc fail SC0001 -cases/asm-let-bool-lit.solc pass - -cases/asm-let-no-return.solc fail SC0220 -cases/asm-let-uninit.solc pass - -cases/asm-match-tuple-read.solc pass - -cases/asm-match-tuple-write-read.solc pass - -cases/assembly.solc pass - -cases/bal.solc pass - -cases/bar.solc pass - -cases/bitwise.solc pass - -cases/bool-elim.solc pass - -cases/bound-merge-case.solc pass - -cases/bound-minimal.solc fail SC0103 -cases/bound-only-test.solc fail SC0103 -cases/bound-with-pragma.solc pass - -cases/bug-call-expected-nontail-return.solc pass - -cases/bug-import-default-inst-shadow.solc pass - -cases/bug-rep-name-capture.solc pass - -cases/bug-spec-generic-let.solc fail - -cases/catch-all.solc pass - -cases/catenable-err.solc fail SC0001 -cases/class-context.solc pass - -cases/class-return-type-miss.solc fail SC0221 -cases/class-type-name-collision.solc fail SC0108 -cases/clone-deriving.solc pass - -cases/closure-capture-only.solc pass - -cases/closure-free-bound-test.solc pass - -cases/closure-free-var-local.solc pass - -cases/closure-free-var-std.solc pass - -cases/closure-free-var.solc pass - -cases/closure.solc pass - -cases/comp.solc fail SC0220 -cases/comparisons.solc pass - -cases/complexproxy.solc fail SC0102 -cases/compose0.solc pass - -cases/compose_desugared.solc fail SC0209 -cases/compound-operators.solc pass - -cases/const-array.solc fail SC0221 -cases/const.solc pass - -cases/constrained-instance-context.solc pass - -cases/constrained-instance.solc pass - -cases/constructor-weak-args.solc pass - -cases/contract-local-derive.solc pass - -cases/contract-local-type-escapes-fail.solc fail SC0103 -cases/contract-local-type-same-name.solc pass - -cases/copytomem.solc pass - -cases/cyclical-defs-inferred.solc pass - -cases/cyclical-defs.solc pass - -cases/default-inst.solc fail SC0102 -cases/default-instance-missing.solc fail SC0102 -cases/default-instance-weak.solc fail SC0102 -cases/derive-custom-hash.solc pass - -cases/derive-eq-action.solc pass - -cases/derive-eq-enum.solc pass - -cases/derive-eq-pair.solc pass - -cases/derive-generic-excluded.solc pass - -cases/derive-generic-sum.solc pass - -cases/derive-universe-instances.solc pass - -cases/derive-unknown-class.solc fail SC0105 -cases/deriving-empty-type.solc pass - -cases/dispatch.solc fail SC0103 -cases/dot-expression-assignment-context.solc pass - -cases/dot-expression-call-arg-context.solc pass - -cases/dot-expression-constructor.solc pass - -cases/dot-expression-match-return.solc pass - -cases/dot-expression-nested-context.solc pass - -cases/dot-expression-no-context-fail.solc fail SC0224 -cases/dot-expression-unknown-fail.solc fail SC0224 -cases/dot-pattern-constructor.solc pass - -cases/dot-pattern-nested-constructor.solc pass - -cases/dot-primitive-constructor.solc pass - -cases/duplicated-contract-name.solc fail SC0108 -cases/duplicated-type-name.solc fail SC0108 -cases/empty-asm.solc pass - -cases/encoder.solc pass - -cases/encoder1.solc pass - -cases/fallback-with-args.solc fail SC0001 -cases/fallback-with-return.solc fail SC0001 -cases/false-redundant-warning.solc pass - -cases/field-access.solc fail SC0201 -cases/field-helper-cxt-collision.solc pass - -cases/field-name-error.solc pass - -cases/foo-class.solc pass - -cases/for-body-shadow.solc pass - -cases/for-break.solc pass - -cases/for-continue.solc pass - -cases/for-empty-init.solc pass - -cases/for-init-shadow.solc pass - -cases/for-inner-block.solc pass - -cases/for-let-post.solc fail SC0001 -cases/for-let.solc pass - -cases/for-loop.solc pass - -cases/for-multi-init.solc pass - -cases/for-multi-post.solc pass - -cases/fresh-pat-arg-synonym.solc pass - -cases/fresh-pat-arg.solc pass - -cases/fresh-variable-shadowing.solc pass - -cases/generic-manual-no-pragma.solc fail - -cases/generic-product-no-pragma.solc fail - -cases/generic-sum-no-pragma.solc fail - -cases/if-examples.solc pass - -cases/import-std.solc pass - -cases/inc-closure.solc pass - -cases/index-example.solc fail SC0108 -cases/instance-closure-error-invalid-member.solc fail SC0201 -cases/instance-closure-error.solc pass - -cases/instance-context-wrong-kind.solc fail SC0299 -cases/instance-synonym-int.solc pass - -cases/instance-synonym.solc pass - -cases/instance-wrong-sig.solc fail SC0299 -cases/invokable-issue.solc pass - -cases/ixa.solc pass - -cases/join.solc pass - -cases/joinErr.solc fail SC0201 -cases/listeq.solc fail SC0220 -cases/listid.solc pass - -cases/ltimp.solc pass - -cases/ltproxy.solc pass - -cases/mainproxy.solc fail SC0102 -cases/match-bitwise.solc pass - -cases/match-compiler-undef-asm.solc fail SC0299 -cases/match-yul.solc pass - -cases/memory.solc pass - -cases/missing-instance.solc fail SC0223 -cases/mod-example.solc pass - -cases/modifier.solc pass - -cases/modulo.solc pass - -cases/monomorphic-require.solc pass - -cases/morefun.solc pass - -cases/mptc-both-templates.solc pass - -cases/mptc-chain-phantom.solc pass - -cases/mptc-guard-extras-concrete.solc pass - -cases/mptc-multi-instance.solc pass - -cases/mptc-nop-mainty-free.solc pass - -cases/mptc-partial-instance.solc pass - -cases/mptc-template-a-only.solc pass - -cases/mptc-template-b-only.solc pass - -cases/multi-stmt-var-leaf.solc pass - -cases/nano-desugared.solc fail SC0108 -cases/nid.solc pass - -cases/noclosure.solc pass - -cases/noconstr.solc fail SC0102 -cases/notif.solc pass - -cases/option2.solc pass - -cases/overlap-synonym-detected.solc fail SC0299 -cases/overlap-synonym-missed-order.solc fail SC0299 -cases/overlap-synonym-missed-two-synonyms.solc fail SC0299 -cases/overlapping-heads.solc fail SC0299 -cases/pair-bug.solc pass - -cases/pars.solc pass - -cases/patterson-bug.solc fail SC0108 -cases/payable-toplevel-function.solc fail SC0001 -cases/phantom-type-return-con.solc pass - -cases/polymatch-error.solc pass - -cases/polymorphic-require.solc pass - -cases/pragma_merge_base.solc pass - -cases/pragma_merge_fail_coverage.solc fail SC0299 -cases/pragma_merge_fail_patterson.solc fail SC0105 -cases/pragma_merge_import.solc fail SC0105 -cases/pragma_merge_verify.solc fail SC0105 -cases/pragma_test_patterson.solc pass - -cases/proxy-desugar.solc pass - -cases/proxy.solc pass - -cases/proxy1.solc fail SC0223 -cases/public-constructor.solc fail SC0001 -cases/public-fallback.solc fail SC0001 -cases/public-top-level-function.solc fail SC0001 -cases/rec.solc pass - -cases/redundant-match.solc pass - -cases/reference-encoding-good.solc pass - -cases/reference-encoding-good1.solc pass - -cases/reference-encoding.solc fail SC0102 -cases/reference-test.solc fail SC0102 -cases/reference.solc fail SC0001 -cases/references-daniel.solc fail SC0102 -cases/require-annotation-contract-method.solc fail SC0220 -cases/require-annotation-missing-both.solc fail SC0220 -cases/require-annotation-missing-param.solc fail SC0220 -cases/require-annotation-missing-return.solc fail SC0220 -cases/require-annotation-mutual.solc fail SC0220 -cases/return-fun-adder.solc pass - -cases/return-fun-bad-arity.solc fail SC0201 -cases/return-fun-bad-param.solc fail SC0201 -cases/return-fun-bad-return.solc fail SC0201 -cases/return-fun-bad-sig.solc fail SC0201 -cases/return-fun-const.solc pass - -cases/return-fun-eq.solc pass - -cases/return-fun-instance.solc pass - -cases/return-fun-not-fun.solc fail SC0201 -cases/same-name-constructor-qualifier.solc pass - -cases/signature.solc fail SC0001 -cases/simpleDiscount.solc pass - -cases/simpleIfExpr.solc fail SC0220 -cases/simpleIfStmt.solc fail SC0220 -cases/simpleid.solc pass - -cases/single-lambda.solc pass - -cases/skolem-let.solc fail SC0209 -cases/snds.solc pass - -cases/spec-fail-ungrounded.solc pass - -cases/storage-adt-mapping-field-fail.solc fail SC0201 -cases/storage-adt-recursive-fail.solc pass - -cases/storage-adt-recursive-ok.solc pass - -cases/strange-unbound.solc pass - -cases/string-const.solc fail SC0220 -cases/subject-index.solc fail SC0108 -cases/subject-reduction.solc fail SC0108 -cases/subsumption-constraint.solc fail SC0223 -cases/subsumption-test.solc fail SC0209 -cases/sum-match-default.solc pass - -cases/super-class-cycle-fail.solc fail SC0223 -cases/super-class-cycle.solc pass - -cases/super-class-num.solc pass - -cases/super-class-recursive-arg.solc fail SC0223 -cases/super-class.solc pass - -cases/synonym-arity-mismatch.solc fail SC0299 -cases/synonym-basic.solc pass - -cases/synonym-in-function.solc pass - -cases/synonym-long-cycle.solc fail SC0299 -cases/synonym-nested.solc pass - -cases/synonym-param.solc pass - -cases/synonym-recursive.solc fail SC0299 -cases/synonym-self-recursive.solc fail SC0299 -cases/tabled-answer-reuse.solc fail SC0299 -cases/tabled-cycle-fail.solc timeout - -cases/tabled-default-instance.solc pass - -cases/tabled-given-order.solc pass - -cases/tabled-left-recursive-fail.solc timeout - -cases/tabled-mutual-chain.solc fail SC0299 -cases/tabled-residual-given.solc pass - -cases/td.solc pass - -cases/tiamat.solc pass - -cases/toplevel-constructor.solc fail SC0001 -cases/toplevel-fallback.solc fail SC0001 -cases/tuple-trick.solc pass - -cases/tuva.solc pass - -cases/tyexp.solc pass - -cases/type-synonym-arg.solc pass - -cases/typedef.solc pass - -cases/ufcs-no-conflict.solc pass - -cases/uintdesugared.solc pass - -cases/unbound-instance-var.solc fail SC0103 -cases/unconstrained-instance.solc fail SC0001 -cases/undefined.solc pass - -cases/unit.solc pass - -cases/user-op-lambda.solc fail SC0001 -cases/vartyped.solc fail SC0220 -cases/weird-error-foo.solc fail SC0220 -cases/weirdfoo.solc fail SC0001 -cases/word-match-default.solc pass - -cases/word-match.solc pass - -cases/xref.solc fail SC0221 -cases/yul-asm-break-continue-leave.solc pass - -cases/yul-asm-for-body.solc pass - -cases/yul-asm-switch-body.solc pass - -cases/yul-deposit-example.solc pass - -cases/yul-for.solc pass - -cases/yul-function-typing.solc pass - -cases/yul-multi-return-arity-fail.solc fail SC0299 -cases/yul-multi-return.solc pass - -cases/yul-return.solc pass - -comptime/CondExpr.solc pass - -comptime/CondStmt.solc pass - -comptime/OneOne.solc fail SC0001 -comptime/OneTwo.solc pass - -comptime/Plus.solc pass - -comptime/Size.solc pass - -comptime/StdSize.solc pass - -comptime/comptime_syntax.solc pass - -comptime/counter.solc pass - -comptime/ct_asm_mem.solc pass - -comptime/ct_asm_ret.solc pass - -comptime/ct_chain_ok.solc pass - -comptime/ct_let_ok.solc pass - -comptime/ct_let_runtime.solc pass - -comptime/ct_overloaded_bad.solc pass - -comptime/ct_overloaded_ok.solc pass - -comptime/ct_param_ok.solc pass - -comptime/ct_param_poly_runtime.solc fail SC0299 -comptime/ct_param_runtime.solc fail - -comptime/ct_runtime_arg.solc pass - -comptime/erc7201-lit.solc pass - -comptime/fib.solc pass - -comptime/fib2.solc pass - -comptime/fib3.solc pass - -comptime/fromInt.solc fail SC0103 -comptime/fromInt2.solc fail SC0103 -comptime/fromInt3.solc fail SC0103 -comptime/fromLit.solc fail SC0103 -comptime/int-untyped-let.solc pass - -comptime/integer-basic.solc pass - -comptime/integer-fib.solc pass - -comptime/integer-from-integer.solc pass - -comptime/integer-lit-class.solc pass - -comptime/integer-lit-cond.solc pass - -comptime/integer-lit-pat.solc pass - -comptime/integer-lit-poly.solc pass - -comptime/integer-lit-safe.solc pass - -comptime/integer-lit-word-site.solc pass - -comptime/integer-lit.solc pass - -comptime/match_labels.solc pass - -comptime/string-concat-mem.solc pass - -comptime/string-lit-dedup.solc pass - -comptime/string-lit-keccak.solc pass - -comptime/string-lit-len.solc pass - -comptime/string-lit-mem.solc pass - -comptime/string-lit-ops.solc pass - -comptime/string-mem-runtime-fail.solc fail SC0201 -comptime/string-param-erasure.solc pass - -comptime/string-user-instance.solc pass - -comptime/uint256-lit.solc pass - -dispatch/Revert.solc pass - -dispatch/abi_address_array.solc pass - -dispatch/abi_array_sum.solc pass - -dispatch/abi_batch_adt.solc pass - -dispatch/abi_bytes_array.solc pass - -dispatch/abi_dyn_sum.solc pass - -dispatch/abi_dyn_sum_return.solc pass - -dispatch/abi_encode_adt.solc pass - -dispatch/abi_encode_types.solc pass - -dispatch/abi_sum_roundtrip.solc pass - -dispatch/array_copy.solc pass - -dispatch/array_nested.solc pass - -dispatch/array_ops.solc pass - -dispatch/array_string.solc pass - -dispatch/arraylit.solc pass - -dispatch/asm_break_continue_leave.solc pass - -dispatch/assembly.solc pass - -dispatch/basic.solc pass - -dispatch/concat.solc pass - -dispatch/counter.solc pass - -dispatch/deposit.solc pass - -dispatch/derive_contract_local.solc pass - -dispatch/derive_ord.solc pass - -dispatch/ecrecover.solc pass - -dispatch/eip712.solc pass - -dispatch/empty.solc pass - -dispatch/empty_no_constructor.solc pass - -dispatch/fallback.solc pass - -dispatch/fib.solc fail SC0103 -dispatch/forloops.solc pass - -dispatch/generic_product.solc pass - -dispatch/generic_sum.solc pass - -dispatch/hashes.solc pass - -dispatch/memory.solc pass - -dispatch/miniERC20.solc pass - -dispatch/neg.solc pass - -dispatch/nonpayable_ctor.solc pass - -dispatch/ownable.solc pass - -dispatch/p256verify.solc pass - -dispatch/payable.solc pass - -dispatch/payable_ctor.solc pass - -dispatch/slices.solc pass - -dispatch/specialise_sum_of_product.solc pass - -dispatch/storage.solc pass - -dispatch/storage_adt_abi.solc pass - -dispatch/storage_adt_bool.solc pass - -dispatch/storage_adt_enum.solc pass - -dispatch/storage_adt_field.solc pass - -dispatch/storage_adt_mapping.solc pass - -dispatch/storage_array.solc pass - -dispatch/storage_dynamic_field.solc pass - -dispatch/stringid.solc pass - -dispatch/stringlit.solc pass - -dispatch/sum_wide_product.solc pass - -dispatch/ufcs_array.solc pass - -dispatch/weth9.solc pass - -invokable/021nid.solc fail SC0220 -invokable/022nid-invoke.solc fail SC0001 -invokable/024lamid.solc fail SC0220 -invokable/025lamid-invoke.solc fail SC0001 -invokable/026capture.solc fail SC0001 -invokable/027retfun.solc fail SC0001 -invokable/028modifier.solc fail SC0001 -invokable/031enum.solc fail SC0001 -opcodes/all-shapes.solc pass - -opcodes/terminators.solc pass - -pragmas/bound.solc fail SC0001 -pragmas/coverage.solc pass - -pragmas/patterson.solc pass - -spec/00answer.solc pass - -spec/010answer.solc fail SC0220 -spec/011id.solc fail SC0220 -spec/012nid.solc fail SC0220 -spec/013comp.solc fail SC0220 -spec/01id.solc pass - -spec/021not.solc pass - -spec/022add.solc pass - -spec/024arith.solc pass - -spec/027sstore.solc fail SC0220 -spec/02nid.solc pass - -spec/031maybe.solc pass - -spec/032simplejoin.solc pass - -spec/033join.solc pass - -spec/034cojoin.solc pass - -spec/035padding.solc pass - -spec/036wildcard.solc pass - +Convertible.sol fail SC0001 +cases/Ackermann.sol pass - +cases/Add1.sol pass - +cases/BadInstance.sol fail SC0102 +cases/BoolNot.sol pass - +cases/Compose.sol pass - +cases/Compose3.sol pass - +cases/CondExp.sol pass - +cases/DupFun.sol fail SC0108 +cases/DuplicateFun.sol pass - +cases/EitherModule.sol pass - +cases/Enum.sol fail SC0108 +cases/Eq.sol fail SC0102 +cases/EqQual.sol pass - +cases/EvenOdd.sol pass - +cases/Filter.sol fail SC0102 +cases/Foo.sol pass - +cases/GetSet.sol fail SC0103 +cases/GoodInstance.sol fail SC0102 +cases/Id.sol pass - +cases/IncompleteInstDef.sol fail SC0299 +cases/Invokable.sol fail SC0102 +cases/KindTest.sol fail SC0103 +cases/ListModule.sol pass - +cases/Logic.sol pass - +cases/MatchCall.sol pass - +cases/Memory1.sol pass - +cases/Memory2.sol pass - +cases/Mutuals.sol pass - +cases/NegPair.sol pass - +cases/Option.sol pass - +cases/Pair.sol pass - +cases/PairMatch1.sol fail SC0209 +cases/PairMatch2.sol fail SC0209 +cases/Peano.sol pass - +cases/PeanoMatch.sol pass - +cases/Ref.sol fail SC0102 +cases/RefDeref.sol pass - +cases/SillyReturn.sol fail SC0220 +cases/SimpleInvoke.sol fail SC0102 +cases/SimpleLambda.sol pass - +cases/SingleFun.sol pass - +cases/StructMembers.sol fail SC0001 +cases/Uncurry.sol pass - +cases/abigeneric.sol pass - +cases/add-moritz.sol fail SC0102 +cases/another-subst.sol pass - +cases/app.sol pass - +cases/array-elem-no-storagecopy.sol fail SC0223 +cases/array-push-no-canstore.sol fail SC0223 +cases/array.sol pass - +cases/arraylit-bad-target.sol fail SC0201 +cases/arraylit-mixed-types.sol fail SC0201 +cases/asm-assign-no-return.sol fail SC0220 +cases/asm-assign-non-word.sol fail SC0001 +cases/asm-let-bool-lit.sol pass - +cases/asm-let-no-return.sol fail SC0220 +cases/asm-let-uninit.sol pass - +cases/asm-match-tuple-read.sol pass - +cases/asm-match-tuple-write-read.sol pass - +cases/assembly.sol pass - +cases/bal.sol pass - +cases/bar.sol pass - +cases/bitwise.sol pass - +cases/bool-elim.sol pass - +cases/bound-merge-case.sol pass - +cases/bound-minimal.sol fail SC0103 +cases/bound-only-test.sol fail SC0103 +cases/bound-with-pragma.sol pass - +cases/bug-call-expected-nontail-return.sol pass - +cases/bug-import-default-inst-shadow.sol pass - +cases/bug-rep-name-capture.sol pass - +cases/bug-spec-generic-let.sol fail - +cases/catch-all.sol pass - +cases/catenable-err.sol fail SC0001 +cases/class-context.sol pass - +cases/class-return-type-miss.sol fail SC0221 +cases/class-type-name-collision.sol fail SC0108 +cases/clone-deriving.sol pass - +cases/closure-capture-only.sol pass - +cases/closure-free-bound-test.sol pass - +cases/closure-free-var-local.sol pass - +cases/closure-free-var-std.sol pass - +cases/closure-free-var.sol pass - +cases/closure.sol pass - +cases/comp.sol fail SC0220 +cases/comparisons.sol pass - +cases/complexproxy.sol fail SC0102 +cases/compose0.sol pass - +cases/compose_desugared.sol fail SC0209 +cases/compound-operators.sol pass - +cases/const-array.sol fail SC0221 +cases/const.sol pass - +cases/constrained-instance-context.sol pass - +cases/constrained-instance.sol pass - +cases/constructor-weak-args.sol pass - +cases/contract-local-derive.sol pass - +cases/contract-local-type-escapes-fail.sol fail SC0103 +cases/contract-local-type-same-name.sol pass - +cases/copytomem.sol pass - +cases/cyclical-defs-inferred.sol pass - +cases/cyclical-defs.sol pass - +cases/default-inst.sol fail SC0102 +cases/default-instance-missing.sol fail SC0102 +cases/default-instance-weak.sol fail SC0102 +cases/derive-custom-hash.sol pass - +cases/derive-eq-action.sol pass - +cases/derive-eq-enum.sol pass - +cases/derive-eq-pair.sol pass - +cases/derive-generic-excluded.sol pass - +cases/derive-generic-sum.sol pass - +cases/derive-universe-instances.sol pass - +cases/derive-unknown-class.sol fail SC0105 +cases/deriving-empty-type.sol pass - +cases/dispatch.sol fail SC0103 +cases/dot-expression-assignment-context.sol pass - +cases/dot-expression-call-arg-context.sol pass - +cases/dot-expression-constructor.sol pass - +cases/dot-expression-match-return.sol pass - +cases/dot-expression-nested-context.sol pass - +cases/dot-expression-no-context-fail.sol fail SC0224 +cases/dot-expression-unknown-fail.sol fail SC0224 +cases/dot-pattern-constructor.sol pass - +cases/dot-pattern-nested-constructor.sol pass - +cases/dot-primitive-constructor.sol pass - +cases/duplicated-contract-name.sol fail SC0108 +cases/duplicated-type-name.sol fail SC0108 +cases/empty-asm.sol pass - +cases/encoder.sol pass - +cases/encoder1.sol pass - +cases/fallback-with-args.sol fail SC0001 +cases/fallback-with-return.sol fail SC0001 +cases/false-redundant-warning.sol pass - +cases/field-access.sol fail SC0201 +cases/field-helper-cxt-collision.sol pass - +cases/field-name-error.sol pass - +cases/foo-class.sol pass - +cases/for-body-shadow.sol pass - +cases/for-break.sol pass - +cases/for-continue.sol pass - +cases/for-empty-init.sol pass - +cases/for-init-shadow.sol pass - +cases/for-inner-block.sol pass - +cases/for-let-post.sol fail SC0001 +cases/for-let.sol pass - +cases/for-loop.sol pass - +cases/for-multi-init.sol pass - +cases/for-multi-post.sol pass - +cases/fresh-pat-arg-synonym.sol pass - +cases/fresh-pat-arg.sol pass - +cases/fresh-variable-shadowing.sol pass - +cases/generic-manual-no-pragma.sol fail - +cases/generic-product-no-pragma.sol fail - +cases/generic-sum-no-pragma.sol fail - +cases/if-examples.sol pass - +cases/import-std.sol pass - +cases/inc-closure.sol pass - +cases/index-example.sol fail SC0108 +cases/instance-closure-error-invalid-member.sol fail SC0201 +cases/instance-closure-error.sol pass - +cases/instance-context-wrong-kind.sol fail SC0299 +cases/instance-synonym-int.sol pass - +cases/instance-synonym.sol pass - +cases/instance-wrong-sig.sol fail SC0299 +cases/invokable-issue.sol pass - +cases/ixa.sol pass - +cases/join.sol pass - +cases/joinErr.sol fail SC0201 +cases/listeq.sol fail SC0220 +cases/listid.sol pass - +cases/ltimp.sol pass - +cases/ltproxy.sol pass - +cases/mainproxy.sol fail SC0102 +cases/match-bitwise.sol pass - +cases/match-compiler-undef-asm.sol fail SC0299 +cases/match-yul.sol pass - +cases/memory.sol pass - +cases/missing-instance.sol fail SC0223 +cases/mod-example.sol pass - +cases/modifier.sol pass - +cases/modulo.sol pass - +cases/monomorphic-require.sol pass - +cases/morefun.sol pass - +cases/mptc-both-templates.sol pass - +cases/mptc-chain-phantom.sol pass - +cases/mptc-guard-extras-concrete.sol pass - +cases/mptc-multi-instance.sol pass - +cases/mptc-nop-mainty-free.sol pass - +cases/mptc-partial-instance.sol pass - +cases/mptc-template-a-only.sol pass - +cases/mptc-template-b-only.sol pass - +cases/multi-stmt-var-leaf.sol pass - +cases/nano-desugared.sol fail SC0108 +cases/nid.sol pass - +cases/noclosure.sol pass - +cases/noconstr.sol fail SC0102 +cases/notif.sol pass - +cases/option2.sol pass - +cases/overlap-synonym-detected.sol fail SC0299 +cases/overlap-synonym-missed-order.sol fail SC0299 +cases/overlap-synonym-missed-two-synonyms.sol fail SC0299 +cases/overlapping-heads.sol fail SC0299 +cases/pair-bug.sol pass - +cases/pars.sol pass - +cases/patterson-bug.sol fail SC0108 +cases/payable-toplevel-function.sol fail SC0001 +cases/phantom-type-return-con.sol pass - +cases/polymatch-error.sol pass - +cases/polymorphic-require.sol pass - +cases/pragma_merge_base.sol pass - +cases/pragma_merge_fail_coverage.sol fail SC0299 +cases/pragma_merge_fail_patterson.sol fail SC0105 +cases/pragma_merge_import.sol fail SC0105 +cases/pragma_merge_verify.sol fail SC0105 +cases/pragma_test_patterson.sol pass - +cases/proxy-desugar.sol pass - +cases/proxy.sol pass - +cases/proxy1.sol fail SC0223 +cases/public-constructor.sol fail SC0001 +cases/public-fallback.sol fail SC0001 +cases/public-top-level-function.sol fail SC0001 +cases/rec.sol pass - +cases/redundant-match.sol pass - +cases/reference-encoding-good.sol pass - +cases/reference-encoding-good1.sol pass - +cases/reference-encoding.sol fail SC0102 +cases/reference-test.sol fail SC0102 +cases/reference.sol fail SC0001 +cases/references-daniel.sol fail SC0102 +cases/require-annotation-contract-method.sol fail SC0220 +cases/require-annotation-missing-both.sol fail SC0220 +cases/require-annotation-missing-param.sol fail SC0220 +cases/require-annotation-missing-return.sol fail SC0220 +cases/require-annotation-mutual.sol fail SC0220 +cases/return-fun-adder.sol pass - +cases/return-fun-bad-arity.sol fail SC0201 +cases/return-fun-bad-param.sol fail SC0201 +cases/return-fun-bad-return.sol fail SC0201 +cases/return-fun-bad-sig.sol fail SC0201 +cases/return-fun-const.sol pass - +cases/return-fun-eq.sol pass - +cases/return-fun-instance.sol pass - +cases/return-fun-not-fun.sol fail SC0201 +cases/same-name-constructor-qualifier.sol pass - +cases/signature.sol fail SC0001 +cases/simpleDiscount.sol pass - +cases/simpleIfExpr.sol fail SC0220 +cases/simpleIfStmt.sol fail SC0220 +cases/simpleid.sol pass - +cases/single-lambda.sol pass - +cases/skolem-let.sol fail SC0209 +cases/snds.sol pass - +cases/spec-fail-ungrounded.sol pass - +cases/storage-adt-mapping-field-fail.sol fail SC0201 +cases/storage-adt-recursive-fail.sol pass - +cases/storage-adt-recursive-ok.sol pass - +cases/strange-unbound.sol pass - +cases/string-const.sol fail SC0220 +cases/subject-index.sol fail SC0108 +cases/subject-reduction.sol fail SC0108 +cases/subsumption-constraint.sol fail SC0223 +cases/subsumption-test.sol fail SC0209 +cases/sum-match-default.sol pass - +cases/super-class-cycle-fail.sol fail SC0223 +cases/super-class-cycle.sol pass - +cases/super-class-num.sol pass - +cases/super-class-recursive-arg.sol fail SC0223 +cases/super-class.sol pass - +cases/synonym-arity-mismatch.sol fail SC0299 +cases/synonym-basic.sol pass - +cases/synonym-in-function.sol pass - +cases/synonym-long-cycle.sol fail SC0299 +cases/synonym-nested.sol pass - +cases/synonym-param.sol pass - +cases/synonym-recursive.sol fail SC0299 +cases/synonym-self-recursive.sol fail SC0299 +cases/tabled-answer-reuse.sol fail SC0299 +cases/tabled-cycle-fail.sol timeout - +cases/tabled-default-instance.sol pass - +cases/tabled-given-order.sol pass - +cases/tabled-left-recursive-fail.sol timeout - +cases/tabled-mutual-chain.sol fail SC0299 +cases/tabled-residual-given.sol pass - +cases/td.sol pass - +cases/tiamat.sol pass - +cases/toplevel-constructor.sol fail SC0001 +cases/toplevel-fallback.sol fail SC0001 +cases/tuple-trick.sol pass - +cases/tuva.sol pass - +cases/tyexp.sol pass - +cases/type-synonym-arg.sol pass - +cases/typedef.sol pass - +cases/ufcs-no-conflict.sol pass - +cases/uintdesugared.sol pass - +cases/unbound-instance-var.sol fail SC0103 +cases/unconstrained-instance.sol fail SC0001 +cases/undefined.sol pass - +cases/unit.sol pass - +cases/user-op-lambda.sol fail SC0001 +cases/vartyped.sol fail SC0220 +cases/weird-error-foo.sol fail SC0220 +cases/weirdfoo.sol fail SC0001 +cases/word-match-default.sol pass - +cases/word-match.sol pass - +cases/xref.sol fail SC0221 +cases/yul-asm-break-continue-leave.sol pass - +cases/yul-asm-for-body.sol pass - +cases/yul-asm-switch-body.sol pass - +cases/yul-deposit-example.sol pass - +cases/yul-for.sol pass - +cases/yul-function-typing.sol pass - +cases/yul-multi-return-arity-fail.sol fail SC0299 +cases/yul-multi-return.sol pass - +cases/yul-return.sol pass - +comptime/CondExpr.sol pass - +comptime/CondStmt.sol pass - +comptime/OneOne.sol fail SC0001 +comptime/OneTwo.sol pass - +comptime/Plus.sol pass - +comptime/Size.sol pass - +comptime/StdSize.sol pass - +comptime/comptime_syntax.sol pass - +comptime/counter.sol pass - +comptime/ct_asm_mem.sol pass - +comptime/ct_asm_ret.sol pass - +comptime/ct_chain_ok.sol pass - +comptime/ct_let_ok.sol pass - +comptime/ct_let_runtime.sol pass - +comptime/ct_overloaded_bad.sol pass - +comptime/ct_overloaded_ok.sol pass - +comptime/ct_param_ok.sol pass - +comptime/ct_param_poly_runtime.sol fail SC0299 +comptime/ct_param_runtime.sol fail - +comptime/ct_runtime_arg.sol pass - +comptime/erc7201-lit.sol pass - +comptime/fib.sol pass - +comptime/fib2.sol pass - +comptime/fib3.sol pass - +comptime/fromInt.sol fail SC0103 +comptime/fromInt2.sol fail SC0103 +comptime/fromInt3.sol fail SC0103 +comptime/fromLit.sol fail SC0103 +comptime/int-untyped-let.sol pass - +comptime/integer-basic.sol pass - +comptime/integer-fib.sol pass - +comptime/integer-from-integer.sol pass - +comptime/integer-lit-class.sol pass - +comptime/integer-lit-cond.sol pass - +comptime/integer-lit-pat.sol pass - +comptime/integer-lit-poly.sol pass - +comptime/integer-lit-safe.sol pass - +comptime/integer-lit-word-site.sol pass - +comptime/integer-lit.sol pass - +comptime/match_labels.sol pass - +comptime/string-concat-mem.sol pass - +comptime/string-lit-dedup.sol pass - +comptime/string-lit-keccak.sol pass - +comptime/string-lit-len.sol pass - +comptime/string-lit-mem.sol pass - +comptime/string-lit-ops.sol pass - +comptime/string-mem-runtime-fail.sol fail SC0201 +comptime/string-param-erasure.sol pass - +comptime/string-user-instance.sol pass - +comptime/uint256-lit.sol pass - +dispatch/Revert.sol pass - +dispatch/abi_address_array.sol pass - +dispatch/abi_array_sum.sol pass - +dispatch/abi_batch_adt.sol pass - +dispatch/abi_bytes_array.sol pass - +dispatch/abi_dyn_sum.sol pass - +dispatch/abi_dyn_sum_return.sol pass - +dispatch/abi_encode_adt.sol pass - +dispatch/abi_encode_types.sol pass - +dispatch/abi_sum_roundtrip.sol pass - +dispatch/array_copy.sol pass - +dispatch/array_nested.sol pass - +dispatch/array_ops.sol pass - +dispatch/array_string.sol pass - +dispatch/arraylit.sol pass - +dispatch/asm_break_continue_leave.sol pass - +dispatch/assembly.sol pass - +dispatch/basic.sol pass - +dispatch/concat.sol pass - +dispatch/counter.sol pass - +dispatch/deposit.sol pass - +dispatch/derive_contract_local.sol pass - +dispatch/derive_ord.sol pass - +dispatch/ecrecover.sol pass - +dispatch/eip712.sol pass - +dispatch/empty.sol pass - +dispatch/empty_no_constructor.sol pass - +dispatch/fallback.sol pass - +dispatch/fib.sol fail SC0103 +dispatch/forloops.sol pass - +dispatch/generic_product.sol pass - +dispatch/generic_sum.sol pass - +dispatch/hashes.sol pass - +dispatch/memory.sol pass - +dispatch/miniERC20.sol pass - +dispatch/neg.sol pass - +dispatch/nonpayable_ctor.sol pass - +dispatch/ownable.sol pass - +dispatch/p256verify.sol pass - +dispatch/payable.sol pass - +dispatch/payable_ctor.sol pass - +dispatch/slices.sol pass - +dispatch/specialise_sum_of_product.sol pass - +dispatch/storage.sol pass - +dispatch/storage_adt_abi.sol pass - +dispatch/storage_adt_bool.sol pass - +dispatch/storage_adt_enum.sol pass - +dispatch/storage_adt_field.sol pass - +dispatch/storage_adt_mapping.sol pass - +dispatch/storage_array.sol pass - +dispatch/storage_dynamic_field.sol pass - +dispatch/stringid.sol pass - +dispatch/stringlit.sol pass - +dispatch/sum_wide_product.sol pass - +dispatch/ufcs_array.sol pass - +dispatch/weth9.sol pass - +invokable/021nid.sol fail SC0220 +invokable/022nid-invoke.sol fail SC0001 +invokable/024lamid.sol fail SC0220 +invokable/025lamid-invoke.sol fail SC0001 +invokable/026capture.sol fail SC0001 +invokable/027retfun.sol fail SC0001 +invokable/028modifier.sol fail SC0001 +invokable/031enum.sol fail SC0001 +opcodes/all-shapes.sol pass - +opcodes/terminators.sol pass - +pragmas/bound.sol fail SC0001 +pragmas/coverage.sol pass - +pragmas/patterson.sol pass - +spec/00answer.sol pass - +spec/010answer.sol fail SC0220 +spec/011id.sol fail SC0220 +spec/012nid.sol fail SC0220 +spec/013comp.sol fail SC0220 +spec/01id.sol pass - +spec/021not.sol pass - +spec/022add.sol pass - +spec/024arith.sol pass - +spec/027sstore.sol fail SC0220 +spec/02nid.sol pass - +spec/031maybe.sol pass - +spec/032simplejoin.sol pass - +spec/033join.sol pass - +spec/034cojoin.sol pass - +spec/035padding.sol pass - +spec/036wildcard.sol pass - spec/037dwarves.solc pass - spec/038food0.solc pass - spec/039food.solc pass - From 07ee4523ece08b8b934455a2d758b756515546f6 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 078/110] Switch the compiler and fixtures to canonical syntax: parser corpus reference frontend.tsv Co-authored-by: Codex --- .../fixtures/corpus/reference-frontend.tsv | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/reference-frontend.tsv b/crates/parser/tests/fixtures/corpus/reference-frontend.tsv index 99ae9dfc..6a41a651 100644 --- a/crates/parser/tests/fixtures/corpus/reference-frontend.tsv +++ b/crates/parser/tests/fixtures/corpus/reference-frontend.tsv @@ -449,52 +449,52 @@ spec/033join.sol pass - spec/034cojoin.sol pass - spec/035padding.sol pass - spec/036wildcard.sol pass - -spec/037dwarves.solc pass - -spec/038food0.solc pass - -spec/039food.solc pass - -spec/041pair.solc pass - -spec/042triple.solc pass - -spec/043fstsnd.solc pass - -spec/047rgb.solc pass - -spec/048rgb2.solc pass - -spec/049rgb3.solc pass - -spec/051expreturn.solc fail SC0103 -spec/051negBool.solc fail SC0102 -spec/052negPair.solc fail SC0001 -spec/052return.solc fail SC0103 -spec/053return.solc fail SC0103 -spec/06comp.solc pass - -spec/09not.solc pass - -spec/101struct1Field.solc fail SC0102 -spec/102uintField.solc fail SC0102 -spec/103struct3Fields.solc fail SC0102 -spec/105nestedStruct.solc fail SC0102 -spec/10negBool.solc pass - -spec/111storageStruct.solc fail SC0102 -spec/112ContractStorage.solc fail SC0105 -spec/113counter.solc fail SC0105 -spec/11negPair.solc pass - -spec/120basicCounter.solc pass - -spec/121counter.solc pass - -spec/122counters.solc pass - -spec/123stackAndStorage.solc pass - -spec/126nanoerc20.solc pass - -spec/127microerc20.solc pass - -spec/128minierc20.solc pass - -spec/129arraystorage.solc pass - -spec/130arrayfield.solc pass - -spec/131constructor.solc fail SC0220 -spec/131localindex.solc pass - -spec/132nestedarray.solc pass - -spec/133arraystring.solc pass - -spec/135aliaspush.solc pass - -spec/135cons3.solc fail SC0108 -spec/136arraylit.solc pass - -spec/137arraylitstorage.solc pass - -spec/903badassign.solc pass - -spec/939badfood.solc pass - -spec/SimpleField.solc pass - -spec/StorageLib.solc fail SC0220 -spec/attic/051expreturn.solc fail SC0001 -spec/attic/052return.solc fail SC0001 -spec/attic/053return.solc fail SC0001 +spec/037dwarves.sol pass - +spec/038food0.sol pass - +spec/039food.sol pass - +spec/041pair.sol pass - +spec/042triple.sol pass - +spec/043fstsnd.sol pass - +spec/047rgb.sol pass - +spec/048rgb2.sol pass - +spec/049rgb3.sol pass - +spec/051expreturn.sol fail SC0103 +spec/051negBool.sol fail SC0102 +spec/052negPair.sol fail SC0001 +spec/052return.sol fail SC0103 +spec/053return.sol fail SC0103 +spec/06comp.sol pass - +spec/09not.sol pass - +spec/101struct1Field.sol fail SC0102 +spec/102uintField.sol fail SC0102 +spec/103struct3Fields.sol fail SC0102 +spec/105nestedStruct.sol fail SC0102 +spec/10negBool.sol pass - +spec/111storageStruct.sol fail SC0102 +spec/112ContractStorage.sol fail SC0105 +spec/113counter.sol fail SC0105 +spec/11negPair.sol pass - +spec/120basicCounter.sol pass - +spec/121counter.sol pass - +spec/122counters.sol pass - +spec/123stackAndStorage.sol pass - +spec/126nanoerc20.sol pass - +spec/127microerc20.sol pass - +spec/128minierc20.sol pass - +spec/129arraystorage.sol pass - +spec/130arrayfield.sol pass - +spec/131constructor.sol fail SC0220 +spec/131localindex.sol pass - +spec/132nestedarray.sol pass - +spec/133arraystring.sol pass - +spec/135aliaspush.sol pass - +spec/135cons3.sol fail SC0108 +spec/136arraylit.sol pass - +spec/137arraylitstorage.sol pass - +spec/903badassign.sol pass - +spec/939badfood.sol pass - +spec/SimpleField.sol pass - +spec/StorageLib.sol fail SC0220 +spec/attic/051expreturn.sol fail SC0001 +spec/attic/052return.sol fail SC0001 +spec/attic/053return.sol fail SC0001 From ea8a2ace0cf90873d735f0bf9337e34475ca3fda Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 079/110] Switch the compiler and fixtures to canonical syntax: parser corpus rust accepted reference failures.tsv Co-authored-by: Codex --- .../rust-accepted-reference-failures.tsv | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/rust-accepted-reference-failures.tsv b/crates/parser/tests/fixtures/corpus/rust-accepted-reference-failures.tsv index c82dc360..fd62a5f5 100644 --- a/crates/parser/tests/fixtures/corpus/rust-accepted-reference-failures.tsv +++ b/crates/parser/tests/fixtures/corpus/rust-accepted-reference-failures.tsv @@ -1,7 +1,17 @@ # pathreason -cases/compose_desugared.solc SC0209 reference rejects the explicitly desugared closure because its inferred invoke implementation is not polymorphic enough; Rust accepts it -cases/for-let-post.solc SC0001 reference frontend rejects this for-loop let form while the Rust grammar accepts it -cases/super-class-recursive-arg.solc SC0223 reference legacy solver rejects this recursive superclass argument, while the reference tabled mode and Rust both accept it -cases/tabled-answer-reuse.solc SC0299 reference legacy solver reports an ambiguous inferred type, while the reference tabled mode and Rust both accept it -cases/tabled-mutual-chain.solc SC0299 reference legacy solver reports an ambiguous inferred type, while the reference tabled mode and Rust both accept it -comptime/ct_param_poly_runtime.solc SC0299 reference legacy frontend reports ambiguity; both tabled Haskell and Rust reject the runtime argument during their full specialization pipelines, while this frontend-only parity gate intentionally defers that check +cases/Enum.sol canonical trait parameters and method result types are explicit, eliminating the reference source's legacy implicit-binder failure +cases/Eq.sol canonical impl method parameter and result types are explicit, eliminating the reference source's legacy signature-inference failure +cases/Filter.sol canonical function and trait signatures are explicit; Rust accepts the resulting fully annotated higher-order program +cases/GoodInstance.sol canonical trait and impl signatures are explicit; Rust accepts the resulting fully annotated enum conversion program +cases/class-return-type-miss.sol canonical omitted results mean unit consistently in both the trait and impl member, so the legacy inferred-result mismatch no longer applies +cases/compose_desugared.sol SC0209 reference rejects the explicitly desugared closure because its inferred invoke implementation is not polymorphic enough; Rust accepts it +cases/for-let-post.sol SC0001 reference frontend rejects this for-loop let form while the Rust grammar accepts it +cases/signature.sol canonical trait parameters and function constraints make every binder explicit, eliminating the reference source's legacy binder failure +cases/super-class-recursive-arg.sol SC0223 reference legacy solver rejects this recursive superclass argument, while the reference tabled mode and Rust both accept it +cases/tabled-answer-reuse.sol SC0299 reference legacy solver reports an ambiguous inferred type, while the reference tabled mode and Rust both accept it +cases/tabled-mutual-chain.sol SC0299 reference legacy solver reports an ambiguous inferred type, while the reference tabled mode and Rust both accept it +comptime/ct_param_poly_runtime.sol SC0299 reference legacy frontend reports ambiguity; both tabled Haskell and Rust reject the runtime argument during their full specialization pipelines, while this frontend-only parity gate intentionally defers that check +comptime/OneOne.sol canonical function result annotations make the formerly inferred word-valued helpers explicit +spec/051negBool.sol canonical named-parameter and result annotations make the formerly inferred signatures explicit +spec/052negPair.sol canonical generics, named-parameter types, and result annotations make the formerly inferred signatures explicit +spec/131constructor.sol canonical public function signatures make the formerly inferred contract entry signatures explicit; Rust accepts the resulting constructor program From d5f06d7aaf42173b1d8e153afb8108c634361d11 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 080/110] Switch the compiler and fixtures to canonical syntax: parser corpus rust rejected reference passes.tsv Co-authored-by: Codex --- .../corpus/rust-rejected-reference-passes.tsv | 182 +++++++++--------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/crates/parser/tests/fixtures/corpus/rust-rejected-reference-passes.tsv b/crates/parser/tests/fixtures/corpus/rust-rejected-reference-passes.tsv index f62ce181..771680a0 100644 --- a/crates/parser/tests/fixtures/corpus/rust-rejected-reference-passes.tsv +++ b/crates/parser/tests/fixtures/corpus/rust-rejected-reference-passes.tsv @@ -1,92 +1,92 @@ # pathphasediagnostic-prefixreason -cases/Uncurry.solc typeck SC0206: non-callable value of type word legacy reference accepts invoking a word-typed parameter; Rust frontend deliberately requires a callable type -cases/contract-local-derive.solc typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-derive.solc typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-derive.solc typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-derive.solc typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-derive.solc typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-derive.solc typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-derive.solc typeck SC0105: undefined class: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/contract-local-type-same-name.solc typeck SC0105: undefined class: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/field-helper-cxt-collision.solc typeck SC0105: undefined class: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ixa.solc typeck SC0221: invalid instance member signature for `size` reference accepts this legacy instance member with a narrowed array signature; Rust frontend enforces the declared class signature -cases/multi-stmt-var-leaf.solc typeck SC0236: contract runtime `main` must not take parameters reference accepts the legacy parameterized contract main form; Rust frontend reserves runtime main as a zero-argument entrypoint -cases/pair-bug.solc typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/pair-bug.solc typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/pair-bug.solc typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/pair-bug.solc typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/pair-bug.solc typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/rec.solc typeck SC0206: non-callable value of type word legacy reference accepts invoking a word-typed parameter; Rust frontend deliberately requires a callable type -cases/storage-adt-recursive-fail.solc typeck SC0207: cannot satisfy class constraint: storage(IntList) : reference verdict used -g and left the constructor/storage obligation unreachable; the Rust full-frontend gate generates dispatch and correctly rejects recursive ADT storage through its CanStore or Assign obligation -cases/ufcs-no-conflict.solc typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ufcs-no-conflict.solc typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ufcs-no-conflict.solc typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ufcs-no-conflict.solc typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ufcs-no-conflict.solc typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ufcs-no-conflict.solc typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -cases/ufcs-no-conflict.solc typeck SC0105: undefined class: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch -dispatch/storage_array.solc typeck SC0231: ABI output cannot be represented in the ABI: adt:DynArray(adt:address) (only memory(string) and memory(bytes) have canonical ABI evidence) reference verdict used -g and skipped ABI validation; Rust deliberately rejects the externally undescribed memory(DynArray(address)) result in its full-frontend gate -dispatch/ufcs_array.solc typeck SC0231: ABI output cannot be represented in the ABI: adt:DynArray(adt:address) (only memory(string) and memory(bytes) have canonical ABI evidence) reference verdict used -g and skipped ABI validation; Rust deliberately rejects the externally undescribed memory(DynArray(address)) result in its full-frontend gate -imports/alias_dup.solc frontend SC0116: duplicate import qualifier `M` intentional negative import fixture for duplicate aliases -imports/alias_hides_original_fail.solc frontend SC0101: undefined name: foo intentional negative import fixture proving an alias hides the original qualifier -imports/alias_unqualified_constr_fail.solc frontend SC0106: unqualified constructor: True intentional negative import fixture proving module imports do not open constructors -imports/alias_unqualified_fun_fail.solc frontend SC0101: undefined name: base intentional negative import fixture proving aliased module imports do not open terms -imports/alias_unqualified_type_fail.solc frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving aliased module imports do not open types -imports/amb_main.solc frontend SC0120: ambiguous selected import `pick` in term namespace intentional negative import fixture for ambiguous selected imports -imports/boolalias_open_fail.solc frontend SC0101: undefined name: not intentional negative import fixture proving an aliased module import is not an open import -imports/boolalias_open_fail.solc frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving an aliased module import is not an open import -imports/boolconselect_fail.solc frontend SC0106: unqualified constructor: True intentional negative import fixture proving a selected type import does not expose its constructors -imports/export_item_dup_fail.solc frontend SC0111: duplicate exported item name `pick` intentional negative import fixture for duplicate item re-exports -imports/export_module_dup_fail.solc frontend SC0112: duplicate exported module name `M` intentional negative import fixture for duplicate module re-exports -imports/external_lib_missing_fail.solc frontend SC0118: external library root is not configured: @missing intentional negative import fixture for an unconfigured external library -imports/external_lib_missing_fail.solc frontend unresolved-import: external_lib_missing_fail imports `@missing.math.api` intentional negative import fixture for an unconfigured external library -imports/external_lib_missing_fail.solc typeck SC0101: undefined name: Contract unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/external_lib_missing_fail.solc typeck SC0101: undefined name: Fallback unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/external_lib_missing_fail.solc typeck SC0101: undefined name: Proxy unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/external_lib_missing_fail.solc typeck SC0101: undefined name: RunContract unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/external_lib_missing_fail.solc typeck SC0101: undefined name: fallback_default_implementation unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/external_lib_missing_fail.solc typeck SC0103: undefined type constructor: NonPayable unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/external_lib_missing_fail.solc typeck SC0103: undefined type constructor: Proxy unresolved external import intentionally causes generated contract-helper cascades in this negative fixture -imports/glob_amb_main_fail.solc frontend SC0120: ambiguous selected import `shared` in term namespace intentional negative import fixture for colliding wildcard imports -imports/glob_import_hiding_unknown_fail.solc frontend SC0110: unknown import item `missing` intentional negative import fixture for hiding an unknown wildcard-imported name -imports/hidden_ctor_dot_fail.solc frontend SC0101: undefined name: Err intentional negative import fixture proving hidden constructors are unavailable to dot syntax -imports/hidden_ctor_expr_fail.solc frontend SC0101: undefined name: Err intentional negative import fixture proving hidden constructors are unavailable in expressions -imports/hidden_ctor_nonexhaustive_fail.solc typeck SC0223: pattern match on type with hidden constructors requires a wildcard arm: Token intentional negative import fixture for exhaustiveness with a partially visible data type -imports/hidden_ctor_pattern_fail.solc frontend SC0101: undefined name: Token.Err intentional negative import fixture proving hidden constructors are unavailable in patterns -imports/leak_b.solc frontend SC0101: undefined name: fromA intentional negative import fixture proving private imported terms do not leak through an intermediate module -imports/leak_main.solc frontend SC0101: undefined name: fromA intentional negative import fixture proving private imported terms do not leak through an intermediate module -imports/leak_main.solc frontend SC0101: undefined name: fromB intentional negative import fixture proving private imported terms do not leak through an intermediate module -imports/module_name_shadow.solc frontend SC0121: conflicting unqualified name `keep` intentional negative import fixture for a module qualifier colliding with a selected term -imports/module_unqualified_constr_fail.solc frontend SC0106: unqualified constructor: True intentional negative import fixture proving module imports do not open constructors -imports/module_unqualified_fun_fail.solc frontend SC0101: undefined name: base intentional negative import fixture proving module imports do not open terms -imports/module_unqualified_type_fail.solc frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving module imports do not open types -imports/opaque_alias_leak_fail.solc frontend SC0103: undefined type constructor: T intentional negative import fixture proving opaque type aliases do not leak through imports -imports/opaque_alias_qualifier_leak_fail.solc frontend SC0103: undefined type constructor: Base.T intentional negative import fixture proving opaque type aliases do not leak through qualifiers -imports/opaque_select_direct_leak_fail.solc frontend SC0103: undefined type constructor: T intentional negative import fixture proving opaque type aliases cannot be selected through re-exports -imports/pragma_scope_main.solc typeck SC0212: Coverage condition fails for class: intentional negative import fixture proving a dependency pragma does not disable checks in its importer -imports/private_bad_lib.solc typeck SC0201: type mismatch: expected word, found bool intentional negative import fixture containing a type error in a private helper body -imports/private_bad_main.solc typeck SC0201: type mismatch: expected word, found bool intentional negative import fixture proving reachable private helper bodies are type-checked -imports/reexport_ctor_expr_hidden_fail.solc frontend SC0101: undefined name: Err intentional negative import fixture proving hidden constructors do not leak through re-exports -imports/reexport_ctor_hidden_fail.solc frontend SC0115: unknown re-exported constructor `Token.Err` intentional negative import fixture for explicitly re-exporting a hidden constructor -imports/select_dup_item.solc frontend SC0117: duplicate name `keep` in selective import intentional negative import fixture for duplicate names in one selective import -imports/select_fail.solc frontend SC0101: undefined name: drop intentional negative import fixture proving unselected terms remain unavailable -imports/select_hiding_fail.solc frontend SC0101: undefined name: drop intentional negative import fixture proving hidden selected terms remain unavailable -imports/select_shadow_local.solc frontend SC0108: duplicate declaration `keep` in term namespace intentional negative import fixture for a selected term colliding with a local declaration -imports/select_unknown.solc frontend SC0110: unknown import item `missing` intentional negative import fixture for an unknown selected item -imports/strict_open_fail.solc frontend SC0101: undefined name: not intentional negative import fixture proving a strict module import is not an open import -imports/strict_open_fail.solc frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving a strict module import is not an open import -imports/symlink_identity_fail.solc typeck SC0201: type mismatch: expected Mirror.T, found T intentional negative import fixture proving equivalent source paths retain distinct module type identities -imports/symlink_impl/api.solc frontend SC0109: import helper: file not found auxiliary symlink fixture is materialized by the module-system test and is not independently complete in the checked-in corpus -imports/symlink_impl/api.solc frontend unresolved-import: failed to read auxiliary symlink fixture is materialized by the module-system test and is not independently complete in the checked-in corpus +cases/Uncurry.sol typeck SC0206: non-callable value of type word legacy reference accepts invoking a word-typed parameter; Rust frontend deliberately requires a callable type +cases/contract-local-derive.sol typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-derive.sol typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-derive.sol typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-derive.sol typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-derive.sol typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-derive.sol typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-derive.sol typeck SC0105: undefined trait: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/contract-local-type-same-name.sol typeck SC0105: undefined trait: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/field-helper-cxt-collision.sol typeck SC0105: undefined trait: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ixa.sol typeck SC0221: invalid impl member signature for `size` reference accepts this legacy impl member with a narrowed array signature; Rust frontend enforces the declared trait signature +cases/multi-stmt-var-leaf.sol typeck SC0236: contract runtime `main` must not take parameters reference accepts the legacy parameterized contract main form; Rust frontend reserves runtime main as a zero-argument entrypoint +cases/pair-bug.sol typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/pair-bug.sol typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/pair-bug.sol typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/pair-bug.sol typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/pair-bug.sol typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/rec.sol typeck SC0206: non-callable value of type word legacy reference accepts invoking a word-typed parameter; Rust frontend deliberately requires a callable type +cases/storage-adt-recursive-fail.sol typeck SC0207: cannot satisfy trait constraint: storage: reference verdict used -g and left the constructor/storage obligation unreachable; the Rust full-frontend gate generates dispatch and correctly rejects recursive ADT storage through its CanStore or Assign obligation +cases/ufcs-no-conflict.sol typeck SC0101: undefined name: Contract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ufcs-no-conflict.sol typeck SC0101: undefined name: Fallback reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ufcs-no-conflict.sol typeck SC0101: undefined name: Method reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ufcs-no-conflict.sol typeck SC0101: undefined name: RunContract reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ufcs-no-conflict.sol typeck SC0101: undefined name: fallback_default_implementation reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ufcs-no-conflict.sol typeck SC0103: undefined type constructor: NonPayable reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +cases/ufcs-no-conflict.sol typeck SC0105: undefined trait: SigString reference verdict used -g and skipped generated dispatch; the Rust full-frontend gate generates it, but this fixture does not import std.dispatch +dispatch/storage_array.sol typeck SC0231: ABI output cannot be represented in the ABI: adt:DynArray (only memory and memory have canonical ABI evidence) reference verdict used -g and skipped ABI validation; Rust deliberately rejects the externally undescribed memory> result in its full-frontend gate +dispatch/ufcs_array.sol typeck SC0231: ABI output cannot be represented in the ABI: adt:DynArray (only memory and memory have canonical ABI evidence) reference verdict used -g and skipped ABI validation; Rust deliberately rejects the externally undescribed memory> result in its full-frontend gate +imports/alias_dup.sol frontend SC0116: duplicate import qualifier `M` intentional negative import fixture for duplicate aliases +imports/alias_hides_original_fail.sol frontend SC0101: undefined name: foo intentional negative import fixture proving an alias hides the original qualifier +imports/alias_unqualified_constr_fail.sol frontend SC0106: unqualified constructor: True intentional negative import fixture proving module imports do not open constructors +imports/alias_unqualified_fun_fail.sol frontend SC0101: undefined name: base intentional negative import fixture proving aliased module imports do not open terms +imports/alias_unqualified_type_fail.sol frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving aliased module imports do not open types +imports/amb_main.sol frontend SC0120: ambiguous selected import `pick` in term namespace intentional negative import fixture for ambiguous selected imports +imports/boolalias_open_fail.sol frontend SC0101: undefined name: not intentional negative import fixture proving an aliased module import is not an open import +imports/boolalias_open_fail.sol frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving an aliased module import is not an open import +imports/boolconselect_fail.sol frontend SC0106: unqualified constructor: True intentional negative import fixture proving a selected type import does not expose its constructors +imports/export_item_dup_fail.sol frontend SC0111: duplicate exported item name `pick` intentional negative import fixture for duplicate item re-exports +imports/export_module_dup_fail.sol frontend SC0112: duplicate exported module name `M` intentional negative import fixture for duplicate module re-exports +imports/external_lib_missing_fail.sol frontend SC0118: external library root is not configured: @missing intentional negative import fixture for an unconfigured external library +imports/external_lib_missing_fail.sol frontend unresolved-import: external_lib_missing_fail imports `@missing.math.api` intentional negative import fixture for an unconfigured external library +imports/external_lib_missing_fail.sol typeck SC0101: undefined name: Contract unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/external_lib_missing_fail.sol typeck SC0101: undefined name: Fallback unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/external_lib_missing_fail.sol typeck SC0101: undefined name: Proxy unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/external_lib_missing_fail.sol typeck SC0101: undefined name: RunContract unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/external_lib_missing_fail.sol typeck SC0101: undefined name: fallback_default_implementation unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/external_lib_missing_fail.sol typeck SC0103: undefined type constructor: NonPayable unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/external_lib_missing_fail.sol typeck SC0103: undefined type constructor: Proxy unresolved external import intentionally causes generated contract-helper cascades in this negative fixture +imports/glob_amb_main_fail.sol frontend SC0120: ambiguous selected import `shared` in term namespace intentional negative import fixture for colliding wildcard imports +imports/glob_import_hiding_unknown_fail.sol frontend SC0110: unknown import item `missing` intentional negative import fixture for hiding an unknown wildcard-imported name +imports/hidden_ctor_dot_fail.sol frontend SC0101: undefined name: Err intentional negative import fixture proving hidden constructors are unavailable to dot syntax +imports/hidden_ctor_expr_fail.sol frontend SC0101: undefined name: Err intentional negative import fixture proving hidden constructors are unavailable in expressions +imports/hidden_ctor_nonexhaustive_fail.sol typeck SC0223: pattern match on type with hidden constructors requires a wildcard arm: Token intentional negative import fixture for exhaustiveness with a partially visible data type +imports/hidden_ctor_pattern_fail.sol frontend SC0101: undefined name: Token.Err intentional negative import fixture proving hidden constructors are unavailable in patterns +imports/leak_b.sol frontend SC0101: undefined name: fromA intentional negative import fixture proving private imported terms do not leak through an intermediate module +imports/leak_main.sol frontend SC0101: undefined name: fromA intentional negative import fixture proving private imported terms do not leak through an intermediate module +imports/leak_main.sol frontend SC0101: undefined name: fromB intentional negative import fixture proving private imported terms do not leak through an intermediate module +imports/module_name_shadow.sol frontend SC0121: conflicting unqualified name `keep` intentional negative import fixture for a module qualifier colliding with a selected term +imports/module_unqualified_constr_fail.sol frontend SC0106: unqualified constructor: True intentional negative import fixture proving module imports do not open constructors +imports/module_unqualified_fun_fail.sol frontend SC0101: undefined name: base intentional negative import fixture proving module imports do not open terms +imports/module_unqualified_type_fail.sol frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving module imports do not open types +imports/opaque_alias_leak_fail.sol frontend SC0103: undefined type constructor: T intentional negative import fixture proving opaque type aliases do not leak through imports +imports/opaque_alias_qualifier_leak_fail.sol frontend SC0103: undefined type constructor: Base.T intentional negative import fixture proving opaque type aliases do not leak through qualifiers +imports/opaque_select_direct_leak_fail.sol frontend SC0103: undefined type constructor: T intentional negative import fixture proving opaque type aliases cannot be selected through re-exports +imports/pragma_scope_main.sol typeck SC0212: Coverage condition fails for trait: intentional negative import fixture proving a dependency pragma does not disable checks in its importer +imports/private_bad_lib.sol typeck SC0201: type mismatch: expected word, found bool intentional negative import fixture containing a type error in a private helper body +imports/private_bad_main.sol typeck SC0201: type mismatch: expected word, found bool intentional negative import fixture proving reachable private helper bodies are type-checked +imports/reexport_ctor_expr_hidden_fail.sol frontend SC0101: undefined name: Err intentional negative import fixture proving hidden constructors do not leak through re-exports +imports/reexport_ctor_hidden_fail.sol frontend SC0115: unknown re-exported constructor `Token.Err` intentional negative import fixture for explicitly re-exporting a hidden constructor +imports/select_dup_item.sol frontend SC0117: duplicate name `keep` in selective import intentional negative import fixture for duplicate names in one selective import +imports/select_fail.sol frontend SC0101: undefined name: drop intentional negative import fixture proving unselected terms remain unavailable +imports/select_hiding_fail.sol frontend SC0101: undefined name: drop intentional negative import fixture proving hidden selected terms remain unavailable +imports/select_shadow_local.sol frontend SC0108: duplicate declaration `keep` in term namespace intentional negative import fixture for a selected term colliding with a local declaration +imports/select_unknown.sol frontend SC0110: unknown import item `missing` intentional negative import fixture for an unknown selected item +imports/strict_open_fail.sol frontend SC0101: undefined name: not intentional negative import fixture proving a strict module import is not an open import +imports/strict_open_fail.sol frontend SC0103: undefined type constructor: Bool intentional negative import fixture proving a strict module import is not an open import +imports/symlink_identity_fail.sol typeck SC0201: type mismatch: expected Mirror.T, found T intentional negative import fixture proving equivalent source paths retain distinct module type identities +imports/symlink_impl/api.sol frontend SC0109: import helper: file not found auxiliary symlink fixture is materialized by the module-system test and is not independently complete in the checked-in corpus +imports/symlink_impl/api.sol frontend unresolved-import: failed to read auxiliary symlink fixture is materialized by the module-system test and is not independently complete in the checked-in corpus From 83bc61ff6d3bdaf52b3b5a82501ad2693dc2466c Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 081/110] Switch the compiler and fixtures to canonical syntax: parser fixtures Co-authored-by: Codex --- .../tests/fixtures/ok/body_return_min.sol | 2 +- .../fixtures/ok/comptime_match_label.sol | 14 ++++--- .../tests/fixtures/ok/comptime_modifier.sol | 6 +-- ...ontract_modifiers_constructor_fallback.sol | 6 +-- .../fixtures/ok/dot_ctor_expr_pattern.sol | 18 +++++---- .../tests/fixtures/ok/expression_bodied.sol | 10 ++--- crates/parser/tests/fixtures/ok/for_loop.sol | 2 +- .../ok/import_alias_operator_hiding.sol | 2 +- .../fixtures/ok/import_external_alias.sol | 2 +- .../fixtures/ok/import_mixed_wildcard.sol | 6 +-- .../fixtures/ok/import_wildcard_selector.sol | 2 +- .../tests/fixtures/ok/match_arm_block.sol | 10 +++-- .../fixtures/ok/match_trailing_semicolon.sol | 8 ++-- .../fixtures/ok/operators_compound_assign.sol | 2 +- .../tests/fixtures/ok/parser_catchup_h.sol | 6 +-- .../tests/fixtures/ok/proxy_expression.sol | 4 +- .../tests/fixtures/ok/proxy_type_sugar.sol | 2 +- ...ualified_constructor_pattern_3_segment.sol | 14 ++++--- .../ok/qualified_constructor_patterns.sol | 20 ++++++---- .../fixtures/ok/qualified_type_return.sol | 2 +- .../tests/fixtures/ok/tuple_unit_sail.sol | 38 +++++++++++-------- 21 files changed, 102 insertions(+), 74 deletions(-) diff --git a/crates/parser/tests/fixtures/ok/body_return_min.sol b/crates/parser/tests/fixtures/ok/body_return_min.sol index fe8c43b6..b5f26d73 100644 --- a/crates/parser/tests/fixtures/ok/body_return_min.sol +++ b/crates/parser/tests/fixtures/ok/body_return_min.sol @@ -1,3 +1,3 @@ -function main() { +function main() returns (word) { return 1; } diff --git a/crates/parser/tests/fixtures/ok/comptime_match_label.sol b/crates/parser/tests/fixtures/ok/comptime_match_label.sol index c039e31f..f405ffc0 100644 --- a/crates/parser/tests/fixtures/ok/comptime_match_label.sol +++ b/crates/parser/tests/fixtures/ok/comptime_match_label.sol @@ -1,6 +1,10 @@ -function classify(x : word) -> word { - match x { - | comptime 1 => return 1; - | _ => return 0; - } +function classify(x: word) returns (word) { + match (x) { +case comptime 1 { +return 1; +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/ok/comptime_modifier.sol b/crates/parser/tests/fixtures/ok/comptime_modifier.sol index 1bbc6bbf..3d9e70d3 100644 --- a/crates/parser/tests/fixtures/ok/comptime_modifier.sol +++ b/crates/parser/tests/fixtures/ok/comptime_modifier.sol @@ -1,13 +1,13 @@ type comptime = word; contract ComptimeModifier { - function f(comptime x : word) -> comptime word { + function f(comptime x: word) returns (comptime) { return x; } - function identifier(x : comptime) -> comptime { + function identifier(x: comptime) returns (comptime) { let comptime : word = 1; - let y : comptime word = f(comptime); + let y : comptime = f(comptime); return y; } } diff --git a/crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.sol b/crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.sol index 1a59df45..3f88a5c8 100644 --- a/crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.sol +++ b/crates/parser/tests/fixtures/ok/contract_modifiers_constructor_fallback.sol @@ -1,11 +1,11 @@ contract Modifiers { constructor() {} - public function ping() -> () {} + function ping() public {} - public payable function deposit() -> uint256 { + function deposit() public payable returns (uint256) { return 0; } - payable fallback() -> () {} + fallback() payable {} } diff --git a/crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.sol b/crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.sol index dac1fb48..2fa6950a 100644 --- a/crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.sol +++ b/crates/parser/tests/fixtures/ok/dot_ctor_expr_pattern.sol @@ -1,12 +1,16 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function mkSome(x: word) -> Option { +function mkSome(x: word) returns (Option) { return .Some(x); } -function fromOption(x: Option) -> word { - match x { - | .Some(v) => return v; - | .None => return 0; - } +function fromOption(x: Option) returns (word) { + match (x) { +case .Some(v) { +return v; +} +case .None { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/ok/expression_bodied.sol b/crates/parser/tests/fixtures/ok/expression_bodied.sol index 377ad401..0388d778 100644 --- a/crates/parser/tests/fixtures/ok/expression_bodied.sol +++ b/crates/parser/tests/fixtures/ok/expression_bodied.sol @@ -1,15 +1,15 @@ -function zero() { +function zero() returns (word) { 0 } -function apply(f, x) { +function apply(f: function(a) returns (b), x: a) returns (b) { f(x) } -function choose(c, a, b) { - if c then a else b +function choose(c: bool, a: a, b: a) returns (a) { + c ? a : b } -function keepThen(then: word) -> word { +function keepThen(then: word) returns (word) { then } diff --git a/crates/parser/tests/fixtures/ok/for_loop.sol b/crates/parser/tests/fixtures/ok/for_loop.sol index fca554cd..8bf38cff 100644 --- a/crates/parser/tests/fixtures/ok/for_loop.sol +++ b/crates/parser/tests/fixtures/ok/for_loop.sol @@ -1,4 +1,4 @@ -function sum10() -> word { +function sum10() returns (word) { let s : word = 0; for (let i = 1; i <= 10; i = i + 1) { s = s + i; diff --git a/crates/parser/tests/fixtures/ok/import_alias_operator_hiding.sol b/crates/parser/tests/fixtures/ok/import_alias_operator_hiding.sol index a6df80bf..60042cec 100644 --- a/crates/parser/tests/fixtures/ok/import_alias_operator_hiding.sol +++ b/crates/parser/tests/fixtures/ok/import_alias_operator_hiding.sol @@ -1 +1 @@ -import mod.{A as B, (^^)} hiding {C}; +import {A as B, (^^)} from mod hiding {C}; diff --git a/crates/parser/tests/fixtures/ok/import_external_alias.sol b/crates/parser/tests/fixtures/ok/import_external_alias.sol index 37da0169..11484c62 100644 --- a/crates/parser/tests/fixtures/ok/import_external_alias.sol +++ b/crates/parser/tests/fixtures/ok/import_external_alias.sol @@ -1 +1 @@ -import @lib.a.b as X; +import * as X from @lib.a.b; diff --git a/crates/parser/tests/fixtures/ok/import_mixed_wildcard.sol b/crates/parser/tests/fixtures/ok/import_mixed_wildcard.sol index 31ded143..6774bea0 100644 --- a/crates/parser/tests/fixtures/ok/import_mixed_wildcard.sol +++ b/crates/parser/tests/fixtures/ok/import_mixed_wildcard.sol @@ -1,3 +1,3 @@ -import glob.{*, idWord}; -import glob2.{idWord, *}; -import glob3.{*, *}; +import * from glob; +import * from glob2; +import * from glob3; diff --git a/crates/parser/tests/fixtures/ok/import_wildcard_selector.sol b/crates/parser/tests/fixtures/ok/import_wildcard_selector.sol index 8bfe2b25..ccd19daf 100644 --- a/crates/parser/tests/fixtures/ok/import_wildcard_selector.sol +++ b/crates/parser/tests/fixtures/ok/import_wildcard_selector.sol @@ -1 +1 @@ -import mod.{*}; +import * from mod; diff --git a/crates/parser/tests/fixtures/ok/match_arm_block.sol b/crates/parser/tests/fixtures/ok/match_arm_block.sol index ae8c80de..31eab5ff 100644 --- a/crates/parser/tests/fixtures/ok/match_arm_block.sol +++ b/crates/parser/tests/fixtures/ok/match_arm_block.sol @@ -1,10 +1,12 @@ -function main(foo: (word, word)) -> word { +function main(foo: (word, word)) returns (word) { let res: word; - match foo { - | (v0, v1) => { + match (foo) { +case (v0, v1) { +{ let x: word = v1; res = x; } - } +} +} return res; } diff --git a/crates/parser/tests/fixtures/ok/match_trailing_semicolon.sol b/crates/parser/tests/fixtures/ok/match_trailing_semicolon.sol index 4cc77387..beff201a 100644 --- a/crates/parser/tests/fixtures/ok/match_trailing_semicolon.sol +++ b/crates/parser/tests/fixtures/ok/match_trailing_semicolon.sol @@ -1,5 +1,7 @@ function f() { - match 0 { - | _ => return (); - }; + match (0) { +default { +return (); +} +} } diff --git a/crates/parser/tests/fixtures/ok/operators_compound_assign.sol b/crates/parser/tests/fixtures/ok/operators_compound_assign.sol index 5ceda12a..c31ffe95 100644 --- a/crates/parser/tests/fixtures/ok/operators_compound_assign.sol +++ b/crates/parser/tests/fixtures/ok/operators_compound_assign.sol @@ -1,4 +1,4 @@ -function operators(x, y, z) { +function operators(x: word, y: word, z: word) returns (word) { let acc = x % y; acc = (acc & y) | (x ^ z); acc += x; diff --git a/crates/parser/tests/fixtures/ok/parser_catchup_h.sol b/crates/parser/tests/fixtures/ok/parser_catchup_h.sol index ab02b9db..85e2c5c6 100644 --- a/crates/parser/tests/fixtures/ok/parser_catchup_h.sol +++ b/crates/parser/tests/fixtures/ok/parser_catchup_h.sol @@ -1,9 +1,9 @@ -data First = First(word); -data Second = Second; +enum First { First(word) } +enum Second { Second } export mod; export mod as M; export mod.{a}; export { T(*) }; -import m.{T}; +import {T} from m; diff --git a/crates/parser/tests/fixtures/ok/proxy_expression.sol b/crates/parser/tests/fixtures/ok/proxy_expression.sol index 853bd1e7..cb0925b5 100644 --- a/crates/parser/tests/fixtures/ok/proxy_expression.sol +++ b/crates/parser/tests/fixtures/ok/proxy_expression.sol @@ -1,6 +1,6 @@ -function main(x: word) -> word { +function main(x: word) returns (word) { let p = @word; let pairProxy = @(word, word); - let annotated = p : @word; + let annotated = p ; return x; } diff --git a/crates/parser/tests/fixtures/ok/proxy_type_sugar.sol b/crates/parser/tests/fixtures/ok/proxy_type_sugar.sol index 35206d4e..2bf9677e 100644 --- a/crates/parser/tests/fixtures/ok/proxy_type_sugar.sol +++ b/crates/parser/tests/fixtures/ok/proxy_type_sugar.sol @@ -1 +1 @@ -function proxy_sig(x: @word) -> @word {} +function proxy_sig(x: @word) returns (@word) {} diff --git a/crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.sol b/crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.sol index cbbc9861..843d6c30 100644 --- a/crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.sol +++ b/crates/parser/tests/fixtures/ok/qualified_constructor_pattern_3_segment.sol @@ -1,6 +1,10 @@ -function main(x: mod.Type.Bool) -> word { - match x { - | mod.Type.True => return 1; - | _ => return 0; - } +function main(x: mod.Type.Bool) returns (word) { + match (x) { +case mod.Type.True { +return 1; +} +default { +return 0; +} +} } diff --git a/crates/parser/tests/fixtures/ok/qualified_constructor_patterns.sol b/crates/parser/tests/fixtures/ok/qualified_constructor_patterns.sol index e7538cd4..b6331ecb 100644 --- a/crates/parser/tests/fixtures/ok/qualified_constructor_patterns.sol +++ b/crates/parser/tests/fixtures/ok/qualified_constructor_patterns.sol @@ -1,11 +1,17 @@ contract QualifiedConstructorPatterns { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function join(mmx) { - match mmx { - | Option.None => return Option.None; - | Option.Some(Option.Some(x)) => return Option.Some(x); - | Option.Some(Option.None) => return Option.None; - } + function join(mmx: Option>) returns (Option) { + match (mmx) { +case Option.None { +return Option.None; +} +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +case Option.Some(Option.None) { +return Option.None; +} +} } } diff --git a/crates/parser/tests/fixtures/ok/qualified_type_return.sol b/crates/parser/tests/fixtures/ok/qualified_type_return.sol index d38bacd5..3ec301e7 100644 --- a/crates/parser/tests/fixtures/ok/qualified_type_return.sol +++ b/crates/parser/tests/fixtures/ok/qualified_type_return.sol @@ -1 +1 @@ -function qualified_ret() -> mod.Type {} +function qualified_ret() returns (mod.Type) {} diff --git a/crates/parser/tests/fixtures/ok/tuple_unit_sail.sol b/crates/parser/tests/fixtures/ok/tuple_unit_sail.sol index 654e2025..edfc217b 100644 --- a/crates/parser/tests/fixtures/ok/tuple_unit_sail.sol +++ b/crates/parser/tests/fixtures/ok/tuple_unit_sail.sol @@ -1,31 +1,37 @@ -data Pair(a, b) = Pair(a, b); +enum Pair { Pair(a, b) } -forall a b . function fst(p : (a, b)) -> a { - match p { - | (x, y) => return x; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (x, y) { +return x; +} +} } -function tupleValue() -> (word, word) { +function tupleValue() returns (word, word) { return (1, 0); } -function unitValue() -> () { +function unitValue() { return (); } -function nestedTupleUnitPattern(p) { - match p { - | ((), (x, y)) => return x; - } +function nestedTupleUnitPattern(p: ((), (word, word))) returns (word) { + match (p) { +case ((), (x, y)) { +return x; +} +} } -function groupedSinglePattern(p) { - match p { - | (y) => return y; - } +function groupedSinglePattern(p: word) returns (word) { + match (p) { +case (y) { +return y; +} +} } -function pairData(x : word, y : word) -> Pair(word, word) { +function pairData(x: word, y: word) returns (Pair) { return Pair(x, y); } From 16a56d14192ba76c142879a08229a0d1894a76d7 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 082/110] Switch the compiler and fixtures to canonical syntax: sonatina Co-authored-by: Codex --- crates/sonatina/tests/e2e.rs | 4 +- crates/sonatina/tests/lowering.rs | 68 +++++++++++++++---------------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/crates/sonatina/tests/e2e.rs b/crates/sonatina/tests/e2e.rs index 7e29dc40..f2eaeb3c 100644 --- a/crates/sonatina/tests/e2e.rs +++ b/crates/sonatina/tests/e2e.rs @@ -31,7 +31,7 @@ type CompiledFixture = (Vec<(OptLevel, Vec)>, E2eExecution); #[dir_test( dir: "$CARGO_MANIFEST_DIR/../../tests/e2e", - glob: "**/main.solc" + glob: "**/main.sol" )] fn sonatina_evm_e2e(fixture: Fixture<&str>) { if !e2e_enabled() { @@ -245,7 +245,7 @@ fn resolve_fixture_directives( } Item::InstanceDef(instance) => { for function in instance.methods(db) { - reject_non_dispatch_directives(db, *function, "instance method")?; + reject_non_dispatch_directives(db, *function, "impl method")?; } } Item::ContractDef(contract) => { diff --git a/crates/sonatina/tests/lowering.rs b/crates/sonatina/tests/lowering.rs index 5bdfe4bc..c5a56697 100644 --- a/crates/sonatina/tests/lowering.rs +++ b/crates/sonatina/tests/lowering.rs @@ -49,7 +49,7 @@ define_frontend_test_db!(SourceTestDb, hir_ty); fn test_span<'db>(db: &'db TestDb) -> Span<'db> { let file = SourceFile::new( db, - "memory:///sonatina_lowering.solc" + "memory:///sonatina_lowering.sol" .parse() .expect("valid URL"), Some(String::new()), @@ -385,7 +385,7 @@ fn source_main_lowers_through_hull_to_verified_ir() { let (_, ir) = lower_source( r#" contract SimpleMain { - function main() -> word { + function main() returns (word) { return 42; } } @@ -403,18 +403,17 @@ fn source_bool_product_sum_and_branches_lower_to_verified_ir() { let (_, ir) = lower_source( r#" contract AggregateContract { - data Choice = Left(word, word) | Right(word); + enum Choice {Left(word, word) , Right(word)} - function runtime_flag() -> bool { + function runtime_flag() returns (bool) { let raw : word; assembly { raw := callvalue() } - match raw { - | 0 => return false; - | _ => return true; - } + match (raw) { + case 0 { return false; } +default { return true; }} } - function choose(flag : bool, x : word, y : word) -> Choice { + function choose(flag : bool, x : word, y : word) returns (Choice) { if (flag) { return Choice.Left(x, y); } else { @@ -422,14 +421,13 @@ contract AggregateContract { } } - function unwrap(value : Choice) -> word { - match value { - | Choice.Left(x, y) => return x; - | Choice.Right(x) => return x; - } + function unwrap(value : Choice) returns (word) { + match (value) { + case Choice.Left(x, y) { return x; } +case Choice.Right(x) { return x; }} } - function main() -> word { + function main() returns (word) { return unwrap(choose(runtime_flag(), 1, 42)); } } @@ -450,7 +448,7 @@ fn contract_object_data_symbols_and_inline_evm_lower_to_verified_ir() { let (_, ir) = lower_source( r#" contract MemoryContract { - function main() -> word { + function main() returns (word) { let result : word; assembly { mstore(0, 42) @@ -476,7 +474,7 @@ fn memoryguard_reserves_aligned_literal_space_through_the_unified_allocator() { let (_, ir) = lower_source( r#" contract MemoryGuardContract { - function main() -> word { + function main() returns (word) { let guarded : word; assembly { mstore(0x40, memoryguard(128)) @@ -550,12 +548,12 @@ fn contract_storage_load_and_store_lower_to_snapshotted_verified_ir() { contract StorageContract { value: word; - function update(next: word) -> word { + function update(next: word) returns (word) { value = next; return value; } - function main() -> word { + function main() returns (word) { return update(42); } } @@ -571,10 +569,10 @@ contract StorageContract { fn source_bit_not_lowers_to_verified_evm_not() { let (_, ir) = lower_source( r#" -import std.{*}; +import * from std; contract BitNotContract { - public function main() -> word { + function main() public returns (word) { let value:word; assembly { value := callvalue() } return ~value; @@ -591,7 +589,7 @@ fn inline_yul_for_init_binding_remains_in_loop_scope() { let (_, ir) = lower_source( r#" contract LoopContract { - function main() -> word { + function main() returns (word) { let result : word; assembly { result := 0 @@ -614,7 +612,7 @@ fn inline_yul_functions_lower_arguments_multi_returns_leave_and_recursion() { let (_, ir) = lower_source( r#" contract InlineYulFunctions { - function main() -> word { + function main() returns (word) { let left : word; let right : word; let result : word; @@ -664,7 +662,7 @@ fn inline_yul_named_returns_preserve_zero_defaults_and_position() { let (_, ir) = lower_source( r#" contract InlineYulNamedReturns { - function main() -> word { + function main() returns (word) { let x : word; let y : word; let z : word; @@ -760,7 +758,7 @@ fn inline_yul_functions_support_forward_calls_and_mutual_recursion() { let (_, ir) = lower_source( r#" contract InlineYulMutualRecursion { - function main() -> word { + function main() returns (word) { let result : word; assembly { result := even(6) @@ -803,7 +801,7 @@ fn inline_yul_call_arguments_evaluate_right_to_left_without_reordering_parameter let (_, ir) = lower_source( r#" contract InlineYulArgumentOrder { - function main() -> word { + function main() returns (word) { let result : word; assembly { function left() -> value { @@ -862,7 +860,7 @@ fn inline_yul_function_names_are_isolated_between_assembly_blocks() { let (_, ir) = lower_source( r#" contract InlineYulFunctionScopes { - function main() -> word { + function main() returns (word) { let result : word; assembly { function value() -> result { result := 1 } @@ -1049,26 +1047,26 @@ fn inline_yul_functions_do_not_inherit_outer_loop_targets() { fn polymorphic_yul_terminators_end_value_returning_functions() { let (_, ir) = lower_source( r#" -forall a . function viaStop() -> a { +function viaStop() returns (a) { assembly { stop() } } -forall a . function viaInvalid() -> a { +function viaInvalid() returns (a) { assembly { invalid() } } -forall a . function viaSelfdestruct(beneficiary : word) -> a { +function viaSelfdestruct(beneficiary : word) returns (a) { assembly { selfdestruct(beneficiary) } } -forall a . function viaRevert() -> a { +function viaRevert() returns (a) { assembly { revert(0, 0) } } -function useWord(value : word) -> () {} +function useWord(value : word) returns () {} contract Terminators { - public function main() -> () { + function main() public returns () { useWord(viaStop()); useWord(viaInvalid()); useWord(viaSelfdestruct(0)); @@ -1090,9 +1088,9 @@ contract Terminators { fn literal_revert_preserves_its_payload() { let (_, ir) = lower_source_with_file_url_imports( r#" -import std.{*}; +import * from std; -function main() -> () { +function main() returns () { revertLit("regression"); } "#, From 076075234fdcb83fcd0336ef684f30253269bb4d Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 083/110] Switch the compiler and fixtures to canonical syntax: specialize Co-authored-by: Codex --- crates/specialize/src/evaluate/erasure.rs | 2 +- crates/specialize/src/ir.rs | 4 +- crates/specialize/src/specialize/body.rs | 8 +- .../specialize/src/specialize/diagnostics.rs | 4 +- crates/specialize/tests/specialize.rs | 881 +++++++++--------- 5 files changed, 445 insertions(+), 454 deletions(-) diff --git a/crates/specialize/src/evaluate/erasure.rs b/crates/specialize/src/evaluate/erasure.rs index f77120e8..0c74d593 100644 --- a/crates/specialize/src/evaluate/erasure.rs +++ b/crates/specialize/src/evaluate/erasure.rs @@ -148,7 +148,7 @@ fn is_runtime_string_location<'db>( if name == "storage" && is_canonical_std_def_named(db, def, "storage") { // Every storage reference has a one-word runtime representation. Its // payload is a layout tag and may recursively contain the source-only - // `string` tag (for example storage(array(string))). Do not treat that + // `string` tag (for example `storage>`). Do not treat that // nested tag as a runtime comptime-string value. return true; } diff --git a/crates/specialize/src/ir.rs b/crates/specialize/src/ir.rs index 687d083d..57adfe9d 100644 --- a/crates/specialize/src/ir.rs +++ b/crates/specialize/src/ir.rs @@ -126,7 +126,7 @@ pub enum MonoIntrinsic { KeccakLit, KeccakWordLit, /// Runtime materialization of a compile-time string literal into - /// `memory(string)`. This marker is deliberately not foldable: Hull + /// `memory`. This marker is deliberately not foldable: Hull /// replaces it with a call to a generated allocator. MemStringFromLit, /// Runtime revert carrying the bytes of a compile-time string literal. @@ -439,7 +439,7 @@ pub enum MonoExprKind<'db> { base: Box>, index: Box>, }, - /// Checked read from a `memory(DynArray(t))` value. + /// Checked read from a `memory>` value. MemoryArrayIndex { base: Box>, index: Box>, diff --git a/crates/specialize/src/specialize/body.rs b/crates/specialize/src/specialize/body.rs index 1fb1fcd7..42d8c277 100644 --- a/crates/specialize/src/specialize/body.rs +++ b/crates/specialize/src/specialize/body.rs @@ -1910,11 +1910,11 @@ impl<'a, 'db> BodyCtx<'a, 'db> { }; Some(MonoExpr { span, - ty: self.driver.mono_ty(result_ty, "class call result", span)?, + ty: self.driver.mono_ty(result_ty, "trait call result", span)?, kind: MonoExprKind::Call { callee: MonoId { name, - ty: self.driver.mono_ty(callee_ty, "class call callee", span)?, + ty: self.driver.mono_ty(callee_ty, "trait call callee", span)?, span, }, args, @@ -1965,13 +1965,13 @@ impl<'a, 'db> BodyCtx<'a, 'db> { span, ty: self .driver - .mono_ty(result_ty, "contract field class call result", span)?, + .mono_ty(result_ty, "contract field trait call result", span)?, kind: MonoExprKind::Call { callee: MonoId { name, ty: self .driver - .mono_ty(callee_ty, "contract field class call callee", span)?, + .mono_ty(callee_ty, "contract field trait call callee", span)?, span, }, args, diff --git a/crates/specialize/src/specialize/diagnostics.rs b/crates/specialize/src/specialize/diagnostics.rs index 006a94a2..2f62f1f9 100644 --- a/crates/specialize/src/specialize/diagnostics.rs +++ b/crates/specialize/src/specialize/diagnostics.rs @@ -121,8 +121,8 @@ impl SpecializeDiagnosticKind<'_> { Self::TypeSizeExceeded { .. } => "specialization type size limit reached here", Self::MissingBody { .. } => "function body required here", Self::MissingResolution { .. } => "name resolution required here", - Self::MissingEvidence { .. } => "class evidence required here", - Self::UnsupportedEvidence { .. } => "unsupported class evidence here", + Self::MissingEvidence { .. } => "trait evidence required here", + Self::UnsupportedEvidence { .. } => "unsupported trait evidence here", Self::UnresolvedExternal { .. } => "external function required here", Self::ComptimeEvaluationFailed { .. } => "comptime evaluation failed here", Self::ComptimeFuelExhausted { .. } => "comptime fuel limit reached here", diff --git a/crates/specialize/tests/specialize.rs b/crates/specialize/tests/specialize.rs index 94818afa..a46959c1 100644 --- a/crates/specialize/tests/specialize.rs +++ b/crates/specialize/tests/specialize.rs @@ -104,7 +104,7 @@ impl nameres::Db for TestDb { impl hir_ty::Db for TestDb {} fn source_file(db: &TestDb, name: &str, src: &str) -> SourceFile { - let url = format!("memory:///{name}.solc").parse().expect("valid URL"); + let url = format!("memory:///{name}.sol").parse().expect("valid URL"); SourceFile::new(db, url, Some(src.to_owned())) } @@ -162,7 +162,7 @@ fn specialize_src_with_std_and_db_options( db, [main_root.as_path(), std_root.as_path()], )); - let main_path = main_root.join("main.solc"); + let main_path = main_root.join("main.sol"); let key = module_key_for_path(LibraryId::Main, &main_root, &main_path).expect("file under main root"); let file = source_file_at_path(db, &main_path, src); @@ -187,42 +187,41 @@ fn specialize_src_with_fake_calldata_array_std( BTreeMap::new(), )); - let std_path = std_root.join("std.solc"); - let main_path = main_root.join("main.solc"); + let std_path = std_root.join("std.sol"); + let main_path = main_root.join("main.sol"); let std_file = source_file_at_path( db, &std_path, r#" export { calldata(*), array(*), uint256(*), Encoded(*), Decoded(*), Typedef, RValueIdxAccess }; -data calldata(t) = calldata(word); -data array(t) = array(word); -data uint256 = uint256(word); -data Encoded = Encoded(word); -data Decoded = Decoded(word); +enum calldata {calldata(word)} +enum array {array(word)} +enum uint256 {uint256(word)} +enum Encoded {Encoded(word)} +enum Decoded {Decoded(word)} -forall abs rep . class abs:Typedef(rep) { - function abs(x:rep) -> abs; - function rep(x:abs) -> rep; +trait Typedef { + function abs(x:rep) returns (abs) ; + function rep(x:abs) returns (rep) ; } -forall t . default instance t:Typedef(t) { - function abs(x:t) -> t { return x; } - function rep(x:t) -> t { return x; } +default impl Typedef { + function abs(x:t) returns (t) { return x; } + function rep(x:t) returns (t) { return x; } } -instance uint256:Typedef(word) { - function abs(x:word) -> uint256 { return uint256(x); } - function rep(x:uint256) -> word { return 0; } +impl Typedef { + function abs(x:word) returns (uint256) { return uint256(x); } + function rep(x:uint256) returns (word) { return 0; } } -forall col_idx val . class col_idx:RValueIdxAccess(val) { - function lookup(xi:col_idx) -> val; +trait RValueIdxAccess { + function lookup(xi:col_idx) returns (val) ; } -forall i . i:Typedef(word) => -instance (calldata(array(Encoded)), i):RValueIdxAccess(Decoded) { - function lookup(xi:(calldata(array(Encoded)), i)) -> Decoded { +impl RValueIdxAccess<(calldata>, i),Decoded> where i: Typedef { + function lookup(xi:(calldata>, i)) returns (Decoded) { let value:word; assembly { value := calldataload(0) } return Decoded(value); @@ -261,7 +260,7 @@ fn function_names(output: &SpecializeOutput<'_>) -> Vec { fn specializes_large_linear_body_with_indexed_frontend_lookups() { use std::fmt::Write as _; - let mut source = "function main() -> word {\n let value0 : word = 0;\n".to_owned(); + let mut source = "function main() returns (word) {\n let value0 : word = 0;\n".to_owned(); for index in 1..2_000 { writeln!( &mut source, @@ -282,9 +281,9 @@ fn specializes_large_linear_body_with_indexed_frontend_lookups() { fn calldata_array_index_specializes_to_rvalue_lookup_call() { let (db, output) = specialize_src_with_fake_calldata_array_std( r#" -import std.{*}; +import * from std; -function main(xs:calldata(array(Encoded)), i:uint256) -> Decoded { +function main(xs:calldata>, i:uint256) returns (Decoded) { return xs[i]; } "#, @@ -396,11 +395,11 @@ fn naming_matches_reference_mangling() { fn specialized_name_hash_is_independent_of_absolute_module_root() { let src = r#" contract C { - public function main() -> word { return 42; } + function main() public returns (word) { return 42; } } "#; - let left = specialize_source_at_root(Path::new("/workspace-a/project"), "src/main.solc", src); - let right = specialize_source_at_root(Path::new("/workspace-b/project"), "src/main.solc", src); + let left = specialize_source_at_root(Path::new("/workspace-a/project"), "src/main.sol", src); + let right = specialize_source_at_root(Path::new("/workspace-b/project"), "src/main.sol", src); assert_eq!(left.diagnostics, Vec::new()); assert_eq!(right.diagnostics, Vec::new()); @@ -411,10 +410,10 @@ contract C { fn deduplicates_identical_instantiations() { let (_db, output) = specialize_src( r#" -forall a . function id(x:a) -> a { return x; } +function id(x:a) returns (a) { return x; } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { let a = id(x); let b = id(a); return b; @@ -438,30 +437,30 @@ contract C { fn evidence_replay_resolves_instance_and_superclass_methods() { let (_db, output) = specialize_src( r#" -data Bool = True | False; +enum Bool {True , False} -forall a . class a:Eq { - function eq(x:a, y:a) -> Bool; +trait Eq { + function eq(x:a, y:a) returns (Bool) ; } -forall a . a:Eq => class a:Ord { - function lt(x:a, y:a) -> Bool; +trait Ord where a: Eq { + function lt(x:a, y:a) returns (Bool) ; } -instance word:Eq { - function eq(x:word, y:word) -> Bool { return primEqWord(x, y); } +impl Eq { + function eq(x:word, y:word) returns (Bool) { return primEqWord(x, y); } } -instance word:Ord { - function lt(x:word, y:word) -> Bool { return Bool.False; } +impl Ord { + function lt(x:word, y:word) returns (Bool) { return Bool.False; } } -forall a . a:Ord => function same(x:a) -> Bool { +function same(x:a) returns (Bool) where a: Ord { return Eq.eq(x, x); } contract C { - public function main(x:word) -> Bool { + function main(x:word) public returns (Bool) { return same(x); } } @@ -488,18 +487,18 @@ contract C { fn evidence_replay_preserves_class_method_local_forall_binders() { let (_db, output) = specialize_src( r#" -forall b . class b:IsA { - forall a . function ais(x : a, witness : b) -> a; +trait IsA { + function ais(x : a, witness : b) returns (a) ; } -instance word:IsA { - forall a . function ais(x : a, witness : word) -> a { +impl IsA { + function ais(x : a, witness : word) returns (a) { return x; } } contract C { - public function main(x : word) -> word { + function main(x : word) public returns (word) { return IsA.ais(x, 0); } } @@ -520,23 +519,23 @@ contract C { fn field_ufcs_prepends_receiver_and_resolves_instance_method() { let (db, _, output) = specialize_src_with_std_and_db( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -forall a . class a:Combiner { - function combine(x:a, y:uint256) -> uint256; +trait Combiner { + function combine(x:a, y:uint256) returns (uint256) ; } -instance storage(array(uint256)):Combiner { - function combine(x:storage(array(uint256)), y:uint256) -> uint256 { return y; } +impl Combiner>> { + function combine(x:storage>, y:uint256) returns (uint256) { return y; } } contract C { - value:array(uint256); + value:array; constructor() {} - public function viaUfcs(y:uint256) -> uint256 { + function viaUfcs(y:uint256) public returns (uint256) { return value.combine(y); } } @@ -611,24 +610,24 @@ contract C { fn local_and_parameter_ufcs_prepend_receivers_and_share_instance_method() { let (db, output) = specialize_src( r#" -forall a . class a:Combiner { - function combine(x:a, y:word) -> word; +trait Combiner { + function combine(x:a, y:word) returns (word) ; } -instance word:Combiner { - function combine(x:word, y:word) -> word { return y; } +impl Combiner { + function combine(x:word, y:word) returns (word) { return y; } } -function viaParam(paramReceiver:word, paramArg:word) -> word { +function viaParam(paramReceiver:word, paramArg:word) returns (word) { return paramReceiver.combine(paramArg); } -function viaLocal(seed:word, localArg:word) -> word { +function viaLocal(seed:word, localArg:word) returns (word) { let localReceiver:word = seed; return localReceiver.combine(localArg); } -function main(x:word, y:word) -> word { +function main(x:word, y:word) returns (word) { return viaParam(viaLocal(x, y), y); } "#, @@ -712,20 +711,20 @@ fn evidence_replay_resolves_imported_instance_methods() { BTreeMap::new(), )); db.module_fs_snapshot = Some(module_fs_snapshot_for_roots(db, [main_root.as_path()])); - let lib_path = main_root.join("lib.solc"); - let main_path = main_root.join("main.solc"); + let lib_path = main_root.join("lib.sol"); + let main_path = main_root.join("main.sol"); let lib_file = source_file_at_path( db, &lib_path, r#" export { Boxed }; -forall a . class a:Boxed { - function id(x:a) -> a; +trait Boxed { + function id(x:a) returns (a) ; } -instance word:Boxed { - function id(x:word) -> word { return x; } +impl Boxed { + function id(x:word) returns (word) { return x; } } "#, ); @@ -733,10 +732,10 @@ instance word:Boxed { db, &main_path, r#" -import lib.{Boxed}; +import {Boxed} from lib; contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { return Boxed.id(x); } } @@ -774,53 +773,53 @@ fn same_named_classes_in_different_modules_get_distinct_method_symbols() { let modules = [ ( - "left.solc", + "left.sol", r#" export { left }; -forall a . class a:Pick { - function choose(x:a) -> word; +trait Pick { + function choose(x:a) returns (word) ; } -instance word:Pick { - function choose(x:word) -> word { +impl Pick { + function choose(x:word) returns (word) { let y : word; assembly { y := sload(x) } return y; } } -function left(x:word) -> word { return Pick.choose(x); } +function left(x:word) returns (word) { return Pick.choose(x); } "#, ), ( - "right.solc", + "right.sol", r#" export { right }; -forall a . class a:Pick { - function choose(x:a) -> word; +trait Pick { + function choose(x:a) returns (word) ; } -instance word:Pick { - function choose(x:word) -> word { +impl Pick { + function choose(x:word) returns (word) { let y : word; assembly { y := sload(x) } return x; } } -function right(x:word) -> word { return Pick.choose(x); } +function right(x:word) returns (word) { return Pick.choose(x); } "#, ), ( - "main.solc", + "main.sol", r#" -import left.{left}; -import right.{right}; +import {left} from left; +import {right} from right; contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { let unused = right(x); return left(x); } @@ -835,7 +834,7 @@ contract C { let file = source_file_at_path(db, &path, src); let key = module_key_for_path(LibraryId::Main, &main_root, &path).unwrap(); db.insert_module_file(key, file); - if name == "main.solc" { + if name == "main.sol" { main_file = Some(file); } } @@ -865,43 +864,43 @@ fn same_named_adts_in_different_modules_get_distinct_generic_symbols() { let modules = [ ( - "common.solc", + "common.sol", r#" export { id }; -forall a . function id(x:a) -> a { return x; } +function id(x:a) returns (a) { return x; } "#, ), ( - "left.solc", + "left.sol", r#" -import common.{id}; +import {id} from common; export { left }; -data Foo = Foo(word); -function left(x:word) -> word { +enum Foo {Foo(word)} +function left(x:word) returns (word) { let value : Foo = id(Foo(x)); - match value { | Foo(result) => return result; } + match (value) { case Foo(result) { return result; }} } "#, ), ( - "right.solc", + "right.sol", r#" -import common.{id}; +import {id} from common; export { right }; -data Foo = Foo(word); -function right(x:word) -> word { +enum Foo {Foo(word)} +function right(x:word) returns (word) { let value : Foo = id(Foo(x)); - match value { | Foo(result) => return result; } + match (value) { case Foo(result) { return result; }} } "#, ), ( - "main.solc", + "main.sol", r#" -import left.{left}; -import right.{right}; +import {left} from left; +import {right} from right; contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { let unused = right(x); return left(x); } @@ -916,7 +915,7 @@ contract C { let file = source_file_at_path(db, &path, src); let key = module_key_for_path(LibraryId::Main, &main_root, &path).unwrap(); db.insert_module_file(key, file); - if name == "main.solc" { + if name == "main.sol" { main_file = Some(file); } } @@ -944,8 +943,8 @@ fn derived_generic_specialization_uses_the_imported_adt_definition_module() { BTreeMap::new(), )); db.module_fs_snapshot = Some(module_fs_snapshot_for_roots(db, [main_root.as_path()])); - let lib_path = main_root.join("lib.solc"); - let main_path = main_root.join("main.solc"); + let lib_path = main_root.join("lib.sol"); + let main_path = main_root.join("main.sol"); let lib_file = source_file_at_path( db, &lib_path, @@ -955,14 +954,14 @@ pragma no-bounded-variable-condition; export { Box(*), exercise }; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -data Box = Box(word, bool); +enum Box {Box(word, bool)} -function exercise(x:Box) -> Box { +function exercise(x:Box) returns (Box) { let rep : (word, bool) = Generic.from(x); return Generic.to(rep); } @@ -972,10 +971,10 @@ function exercise(x:Box) -> Box { db, &main_path, r#" -import lib.{*}; +import * from lib; contract C { - function main(x:Box) -> Box { return exercise(x); } + function main(x:Box) returns (Box) { return exercise(x); } } "#, ); @@ -1007,26 +1006,26 @@ contract C { fn invokable_invoke_replays_call_site_evidence() { let (_db, output) = specialize_src( r#" -forall a b c . c : invokable(a, b) => function app(f : c, x : a) -> b { +function app(f : c, x : a) returns (b) where c : invokable { return invokable.invoke(f, x); } -data t_id = t_id; +enum t_id {t_id} -function impure(x : word) -> word { +function impure(x : word) returns (word) { let y : word; assembly { y := sload(x) } return y; } -instance t_id : invokable(word, word) { - function invoke(self : t_id, x : word) -> word { +impl invokable { + function invoke(self : t_id, x : word) returns (word) { return impure(x); } } contract C { - public function main(x : word) -> word { + function main(x : word) public returns (word) { return app(t_id, x); } } @@ -1057,42 +1056,39 @@ contract C { fn mptc_phantom_extras_recovered_before_naming_and_body_lowering() { let (_db, output) = specialize_src( r#" -data Foo = Foo(word); +enum Foo {Foo(word)} -forall self rep. -class self:Encoder(rep) { - function encode(x:self, hint:word) -> rep; +trait Encoder { + function encode(x:self, hint:word) returns (rep) ; } -forall rep r. -class rep:Sink(r) { - function sink(x:rep) -> r; +trait Sink { + function sink(x:rep) returns (r) ; } -instance Foo:Encoder(word) { - function encode(x:Foo, hint:word) -> word { +impl Encoder { + function encode(x:Foo, hint:word) returns (word) { let y : word; assembly { y := sload(hint) } - match x { | Foo(v) => return v; } + match (x) { case Foo(v) { return v; }} } } -instance word:Sink(word) { - function sink(x:word) -> word { +impl Sink { + function sink(x:word) returns (word) { let y : word; assembly { y := sload(x) } return x; } } -forall a rep . a:Encoder(rep), rep:Sink(word) => -function f(x:a) -> word { +function f(x:a) returns (word) where a: Encoder, rep: Sink { let r : rep = Encoder.encode(x, 0); return Sink.sink(r); } contract C { - public function main(x : word) -> word { + function main(x : word) public returns (word) { return f(Foo(x)); } } @@ -1125,33 +1121,31 @@ contract C { fn instance_method_names_include_the_complete_class_head() { let (_db, output) = specialize_src( r#" -data Box = Box(word); +enum Box {Box(word)} -forall self rep. -class self:Convert(rep) { - function toRep(x:self) -> rep; - function fromRep(x:rep) -> self; +trait Convert { + function toRep(x:self) returns (rep) ; + function fromRep(x:rep) returns (self) ; } -instance Box:Convert(word) { - function toRep(x:Box) -> word { - match x { | Box(w) => return w; } +impl Convert { + function toRep(x:Box) returns (word) { + match (x) { case Box(w) { return w; }} } - function fromRep(x:word) -> Box { + function fromRep(x:word) returns (Box) { return Box(x); } } -forall a rep . a:Convert(rep) => -function roundtrip(x:a) -> a { +function roundtrip(x:a) returns (a) where a: Convert { let r : rep = Convert.toRep(x); return Convert.fromRep(r); } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { let b : Box = roundtrip(Box(x)); - match b { | Box(w) => return w; } + match (b) { case Box(w) { return w; }} } } "#, @@ -1179,13 +1173,13 @@ contract C { fn ensure_closed_failure_aborts_that_specialization() { let (_db, output) = specialize_src( r#" -forall a . function leak() -> a { +function leak() returns (a) { let y : a; return y; } contract C { - public function main() -> () { + function main() public returns () { let x = leak(); return (); } @@ -1213,11 +1207,11 @@ contract C { #[test] fn generated_contract_dispatch_uses_explicit_std_dispatch_import() { let source = r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - public function answer() -> uint256 { return uint256(1); } + function answer() public returns (uint256) { return uint256(1); } } "#; let output = specialize_src_with_std(source); @@ -1250,11 +1244,11 @@ contract C { fn generated_contract_dispatch_rejects_public_comptime_params_before_runtime_rooting() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - public function answer(comptime x: word) -> word { + function answer(comptime x: word) public returns (word) { return x; } } @@ -1296,11 +1290,11 @@ contract C { #[test] fn generated_contract_dispatch_keeps_the_original_source_file() { let src = r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(1); } } @@ -1365,12 +1359,12 @@ contract C { #[test] fn already_prepared_input_keeps_std_dispatch_origin() { let src = r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { - payable constructor(seed: uint256) { let saved = seed; } - public function answer() -> uint256 { return uint256(1); } + constructor(seed: uint256) payable { let saved = seed; } + function answer() public returns (uint256) { return uint256(1); } } "#; let (db, file, _) = specialize_src_with_std_and_db(src); @@ -1404,8 +1398,8 @@ contract C { fn source_names_are_qualified_across_contracts() { let (_db, output) = specialize_src( r#" -contract A { public function main() -> word { return 1; } } -contract B { public function main() -> word { return 2; } } +contract A { function main() public returns (word) { return 1; } } +contract B { function main() public returns (word) { return 2; } } "#, ); @@ -1448,13 +1442,13 @@ contract B { public function main() -> word { return 2; } } fn dispatch_abi_shape_is_preserved_in_std_dispatch_mono_ir() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PayableTest { constructor() {} - public payable function deposit() -> uint256 { return uint256(1); } - payable fallback() -> () {} + function deposit() public payable returns (uint256) { return uint256(1); } + fallback() payable {} } "#, ); @@ -1515,11 +1509,11 @@ contract PayableTest { fn tuple_dispatch_uses_the_canonical_abi_selector() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract TupleSelector { - public function pack(point: (uint256, uint256), tag: uint256) -> uint256 { + function pack(point: (uint256, uint256), tag: uint256) public returns (uint256) { return tag; } } @@ -1555,33 +1549,33 @@ contract TupleSelector { fn dispatch_selector_patch_uses_identity_safe_method_markers() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; -data XDispatchNameTy_D_veryLongX = Wrapped(uint256); +enum XDispatchNameTy_D_veryLongX {Wrapped(uint256)} contract C { - public function putOpt(k: uint256, v: uint256) -> () { return (); } - public function putOptPair(k: uint256, a: uint256, b: uint256) -> () { return (); } - public function clearOpt(k: uint256) -> () { return (); } - public function clearOptPair(k: uint256) -> () { return (); } - public function foo(k: uint256) -> () { return (); } - public function foo_bar(k: uint256, v: uint256) -> () { return (); } - public function f(x: XDispatchNameTy_D_veryLongX) -> uint256 { return 7; } + function putOpt(k: uint256, v: uint256) public returns () { return (); } + function putOptPair(k: uint256, a: uint256, b: uint256) public returns () { return (); } + function clearOpt(k: uint256) public returns () { return (); } + function clearOptPair(k: uint256) public returns () { return (); } + function foo(k: uint256) public returns () { return (); } + function foo_bar(k: uint256, v: uint256) public returns () { return (); } + function f(x: XDispatchNameTy_D_veryLongX) public returns (uint256) { return 7; } } contract D { - public function veryLong(k: uint256) -> uint256 { return k; } + function veryLong(k: uint256) public returns (uint256) { return k; } } contract A { - public function B_C(k: uint256) -> uint256 { return k; } + function B_C(k: uint256) public returns (uint256) { return k; } } contract A_B { - public function C(k: uint256) -> uint256 { return k; } + function C(k: uint256) public returns (uint256) { return k; } } "#, ); @@ -1669,12 +1663,12 @@ contract A_B { fn constructor_overlay_roots_three_argument_deployment_main() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor(x : uint256, y : uint256, z : uint256) { let saved = x; } - function main() -> () { return (); } + function main() returns () { return (); } } "#, ); @@ -1713,7 +1707,7 @@ contract C { fn specializes_reference_constructor_and_dispatch_collision_regressions() { let repo = repo_root(); let corpus = repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch"); - for fixture in ["miniERC20.solc", "weth9.solc"] { + for fixture in ["miniERC20.sol", "weth9.sol"] { let output = specialize_fixture(&corpus.join(fixture)); assert_eq!(output.diagnostics, Vec::new(), "{fixture}"); } @@ -1723,15 +1717,15 @@ fn specializes_reference_constructor_and_dispatch_collision_regressions() { fn mono_ir_carries_frontend_desugar_hook_plan() { let repo = repo_root(); let storage = specialize_fixture( - &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.solc"), + &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/dispatch/storage.sol"), ); let lambda = specialize_fixture( - &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.solc"), + &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SimpleLambda.sol"), ); let (_if_db, if_output) = specialize_src( r#" contract C { - public function main() -> word { + function main() public returns (word) { if (true) { return 1; } else { return 0; } } } @@ -1784,11 +1778,10 @@ fn tuple_syntax_specializes_through_product_constructors() { let (_db, output) = specialize_src( r#" contract C { - public function main(x:word, y:word, z:word) -> pair(word, pair(word, word)) { + function main(x:word, y:word, z:word) public returns (pair>) { let t = (x, y, z); - match t { - | (a, b, c) => return (a, b, c); - } + match (t) { + case (a, b, c) { return (a, b, c); }} } } "#, @@ -1831,25 +1824,25 @@ fn specializes_p7_cited_regression_corpus() { let repo = repo_root(); let corpus = repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples"); for fixture in [ - "cases/app.solc", - "cases/mptc-chain-phantom.solc", - "cases/mptc-both-templates.solc", - "dispatch/nonpayable_ctor.solc", - "dispatch/storage.solc", - "cases/SimpleLambda.solc", - "dispatch/specialise_sum_of_product.solc", + "cases/app.sol", + "cases/mptc-chain-phantom.sol", + "cases/mptc-both-templates.sol", + "dispatch/nonpayable_ctor.sol", + "dispatch/storage.sol", + "cases/SimpleLambda.sol", + "dispatch/specialise_sum_of_product.sol", ] { let output = specialize_fixture(&corpus.join(fixture)); assert_eq!(output.diagnostics, Vec::new(), "{fixture}"); } - let basic = specialize_fixture(&corpus.join("dispatch/basic.solc")); - assert_eq!(basic.diagnostics, Vec::new(), "dispatch/basic.solc"); + let basic = specialize_fixture(&corpus.join("dispatch/basic.sol")); + assert_eq!(basic.diagnostics, Vec::new(), "dispatch/basic.sol"); assert!( !basic.module.items.iter().any(|item| match item { MonoItem::Function(function) => function.body.iter().any(stmt_has_closure_dispatch), _ => false, }), - "dispatch/basic.solc retained closure dispatch" + "dispatch/basic.sol retained closure dispatch" ); let basic_contract = basic .module @@ -1874,7 +1867,7 @@ fn specializes_p7_cited_regression_corpus() { "{:?}", basic_contract.entries ); - let payable = specialize_fixture(&corpus.join("dispatch/payable.solc")); + let payable = specialize_fixture(&corpus.join("dispatch/payable.sol")); let payable_contract = payable .module .items @@ -1907,7 +1900,7 @@ fn specializes_p7_cited_regression_corpus() { fn folds_direct_function_compose_closure_fixture() { let repo = repo_root(); let output = specialize_fixture( - &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.solc"), + &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/06comp.sol"), ); assert_eq!(output.diagnostics, Vec::new()); @@ -1915,24 +1908,23 @@ fn folds_direct_function_compose_closure_fixture() { } const OPERATOR_CUSTOM_UINT_ADD: &str = r#" -import std.{*}; +import * from std; -data uint = u(word); +enum uint {u(word)} -instance uint:Add { - function add(x:uint, y:uint) -> uint { +impl Add { + function add(x:uint, y:uint) returns (uint) { return uint.u(42); } } -function unwrap(x:uint) -> word { - match x { - | uint.u(w) => return w; - } +function unwrap(x:uint) returns (word) { + match (x) { + case uint.u(w) { return w; }} } contract C { - public function main() -> word { + function main() public returns (word) { let a:uint = uint.u(1); let b:uint = uint.u(2); let c:uint = a + b; @@ -1942,26 +1934,24 @@ contract C { "#; const OPERATOR_METERS_ADD: &str = r#" -import std.{*}; +import * from std; -data meters = meters(word); +enum meters {meters(word)} -instance meters:Add { - function add(x:meters, y:meters) -> meters { - match x, y { - | meters(xw), meters(yw) => return meters(addWord(xw, yw)); - } +impl Add { + function add(x:meters, y:meters) returns (meters) { + match (x, y) { + case (meters(xw), meters(yw)) { return meters(addWord(xw, yw)); }} } } -function unwrap(x:meters) -> word { - match x { - | meters(w) => return w; - } +function unwrap(x:meters) returns (word) { + match (x) { + case meters(w) { return w; }} } contract C { - public function main() -> word { + function main() public returns (word) { let a:meters = meters(1); let b:meters = meters(2); let c:meters = a + b; @@ -1971,28 +1961,26 @@ contract C { "#; const OPERATOR_METERS_ORD: &str = r#" -import std.{*}; +import * from std; -data meters = meters(word); +enum meters {meters(word)} -instance meters:Eq { - function eq(x:meters, y:meters) -> bool { - match x, y { - | meters(xw), meters(yw) => return eqWord(xw, yw); - } +impl Eq { + function eq(x:meters, y:meters) returns (bool) { + match (x, y) { + case (meters(xw), meters(yw)) { return eqWord(xw, yw); }} } } -instance meters:Ord { - function gt(x:meters, y:meters) -> bool { - match x, y { - | meters(xw), meters(yw) => return gtWord(xw, yw); - } +impl Ord { + function gt(x:meters, y:meters) returns (bool) { + match (x, y) { + case (meters(xw), meters(yw)) { return gtWord(xw, yw); }} } } contract C { - public function main() -> word { + function main() public returns (word) { let a:meters = meters(1); let b:meters = meters(2); if (a < b) { @@ -2005,59 +1993,59 @@ contract C { "#; const OPERATOR_CUSTOM_MUL: &str = r#" -import std.{*}; +import * from std; -data Weird = Weird(word); +enum Weird {Weird(word)} -instance Weird:Mul { - function mul(x:Weird, y:Weird) -> Weird { +impl Mul { + function mul(x:Weird, y:Weird) returns (Weird) { return Weird(99); } } contract C { - public function main() -> word { + function main() public returns (word) { let result : Weird = Weird(2) * Weird(3); - match result { | Weird(value) => return value; } + match (result) { case Weird(value) { return value; }} } } "#; const OPERATOR_CUSTOM_EQ: &str = r#" -import std.{*}; +import * from std; -data Weird = Weird(word); +enum Weird {Weird(word)} -instance Weird:Eq { - function eq(x:Weird, y:Weird) -> bool { +impl Eq { + function eq(x:Weird, y:Weird) returns (bool) { return false; } } contract C { - public function main() -> word { + function main() public returns (word) { if (Weird(1) == Weird(1)) { return 0; } else { return 99; } } } "#; const OPERATOR_VISIBLE_BOOL_FUNCTIONS: &str = r#" -function and(x:bool, y:bool) -> bool { return false; } -function or(x:bool, y:bool) -> bool { return false; } -function not(x:bool) -> bool { return true; } +function and(x:bool, y:bool) returns (bool) { return false; } +function or(x:bool, y:bool) returns (bool) { return false; } +function not(x:bool) returns (bool) { return true; } contract C { - public function main() -> word { + function main() public returns (word) { if ((true && true) || !true) { return 0; } else { return 99; } } } "#; const OPERATOR_WORD_ADD: &str = r#" -import std.{*}; +import * from std; contract C { - public function main() -> word { + function main() public returns (word) { return 1 + 2; } } @@ -2102,15 +2090,15 @@ fn every_audited_operator_uses_its_selected_semantics() { ] { let src = format!( r#" -import std.{{*}}; -data Weird = Weird(word); -instance Weird:{class} {{ - function {method}(x:Weird, y:Weird) -> Weird {{ return Weird({expected}); }} +import * from std; +enum Weird {{ Weird(word) }} +impl {class} {{ + function {method}(x: Weird, y: Weird) returns (Weird) {{ return Weird({expected}); }} }} contract C {{ - public function main() -> word {{ - let result : Weird = Weird(8) {operator} Weird(3); - match result {{ | Weird(value) => return value; }} + function main() public returns (word) {{ + let result: Weird = Weird(8) {operator} Weird(3); + match (result) {{ case Weird(value) {{ return value; }} }} }} }} "# @@ -2126,13 +2114,13 @@ contract C {{ let not_eq = specialize_src_with_std( r#" -import std.{*}; -data Weird = Weird(word); -instance Weird:Eq { - function eq(x:Weird, y:Weird) -> bool { return true; } +import * from std; +enum Weird {Weird(word)} +impl Eq { + function eq(x:Weird, y:Weird) returns (bool) { return true; } } contract C { - public function main() -> word { + function main() public returns (word) { if (Weird(1) != Weird(2)) { return 0; } else { return 96; } } } @@ -2144,19 +2132,19 @@ contract C { for (label, definition, expression, expected) in [ ( "And", - "function and(x:bool, y:bool) -> bool { return false; }", + "function and(x:bool, y:bool) returns (bool) { return false; }", "true && true", "0", ), ( "Or", - "function or(x:bool, y:bool) -> bool { return false; }", + "function or(x:bool, y:bool) returns (bool) { return false; }", "false || true", "0", ), ( "Not", - "function not(x:bool) -> bool { return true; }", + "function not(x:bool) returns (bool) { return true; }", "!true", "97", ), @@ -2165,7 +2153,7 @@ contract C { r#" {definition} contract C {{ - public function main() -> word {{ + function main() public returns (word) {{ if ({expression}) {{ return 97; }} else {{ return 0; }} }} }} @@ -2185,10 +2173,10 @@ contract C {{ fn comptime_obligations_are_carried_into_mono_side_table() { let (_db, output) = specialize_src( r#" -function need(comptime x : word) -> word { return x; } +function need(comptime x : word) returns (word) { return x; } contract C { - public function main(x : word) -> comptime word { + function main(x : word) public returns (comptime) { return need(x); } } @@ -2224,15 +2212,15 @@ contract C { fn derived_generic_evidence_generates_from_body() { let (_db, output) = specialize_src( r#" -data Pair = Pair(word, word); +enum Pair {Pair(word, word)} -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } contract C { - public function main(x:Pair) -> pair(word, word) { + function main(x:Pair) public returns (pair) { return Generic.from(x); } } @@ -2254,23 +2242,23 @@ fn derived_class_wrapper_converts_exact_self_arguments_and_returns() { pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall a . class a:CloneLike { - function clone(x:a) -> a; +trait CloneLike { + function clone(x:a) returns (a) ; } -instance word:CloneLike { - function clone(x:word) -> word { return x; } +impl CloneLike { + function clone(x:word) returns (word) { return x; } } #[derive(CloneLike)] -data Box = Box(word); +enum Box {Box(word)} -function main(x:Box) -> Box { +function main(x:Box) returns (Box) { return CloneLike.clone(x); } "#, @@ -2332,23 +2320,23 @@ fn derived_class_wrapper_keeps_method_binders_distinct_from_self() { pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall self . class self:Choose { - forall x . function choose(value:x, witness:self) -> x; +trait Choose { + function choose(value:x, witness:self) returns (x) ; } -instance word:Choose { - forall x . function choose(value:x, witness:word) -> x { return value; } +impl Choose { + function choose(value:x, witness:word) returns (x) { return value; } } #[derive(Choose)] -data Box = Box(word); +enum Box {Box(word)} -function main(value:Box, witness:Box) -> Box { +function main(value:Box, witness:Box) returns (Box) { return Choose.choose(value, witness); } "#, @@ -2409,28 +2397,28 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-generic-instance-for Box; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall a . class a:CloneLike { - function clone(x:a) -> a; +trait CloneLike { + function clone(x:a) returns (a) ; } -instance word:CloneLike { - function clone(x:word) -> word { return x; } +impl CloneLike { + function clone(x:word) returns (word) { return x; } } #[derive(CloneLike)] -data Box = Box(bool); +enum Box {Box(bool)} -instance Box:Generic(word) { - function from(x:Box) -> word { return 7; } - function to(x:word) -> Box { return Box(false); } +impl Generic { + function from(x:Box) returns (word) { return 7; } + function to(x:word) returns (Box) { return Box(false); } } -function main(x:Box) -> Box { +function main(x:Box) returns (Box) { return CloneLike.clone(x); } "#, @@ -2467,8 +2455,8 @@ fn derived_class_wrapper_uses_the_imported_definition_environment() { BTreeMap::new(), )); db.module_fs_snapshot = Some(module_fs_snapshot_for_roots(db, [main_root.as_path()])); - let lib_path = main_root.join("lib.solc"); - let main_path = main_root.join("main.solc"); + let lib_path = main_root.join("lib.sol"); + let main_path = main_root.join("main.sol"); let lib_file = source_file_at_path( db, &lib_path, @@ -2478,23 +2466,23 @@ pragma no-bounded-variable-condition; export { Box(*), cloneBox }; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall a . class a:CloneLike { - function clone(x:a) -> a; +trait CloneLike { + function clone(x:a) returns (a) ; } -instance word:CloneLike { - function clone(x:word) -> word { return x; } +impl CloneLike { + function clone(x:word) returns (word) { return x; } } #[derive(CloneLike)] -data Box = Box(word); +enum Box {Box(word)} -function cloneBox(x:Box) -> Box { +function cloneBox(x:Box) returns (Box) { return CloneLike.clone(x); } "#, @@ -2505,16 +2493,16 @@ function cloneBox(x:Box) -> Box { r#" import lib; -forall a . class a:CloneLike { - function clone(x:a) -> a; +trait CloneLike { + function clone(x:a) returns (a) ; } -instance word:CloneLike { - function clone(x:word) -> word { return x; } +impl CloneLike { + function clone(x:word) returns (word) { return x; } } contract C { - function main(x:lib.Box) -> lib.Box { + function main(x:lib.Box) returns (lib.Box) { return lib.cloneBox(x); } } @@ -2559,87 +2547,86 @@ fn derived_class_and_instance_specializations_are_proof_aware_across_modules() { let modules = [ ( - "lib.solc", + "lib.sol", r#" pragma no-patterson-condition; pragma no-bounded-variable-condition; export { Pick, Wrap(*) }; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall a . class a:Pick { - function pick(x:a) -> word; +trait Pick { + function pick(x:a) returns (word) ; } -forall a b . a:Pick, b:Pick => -instance (a,b):Pick { - function pick(x:(a,b)) -> word { - match x { - | (left, right) => - let left_value = Pick.pick(left); +impl Pick<(a,b)> where a: Pick, b: Pick { + function pick(x:(a,b)) returns (word) { + match (x) { + case (left, right) { +let left_value = Pick.pick(left); let right_value = Pick.pick(right); let result : word; assembly { result := add(mul(left_value, 10), right_value) } return result; - } + }} } } #[derive(Pick)] -data Wrap(a) = Wrap(a, a); +enum Wrap {Wrap(a, a)} "#, ), ( - "left.solc", + "left.sol", r#" -import lib.{*}; +import * from lib; export { left }; -instance word:Pick { - function pick(x:word) -> word { +impl Pick { + function pick(x:word) returns (word) { let result : word; assembly { result := sload(x) } return result; } } -function left(x:Wrap(word)) -> word { +function left(x:Wrap) returns (word) { return Pick.pick(x); } "#, ), ( - "right.solc", + "right.sol", r#" -import lib.{*}; +import * from lib; export { right }; -instance word:Pick { - function pick(x:word) -> word { +impl Pick { + function pick(x:word) returns (word) { let result : word; assembly { result := sload(add(x, 1)) } return result; } } -function right(x:Wrap(word)) -> word { +function right(x:Wrap) returns (word) { return Pick.pick(x); } "#, ), ( - "main.solc", + "main.sol", r#" -import lib.{*}; -import left.{left}; -import right.{right}; +import * from lib; +import {left} from left; +import {right} from right; contract C { - function main(x:Wrap(word), y:Wrap(word)) -> (word, word) { + function main(x:Wrap, y:Wrap) returns ((word, word)) { return (left(x), right(y)); } } @@ -2656,10 +2643,10 @@ contract C { files.insert(name, file); } - let main_file = files["main.solc"]; - let lib_file = files["lib.solc"]; - let left_file = files["left.solc"]; - let right_file = files["right.solc"]; + let main_file = files["main.sol"]; + let lib_file = files["lib.sol"]; + let left_file = files["left.sol"]; + let right_file = files["right.sol"]; let module = parse_file_to_hir(db, main_file).module(db); let output = specialize_module(db, module, SpecializeOptions::default()); @@ -2764,23 +2751,23 @@ fn derived_class_wrapper_preserves_adt_arguments_and_reuses_proofs() { pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall a . class a:CloneLike { - function clone(x:a) -> a; +trait CloneLike { + function clone(x:a) returns (a) ; } -instance word:CloneLike { - function clone(x:word) -> word { return x; } +impl CloneLike { + function clone(x:word) returns (word) { return x; } } #[derive(CloneLike)] -data Wrap(a) = Wrap(a); +enum Wrap {Wrap(a)} -function main(x:Wrap(word)) -> Wrap(word) { +function main(x:Wrap) returns (Wrap) { let first = CloneLike.clone(x); return CloneLike.clone(first); } @@ -2830,16 +2817,16 @@ function main(x:Wrap(word)) -> Wrap(word) { fn derived_class_wrapper_reuses_its_reservation_for_recursive_adts() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.Generic.{*}; +import * from std; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq)] -data List = Nil | Cons(word, List); +enum List {Nil , Cons(word, List)} -function main(x:List) -> bool { +function main(x:List) returns (bool) { return Eq.eq(x, x); } "#, @@ -2871,23 +2858,23 @@ fn derived_class_wrapper_rejects_nested_self_without_emitting_unchecked_ir() { pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall a . class a:NestedSelf { - function inspect(x:a, nested:(a, word)) -> bool; +trait NestedSelf { + function inspect(x:a, nested:(a, word)) returns (bool) ; } -instance word:NestedSelf { - function inspect(x:word, nested:(word, word)) -> bool { return true; } +impl NestedSelf { + function inspect(x:word, nested:(word, word)) returns (bool) { return true; } } #[derive(NestedSelf)] -data Box = Box(word); +enum Box {Box(word)} -function main(x:Box) -> bool { +function main(x:Box) returns (bool) { return NestedSelf.inspect(x, (x, 0)); } "#, @@ -2909,16 +2896,16 @@ function main(x:Box) -> bool { fn derived_class_wrapper_uses_absurd_for_an_empty_adt() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; -forall a . class a:Make { - function make() -> a; +trait Make { + function make() returns (a) ; } #[derive(Make)] -data Never; +enum Never {} -function main() -> Never { +function main() returns (Never) { return Make.make(); } "#, @@ -2957,22 +2944,26 @@ function main() -> Never { fn generic_abi_decoder_evidence_specializes_for_internal_sum_adt() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.Generic; +import * from std.ABIGeneric; -data Choice = Left(uint256) | Right(address); +enum Choice {Left(uint256) , Right(address)} contract C { - function main() -> word { + function main() returns (word) { let buf = allocate_zeroed_memory(64); let rdr : MemoryWordReader = MemoryWordReader(buf); - let dec : ABIDecoder(Choice, MemoryWordReader) = - ABIDecoder(rdr) : ABIDecoder(Choice, MemoryWordReader); + let dec : ABIDecoder = + ABIDecoder(rdr) ; let value : Choice = decode(dec, 0); - match value { - | Choice.Left(x) => return Typedef.rep(x); - | Choice.Right(_) => return 0; + match (value) { + case Choice.Left(x) { + return Typedef.rep(x); + } + case Choice.Right(_) { + return 0; + } } } } @@ -2997,10 +2988,10 @@ contract C { fn snapshot_small_specialized_module() { let (db, output) = specialize_src( r#" -forall a . function id(x:a) -> a { return x; } +function id(x:a) returns (a) { return x; } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { return id(x); } } @@ -3035,9 +3026,9 @@ fn specializes_curated_typecheck_parity_corpus_files() { let repo = repo_root(); let corpus = repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples"); for fixture in [ - "spec/00answer.solc", - "spec/06comp.solc", - "cases/super-class.solc", + "spec/00answer.sol", + "spec/06comp.sol", + "cases/super-class.sol", ] { let output = specialize_fixture(&corpus.join(fixture)); assert_eq!(output.diagnostics, Vec::new(), "{fixture}"); @@ -3049,18 +3040,18 @@ fn specializes_comptime_evaluation_corpus_verdicts() { let repo = repo_root(); let corpus = repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples"); let passing = [ - "comptime/ct_asm_mem.solc", - "comptime/ct_chain_ok.solc", - "comptime/ct_let_ok.solc", - "comptime/ct_overloaded_ok.solc", - "comptime/ct_param_ok.solc", - "comptime/integer-basic.solc", - "comptime/integer-fib.solc", - "comptime/integer-lit-pat.solc", - "comptime/match_labels.solc", - "comptime/Plus.solc", - "comptime/string-lit-keccak.solc", - "comptime/string-lit-len.solc", + "comptime/ct_asm_mem.sol", + "comptime/ct_chain_ok.sol", + "comptime/ct_let_ok.sol", + "comptime/ct_overloaded_ok.sol", + "comptime/ct_param_ok.sol", + "comptime/integer-basic.sol", + "comptime/integer-fib.sol", + "comptime/integer-lit-pat.sol", + "comptime/match_labels.sol", + "comptime/Plus.sol", + "comptime/string-lit-keccak.sol", + "comptime/string-lit-len.sol", ]; for fixture in passing { let output = specialize_fixture(&corpus.join(fixture)); @@ -3072,7 +3063,7 @@ fn specializes_comptime_evaluation_corpus_verdicts() { fn folds_recursive_comptime_integer_function() { let (_db, output) = specialize_src( r#" -function fib(comptime n : integer) -> comptime integer { +function fib(comptime n : integer) returns (comptime) { if (integerLt(n, 2)) { return n; } else { @@ -3081,7 +3072,7 @@ function fib(comptime n : integer) -> comptime integer { } contract C { - public function main() -> word { + function main() public returns (word) { return wordFromInteger(fib(10)); } } @@ -3106,7 +3097,7 @@ contract C { fn folds_comptime_yul_mstore_mload_subset() { let (_db, output) = specialize_src( r#" -function storeLoad(x : word) -> word { +function storeLoad(x : word) returns (word) { let r : word; assembly { mstore(0, x) @@ -3116,8 +3107,8 @@ function storeLoad(x : word) -> word { } contract C { - public function main() -> word { - let res : comptime word = storeLoad(42); + function main() public returns (word) { + let res : comptime = storeLoad(42); return res; } } @@ -3133,7 +3124,7 @@ fn assembly_substitution_does_not_reuse_values_after_an_in_block_write() { let (db, output) = specialize_src( r#" contract C { - public function main(x: word) -> word { + function main(x: word) public returns (word) { let a: word = 1; assembly { a := add(a, x) @@ -3179,7 +3170,7 @@ fn assembly_substitution_does_not_capture_same_named_function_parameters() { let (db, output) = specialize_src( r#" contract C { - public function main() -> word { + function main() public returns (word) { let x : word = 1; let observed : word = 0; assembly { @@ -3246,12 +3237,12 @@ contract C { fn does_not_fold_user_function_shadowing_std_literal_intrinsic() { let (_db, output) = specialize_src( r#" -function keccakLit(a:string) -> word { +function keccakLit(a:string) returns (word) { return 0; } contract C { - public function main() -> word { + function main() public returns (word) { return keccakLit("abc"); } } @@ -3266,7 +3257,7 @@ contract C { fn folds_resolved_std_string_keccak_literal_intrinsic() { let repo = repo_root(); let fixture = repo.join( - "crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.solc", + "crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/string-lit-keccak.sol", ); let output = specialize_fixture(&fixture); @@ -3284,14 +3275,14 @@ fn folds_resolved_std_string_keccak_literal_intrinsic() { fn clones_and_deduplicates_folded_comptime_string_arguments() { let (db, _, output) = specialize_src_with_std_and_db( r#" -import std.{*}; +import * from std; -function consume(s:string, x:word) -> word { +function consume(s:string, x:word) returns (word) { return addWord(strlenLit(s), x); } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { return addWord(consume("abcd", x), consume(concatLit("ab", "cd"), x)); } } @@ -3332,18 +3323,18 @@ contract C { fn user_str_instance_clone_leaves_only_a_literal_materializer_call() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; -data Wrapped = Wrapped(memory(string)); +enum Wrapped {Wrapped(memory)} -instance Wrapped:Str { - function fromString(s:string) -> Wrapped { +impl Str { + function fromString(s:string) returns (Wrapped) { return Wrapped(Str.fromString(s)); } } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { let wrapped:Wrapped = "abcd"; let source = "abcd"; let explicit:Wrapped = Str.fromString(source); @@ -3376,10 +3367,10 @@ contract C { fn require_accepts_a_string_literal_via_the_std_error_str_instance() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract C { - public function main(cond:bool) -> () { + function main(cond:bool) public returns () { require(cond, "boom"); return (); } @@ -3405,13 +3396,13 @@ contract C { fn materializes_a_string_literal_through_a_memory_string_alias() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; -type Text = memory(string); +type Text = memory; type Source = string; contract C { - public function main() -> word { + function main() public returns (word) { let implicit:Text = "x"; let source:Source = "y"; let explicit:Text = Str.fromString(source); @@ -3439,24 +3430,24 @@ contract C { fn string_clone_worklist_evaluates_clones_that_spawn_clones() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; -function inner(s:string, x:word) -> word { +function inner(s:string, x:word) returns (word) { return addWord(strlenLit(s), x); } -function touch(x:word) -> () { +function touch(x:word) returns () { assembly { sstore(0, x) } } -function outer(s:string, x:word) -> word { +function outer(s:string, x:word) returns (word) { let result:word = inner(s, x); touch(x); return result; } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { return outer("abcd", x); } } @@ -3492,7 +3483,7 @@ contract C { fn recursive_string_clone_creation_consumes_global_fuel() { let output = specialize_src_with_std_options( r#" -import std.{*}; +import * from std; function grow(s:string, x:word) -> word { let result:word = grow(concatLit(s, "x"), x); From e5a38563da13d1525ca5f456884b2d417fc13378 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 084/110] Switch the compiler and fixtures to canonical syntax: specialize Co-authored-by: Codex --- crates/specialize/tests/specialize.rs | 398 +++++++++++++------------- 1 file changed, 202 insertions(+), 196 deletions(-) diff --git a/crates/specialize/tests/specialize.rs b/crates/specialize/tests/specialize.rs index a46959c1..094b0ea8 100644 --- a/crates/specialize/tests/specialize.rs +++ b/crates/specialize/tests/specialize.rs @@ -3485,14 +3485,14 @@ fn recursive_string_clone_creation_consumes_global_fuel() { r#" import * from std; -function grow(s:string, x:word) -> word { +function grow(s:string, x:word) returns (word) { let result:word = grow(concatLit(s, "x"), x); assembly { sstore(0, x) } return result; } contract C { - public function main(x:word) -> word { + function main(x:word) public returns (word) { return grow("", x); } } @@ -3532,13 +3532,13 @@ contract C { fn desugars_memory_and_storage_array_literals_to_runtime_builders() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract ArrayLit { - xs : array(uint256); + xs : array; - function main() -> uint256 { - let m : memory(DynArray(uint256)) = [1, 2, 3]; + function main() returns (uint256) { + let m : memory> = [1, 2, 3]; xs = [10, 20, 30]; return m[uint256(1)] + xs[uint256(2)]; } @@ -3584,13 +3584,13 @@ contract ArrayLit { fn routes_whole_storage_array_assignment_through_assign_instance() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract ArrayCopy { - dst : array(uint256); - src : array(uint256); + dst : array; + src : array; - function main() -> () { + function main() returns () { dst = src; return (); } @@ -3618,23 +3618,23 @@ contract ArrayCopy { fn contract_fields_lower_through_storage_classes_and_prefix_offsets() { let (db, main_file, output) = specialize_src_with_std_and_db( r#" -import std.{*}; +import * from std; contract FieldAccess { first : uint256; second : uint256; third : uint256; - values : array(uint256); - balances : mapping(uint256, uint256); + values : array; + balances : mapping(uint256 => uint256); - function readFirst() -> uint256 { return first; } - function writeSecond(v:uint256) -> () { second = v; return (); } - function bumpThird(v:uint256) -> () { third += v; return (); } - function replaceValues() -> () { values = [uint256(4), uint256(5)]; return (); } - function readValue(k:uint256) -> uint256 { return values[k]; } - function readBalance(k:uint256) -> uint256 { return balances[k]; } + function readFirst() returns (uint256) { return first; } + function writeSecond(v:uint256) returns () { second = v; return (); } + function bumpThird(v:uint256) returns () { third += v; return (); } + function replaceValues() returns () { values = [uint256(4), uint256(5)]; return (); } + function readValue(k:uint256) returns (uint256) { return values[k]; } + function readBalance(k:uint256) returns (uint256) { return balances[k]; } - function main() -> uint256 { + function main() returns (uint256) { writeSecond(uint256(1)); bumpThird(uint256(2)); replaceValues(); @@ -3748,11 +3748,11 @@ contract FieldAccess { fn partial_contract_field_support_does_not_fall_back_to_legacy_slots() { let read = specialize_src_with_std( r#" -import std.{Proxy, storage, StorageSize}; +import {Proxy, storage, StorageSize} from std; contract C { value : word; - function main() -> word { return value; } + function main() returns (word) { return value; } } "#, ); @@ -3768,11 +3768,11 @@ contract C { let write = specialize_src_with_std( r#" -import std.{Proxy, storage, StorageSize, CanStore}; +import {Proxy, storage, StorageSize, CanStore} from std; contract C { value : word; - function main() -> word { + function main() returns (word) { value = value; return value; } @@ -3794,30 +3794,30 @@ contract C { fn array_indexes_preserve_non_identity_typedef_representations() { let (db, main_file, output) = specialize_src_with_std_and_db( r#" -import std.{*}; +import * from std; -data Shifted = Shifted(word); -instance Shifted:Typedef(word) { - function rep(x:Shifted) -> word { - match x { | Shifted(w) => return w + 100; } +enum Shifted {Shifted(word)} +impl Typedef { + function rep(x:Shifted) returns (word) { + match (x) { case Shifted(w) { return w + 100; }} } - function abs(w:word) -> Shifted { return Shifted(w - 100); } + function abs(w:word) returns (Shifted) { return Shifted(w - 100); } } -data Second = Second(word); -instance Second:Typedef(word) { - function rep(x:Second) -> word { - match x { | Second(w) => return w + 1; } +enum Second {Second(word)} +impl Typedef { + function rep(x:Second) returns (word) { + match (x) { case Second(w) { return w + 1; }} } - function abs(w:word) -> Second { return Second(w - 1); } + function abs(w:word) returns (Second) { return Second(w - 1); } } contract ReprArray { - xs : array(uint256); + xs : array; seed : word; - function main() -> word { - let m : memory(DynArray(Shifted)) = [Shifted(3), Shifted(4)]; + function main() returns (word) { + let m : memory> = [Shifted(3), Shifted(4)]; xs = [10, 20]; let idx : Second = Second(seed); let picked : Shifted = m[idx]; @@ -3869,13 +3869,13 @@ contract ReprArray { fn public_dynamic_array_return_reaches_abi_encoder() { let output = specialize_src_with_std( r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PublicArray { constructor() {} - public function values() -> memory(DynArray(uint256)) { + function values() public returns (memory>) { return [1, 2, 3]; } } @@ -3902,14 +3902,14 @@ contract PublicArray { fn bool_and_nested_dynamic_storage_arrays_resolve_storage_conversions() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract CollectionArray { - flags : array(bool); - grid : array(array(uint256)); - names : array(string); + flags : array; + grid : array>; + names : array; - function main() -> uint256 { + function main() returns (uint256) { Array.setLength(flags, uint256(0)); ArrayPush.push(flags, true); let flag : bool = flags[uint256(0)]; @@ -3917,15 +3917,15 @@ contract CollectionArray { Array.setLength(grid, uint256(1)); ArrayPush.push(grid[uint256(0)], uint256(7)); grid[uint256(0)][uint256(0)] = uint256(9); - let row : storage(array(uint256)) = grid[uint256(0)]; + let row : storage> = grid[uint256(0)]; ArrayPush.push(row, uint256(11)); - let s : memory(string) = "hello"; + let s : memory = "hello"; ArrayPush.push(names, s); names[uint256(0)] = s; - let loaded : memory(string) = names[uint256(0)]; + let loaded : memory = names[uint256(0)]; - if flag { return row[uint256(1)] + Length.length(names); } + if (flag) { return row[uint256(1)] + Length.length(names); } return uint256(0); } } @@ -3952,12 +3952,12 @@ contract CollectionArray { fn nested_bool_array_write_composes_storage_refs_without_intermediate_copy() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract NestedBool { - grid : array(array(bool)); + grid : array>; - function main(v:bool) -> () { + function main(v:bool) returns () { grid[uint256(0)][uint256(0)] = v; return (); } @@ -3998,10 +3998,10 @@ contract NestedBool { fn folds_resolved_std_word_keccak_literal_intrinsic() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract C { - public function main() -> word { + function main() public returns (word) { return keccakWordLit(0); } } @@ -4022,10 +4022,10 @@ contract C { fn folds_erc7201_namespace_to_a_single_constant() { let output = specialize_src_with_std( r#" -import std.{*}; +import * from std; contract C { - public function main() -> bytes32 { + function main() public returns (bytes32) { return erc7201("example.main"); } } @@ -4048,14 +4048,14 @@ contract C { fn does_not_fold_user_addword_shadowing_builtin_wrapper_name() { let (_db, output) = specialize_src( r#" -function addWord(x: word, y: word) -> word { +function addWord(x: word, y: word) returns (word) { let r : word; assembly { r := sload(0) } return r; } contract C { - public function main() -> word { + function main() public returns (word) { return addWord(1, 2); } } @@ -4070,7 +4070,7 @@ contract C { fn assignment_lhs_root_is_not_substituted() { let repo = repo_root(); let fixture = - repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.solc"); + repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/comptime/Plus.sol"); let output = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new()); @@ -4081,12 +4081,12 @@ fn assignment_lhs_root_is_not_substituted() { fn compound_assignment_invalidates_lhs_root() { let (_db, output) = specialize_src( r#" -forall t . class t:Add { - function add(l:t, r:t) -> t; +trait Add { + function add(l:t, r:t) returns (t) ; } -instance word:Add { - function add(l:word, r:word) -> word { +impl Add { + function add(l:word, r:word) returns (word) { let result : word; assembly { result := sload(0) } return result; @@ -4094,7 +4094,7 @@ instance word:Add { } contract C { - public function main() -> word { + function main() public returns (word) { let x : word = 1; x += 2; return x; @@ -4112,7 +4112,7 @@ fn unknown_if_invalidates_assignments_from_both_branches() { let (_db, output) = specialize_src( r#" contract C { - public function main(c: bool) -> word { + function main(c: bool) public returns (word) { let x : word = 1; if (c) { } else { @@ -4133,7 +4133,7 @@ fn if_statement_specializes_through_pre_typeck_match_view() { let (_db, output) = specialize_src( r#" contract C { - public function main(c: bool) -> word { + function main(c: bool) public returns (word) { let x : word = 1; if (c) { x = 2; @@ -4177,8 +4177,8 @@ fn if_expression_specializes_through_pre_typeck_match_view() { let (_db, output) = specialize_src( r#" contract C { - public function main(c: bool) -> word { - let x : word = if (c) then 2 else 3; + function main(c: bool) public returns (word) { + let x : word = ((c) ? 2 : 3); return x; } } @@ -4217,7 +4217,7 @@ fn bool_constructors_specialize_through_pre_typeck_unit_sum_view() { let (_true_db, true_output) = specialize_src( r#" contract C { - public function main() -> bool { + function main() public returns (bool) { return true; } } @@ -4226,7 +4226,7 @@ contract C { let (_false_db, false_output) = specialize_src( r#" contract C { - public function main() -> bool { + function main() public returns (bool) { return false; } } @@ -4250,11 +4250,10 @@ fn unknown_match_pattern_binders_shadow_outer_constants() { let (_db, output) = specialize_src( r#" contract C { - public function main(n: word) -> word { + function main(n: word) public returns (word) { let x : word = 1; - match n { - | x => return x; - } + match (n) { + case x { return x; }} } } "#, @@ -4272,9 +4271,9 @@ fn folds_qualified_constructor_matches_before_wildcard_defaults() { let repo = repo_root(); let corpus = repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec"); for (fixture, expected) in [ - ("037dwarves.solc", "5"), - ("038food0.solc", "42"), - ("039food.solc", "42"), + ("037dwarves.sol", "5"), + ("038food0.sol", "42"), + ("039food.sol", "42"), ] { let output = specialize_fixture(&corpus.join(fixture)); assert_eq!(output.diagnostics, Vec::new(), "{fixture}"); @@ -5072,7 +5071,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -5173,17 +5172,21 @@ fn repo_root() -> PathBuf { fn constructor_fold_is_not_confused_by_underscored_names() { let (_db, output) = specialize_src( r#" -data D = Suf | Pre_Suf; +enum D {Suf , Pre_Suf} -function pick(d:D) -> word { - match d { - | D.Suf => return 1; - | D.Pre_Suf => return 2; - }; +function pick(d:D) returns (word) { + match (d) { + case D.Suf { + return 1; + } + case D.Pre_Suf { + return 2; + } + } } contract C { - function main() -> word { + function main() returns (word) { return pick(D.Pre_Suf); } } @@ -5203,17 +5206,21 @@ contract C { fn for_loop_post_assignments_are_not_folded_to_preloop_constants() { let (_db, output) = specialize_src( r#" -data Flag = On | Off; +enum Flag {On , Off} -function isOn(f: Flag) -> bool { - match f { - | Flag.On => return true; - | Flag.Off => return false; - }; +function isOn(f: Flag) returns (bool) { + match (f) { + case Flag.On { + return true; + } + case Flag.Off { + return false; + } + } } contract C { - function main() -> word { + function main() returns (word) { let f : Flag = Flag.On; for (; isOn(f); f = Flag.Off) { } @@ -5248,8 +5255,8 @@ contract C { fn non_contract_main_survives_dead_function_elimination_after_name_mangling() { let (_db, output) = specialize_src( r#" -function answer() -> word { return 42; } -function main() -> word { return answer(); } +function answer() returns (word) { return 42; } +function main() returns (word) { return answer(); } "#, ); @@ -5275,12 +5282,12 @@ fn evaluator_fuel_bounds_total_inline_fanout_work() { let module = parse_module( db, r#" -function g2() -> word { return 1; } -function g1() -> word { return g2() + g2(); } -function g0() -> word { return g1() + g1(); } +function g2() returns (word) { return 1; } +function g1() returns (word) { return g2() + g2(); } +function g0() returns (word) { return g1() + g1(); } contract C { - function main() -> word { return g0(); } + function main() returns (word) { return g0(); } } "#, ); @@ -5307,7 +5314,7 @@ contract C { fn default_fuel_handles_the_e136_basic_dispatch_surface() { solcore_test_utils::run_in_large_stack(|| { let source = - include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.solc"); + include_str!("../../parser/tests/fixtures/corpus/ok/test/examples/dispatch/basic.sol"); let output = specialize_src_with_std(source); assert!(output.diagnostics.is_empty(), "{:?}", output.diagnostics); @@ -5350,15 +5357,15 @@ fn default_fuel_handles_the_e136_basic_dispatch_surface() { fn dead_function_elimination_traces_calls_inside_residual_lambdas() { let (_db, output) = specialize_src( r#" -data Box(f) = Box(f); +enum Box {Box(f)} -function target(x : word) -> word { +function target(x : word) returns (word) { let result : word; assembly { result := add(x, 1) } return result; } -function main() -> Box(word -> word) { +function main() returns (Box) { return Box(lam (x : word) -> word { return target(x); }); } "#, @@ -5378,15 +5385,15 @@ function main() -> Box(word -> word) { fn dead_function_elimination_keeps_function_values_nested_in_constructors() { let (_db, output) = specialize_src( r#" -data Box(f) = Box(f); +enum Box {Box(f)} -function target(x : word) -> word { +function target(x : word) returns (word) { let result : word; assembly { result := add(x, 1) } return result; } -function main() -> Box(word -> word) { +function main() returns (Box) { return Box(target); } "#, @@ -5424,15 +5431,15 @@ function main() -> Box(word -> word) { fn user_path_suffix_does_not_grant_std_dispatch_inlining() { let output = specialize_source_at_root( Path::new("/main"), - "mystd/dispatch.solc", + "mystd/dispatch.sol", r#" -function clobber(value : word) -> () { +function clobber(value : word) returns () { let observed : word; assembly { observed := callvalue() } return (); } -function main() -> word { +function main() returns (word) { clobber(0); return 7; } @@ -5464,19 +5471,19 @@ fn std_dispatch_statement_inlining_preserves_lexical_scope() { db, [main_root.as_path(), std_root.as_path()], )); - let path = std_root.join("dispatch.solc"); + let path = std_root.join("dispatch.sol"); let key = module_key_for_path(LibraryId::Std, &std_root, &path).expect("std dispatch key"); let file = source_file_at_path( db, &path, r#" -function clobber() -> () { +function clobber() returns () { let x : word = 1; assembly { mstore(x, x) } return (); } -function main(x : word) -> word { +function main(x : word) returns (word) { clobber(); return x; } @@ -5519,20 +5526,20 @@ function main(x : word) -> word { fn class_method_values_resolve_to_the_specialized_instance_method() { let (_db, output) = specialize_src( r#" -forall t . class t:Pick { - function pick(x : t) -> t; +trait Pick { + function pick(x : t) returns (t) ; } -instance word:Pick { - function pick(x : word) -> word { +impl Pick { + function pick(x : word) returns (word) { let result : word; assembly { result := add(x, 1) } return result; } } -function main(x : word) -> word { - let f : word -> word = Pick.pick; +function main(x : word) returns (word) { + let f : function(word) returns (word) = Pick.pick; return f(x); } "#, @@ -5565,45 +5572,45 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -data Proxy(t) = Proxy; -data ABIDecoder(ty, reader) = ABIDecoder(reader); -data Reader = Reader; +enum Proxy {Proxy} +enum ABIDecoder {ABIDecoder(reader)} +enum Reader {Reader} -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall self . class self:ABIDeriving {} -forall self . class self:ABIAttribs { - function headSize(ty:Proxy(self)) -> word; - function isStatic(ty:Proxy(self)) -> bool; +trait ABIDeriving {} +trait ABIAttribs { + function headSize(ty:Proxy) returns (word) ; + function isStatic(ty:Proxy) returns (bool) ; } -forall decoder decoded . class decoder:ABIDecode(decoded) { - function decode(ptr:decoder, headOffset:word) -> decoded; +trait ABIDecode { + function decode(ptr:decoder, headOffset:word) returns (decoded) ; } -forall reader . class reader:WordReader {} +trait WordReader {} -instance word:ABIAttribs { - function headSize(ty:Proxy(word)) -> word { +impl ABIAttribs { + function headSize(ty:Proxy) returns (word) { assembly { sstore(0, 32) } return 32; } - function isStatic(ty:Proxy(word)) -> bool { + function isStatic(ty:Proxy) returns (bool) { assembly { sstore(1, 1) } return true; } } -instance Reader:WordReader {} -instance ABIDecoder(word, Reader):ABIDecode(word) { - function decode(ptr:ABIDecoder(word, Reader), headOffset:word) -> word { +impl WordReader {} +impl ABIDecode,word> { + function decode(ptr:ABIDecoder, headOffset:word) returns (word) { return headOffset; } } -data Box(a) = Box(a); +enum Box {Box(a)} -function main(ptr:ABIDecoder(Box(word), Reader), headOffset:word) -> Box(word) { - let p:Proxy(Box(word)); +function main(ptr:ABIDecoder, Reader>, headOffset:word) returns (Box) { + let p:Proxy>; let first = ABIAttribs.headSize(p); let second = ABIAttribs.headSize(p); let static = ABIAttribs.isStatic(p); @@ -5736,7 +5743,7 @@ function main(ptr:ABIDecoder(Box(word), Reader), headOffset:word) -> Box(word) { #[test] fn derived_abi_wrappers_replay_definition_side_evidence() { let fixture = - repo_root().join("crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.solc"); + repo_root().join("crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol"); let output = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new(), "{:#?}", output.diagnostics); @@ -5755,21 +5762,21 @@ fn derived_abi_wrappers_replay_definition_side_evidence() { fn direct_adt_abi_specializations_keep_sum_representations_separate() { let (db, _, output) = specialize_src_with_std_and_db( r#" -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; -data D2 = L(uint256) | R(memory(bytes)); -data D3 = X(uint256) | Y(uint256) | Z(memory(bytes)); -data S2 = P(uint256) | Q(uint256); +enum D2 {L(uint256) , R(memory)} +enum D3 {X(uint256) , Y(uint256) , Z(memory)} +enum S2 {P(uint256) , Q(uint256)} contract Sums { constructor() {} - public function makeD2(b:memory(bytes)) -> D2 { return D2.R(b); } - public function makeD3(b:memory(bytes)) -> D3 { return D3.Z(b); } - public function makeS2(n:uint256) -> S2 { return S2.P(n); } - public function roundtripD3(value:D3) -> D3 { return value; } + function makeD2(b:memory) public returns (D2) { return D2.R(b); } + function makeD3(b:memory) public returns (D3) { return D3.Z(b); } + function makeS2(n:uint256) public returns (S2) { return S2.P(n); } + function roundtripD3(value:D3) public returns (D3) { return value; } } "#, ); @@ -5991,49 +5998,48 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -data Proxy(t) = Proxy; -data storage(t) = storage(word); +enum Proxy {Proxy} +enum storage {storage(word)} -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageDeriving {} +trait StorageSize { + function size(x:Proxy) returns (word) ; } -forall slot value . class slot:CanStore(value) { - function store(r:slot, v:value) -> (); - function load(r:slot) -> value; +trait CanStore { + function store(r:slot, v:value) returns () ; + function load(r:slot) returns (value) ; } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x:Proxy) returns (word) { assembly { sstore(0, 1) } return 1; } } -instance storage(word):CanStore(word) { - function store(r:storage(word), v:word) -> () { - match r { - | storage(slot) => assembly { sstore(slot, v) } - } +impl CanStore,word> { + function store(r:storage, v:word) returns () { + match (r) { + case storage(slot) { assembly { sstore(slot, v) } }} } - function load(r:storage(word)) -> word { - match r { - | storage(slot) => - let result:word; + function load(r:storage) returns (word) { + match (r) { + case storage(slot) { +let result:word; assembly { result := sload(slot) } return result; - } + }} } } -data Box(a) = Box(a); +enum Box {Box(a)} -function main(r:storage(Box(word)), v:Box(word)) -> Box(word) { - let first = StorageSize.size(Proxy:Proxy(Box(word))); - let second = StorageSize.size(Proxy:Proxy(Box(word))); +function main(r:storage>, v:Box) returns (Box) { + let first = StorageSize.size(@Box); + let second = StorageSize.size(@Box); CanStore.store(r, v); return CanStore.load(r); } @@ -6136,27 +6142,27 @@ pragma no-patterson-condition; pragma no-bounded-variable-condition; pragma no-coverage-condition; -data storage(t) = storage(word); -data mapping(k, v) = mapping(word); +enum storage {storage(word)} +enum mapping {mapping(word)} -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x:a) returns (rep) ; + function to(x:rep) returns (a) ; } -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize {} -forall slot value . class slot:CanStore(value) { - function store(r:slot, v:value) -> (); - function load(r:slot) -> value; +trait StorageDeriving {} +trait StorageSize {} +trait CanStore { + function store(r:slot, v:value) returns () ; + function load(r:slot) returns (value) ; } -instance word:StorageSize {} -forall k v . instance mapping(k, v):StorageSize {} -forall k v . instance storage(mapping(k, v)):CanStore(storage(mapping(k, v))) {} +impl StorageSize {} +impl StorageSize v)> {} +impl CanStore v)>,storage v)>> {} -data Wrapper = Wrapper(mapping(word, word)); +enum Wrapper {Wrapper(mapping(word => word))} -function main(r:storage(Wrapper)) -> Wrapper { +function main(r:storage) returns (Wrapper) { return CanStore.load(r); } "#, @@ -6176,7 +6182,7 @@ function main(r:storage(Wrapper)) -> Wrapper { #[test] fn derived_storage_wrappers_replay_definition_side_evidence() { let fixture = repo_root() - .join("crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.solc"); + .join("crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol"); let output = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new(), "{:#?}", output.diagnostics); @@ -6200,7 +6206,7 @@ fn derived_storage_wrappers_replay_definition_side_evidence() { #[test] fn contract_field_calls_use_definition_module_evidence() { let fixture = repo_root() - .join("crates/specialize/tests/fixtures/storage_field_definition_evidence/main.solc"); + .join("crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol"); let output = specialize_fixture(&fixture); assert_eq!(output.diagnostics, Vec::new(), "{:#?}", output.diagnostics); From 2e12e2d23a13b7f2a95a91e991cb78abffc3ed3d Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 085/110] Switch the compiler and fixtures to canonical syntax: specialize fixtures Co-authored-by: Codex --- .../derived_abi_evidence_replay/abi.sol | 24 ++++----- .../competitor.sol | 12 ++--- .../derived_abi_evidence_replay/main.sol | 8 +-- .../derived_abi_evidence_replay/types.sol | 12 ++--- .../derived_storage_evidence_replay/main.sol | 8 +-- .../storage_support.sol | 49 ++++++++++--------- .../derived_storage_evidence_replay/types.sol | 4 +- .../competitor.sol | 10 ++-- .../storage_field_definition_evidence/lib.sol | 6 +-- .../main.sol | 4 +- 10 files changed, 70 insertions(+), 67 deletions(-) diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.sol b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.sol index 99788bd8..40db776d 100644 --- a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.sol +++ b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/abi.sol @@ -12,19 +12,19 @@ export { ABIDecoder(*) }; -data Proxy(t) = Proxy; -data ABIDecoder(ty, reader) = ABIDecoder(reader); +enum Proxy { Proxy } +enum ABIDecoder { ABIDecoder(reader) } -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x: a) returns (rep) ; + function to(x: rep) returns (a) ; } -forall self . class self:ABIDeriving {} -forall self . class self:ABIAttribs { - function headSize(ty:Proxy(self)) -> word; - function isStatic(ty:Proxy(self)) -> bool; +trait ABIDeriving {} +trait ABIAttribs { + function headSize(ty: Proxy) returns (word) ; + function isStatic(ty: Proxy) returns (bool) ; } -forall decoder decoded . class decoder:ABIDecode(decoded) { - function decode(ptr:decoder, headOffset:word) -> decoded; +trait ABIDecode { + function decode(ptr: decoder, headOffset: word) returns (decoded) ; } -forall reader . class reader:WordReader {} +trait WordReader {} diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.sol b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.sol index 06a4a691..4a8d0264 100644 --- a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.sol +++ b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/competitor.sol @@ -1,14 +1,14 @@ -import abi.{*}; -import reexport.{Leaf}; +import * from abi; +import {Leaf} from reexport; export { keepCompetitorReachable }; // This orphan is reachable from the entry module but is not visible in the // module that defines Box. A derived wrapper must replay definition-side // evidence rather than scanning every reachable environment. -instance Leaf:ABIAttribs { - function headSize(ty:Proxy(Leaf)) -> word { return 64; } - function isStatic(ty:Proxy(Leaf)) -> bool { return true; } +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 64; } + function isStatic(ty: Proxy) returns (bool) { return true; } } -function keepCompetitorReachable() -> word { return 0; } +function keepCompetitorReachable() returns (word) { return 0; } diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol index 578990a1..4046f5bb 100644 --- a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol +++ b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/main.sol @@ -1,7 +1,7 @@ -import abi.{*}; -import types.{Box}; -import competitor.{keepCompetitorReachable}; +import * from abi; +import {Box} from types; +import {keepCompetitorReachable} from competitor; -function main(p:Proxy(Box)) -> word { +function main(p: Proxy) returns (word) { return ABIAttribs.headSize(p); } diff --git a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.sol b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.sol index 5ba51c21..df01e7fd 100644 --- a/crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.sol +++ b/crates/specialize/tests/fixtures/derived_abi_evidence_replay/types.sol @@ -1,22 +1,22 @@ -import abi.{*}; +import * from abi; export { Leaf(*), Box(*) }; pragma no-generic-instance-for Leaf; -data Leaf = Leaf(word); -data Box = Box(Leaf); +enum Leaf { Leaf(word) } +enum Box { Box(Leaf) } -instance Leaf:ABIAttribs { +impl ABIAttribs { // Keep the definition-side method observable through specialization. The // competing orphan remains pure, so retaining the derived wrapper also // proves that evidence was replayed from this module rather than re-solved // against every reachable instance. - function headSize(ty:Proxy(Leaf)) -> word { + function headSize(ty: Proxy) returns (word) { assembly { sstore(0, 32) } return 32; } - function isStatic(ty:Proxy(Leaf)) -> bool { + function isStatic(ty: Proxy) returns (bool) { assembly { sstore(1, 1) } return true; } diff --git a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol index 241db9f8..1091096f 100644 --- a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol +++ b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/main.sol @@ -1,8 +1,8 @@ -import storage_support.{*}; -import types.{Box}; +import * from storage_support; +import {Box} from types; -function main(r:storage(Box(word)), v:Box(word)) -> Box(word) { - let slots = StorageSize.size(Proxy:Proxy(Box(word))); +function main(r: storage>, v: Box) returns (Box) { + let slots = StorageSize.size(@Box); CanStore.store(r, v); return CanStore.load(r); } diff --git a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.sol b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.sol index 7a391eaa..c115db56 100644 --- a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.sol +++ b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/storage_support.sol @@ -11,41 +11,44 @@ export { CanStore }; -data Proxy(t) = Proxy; -data storage(t) = storage(word); +enum Proxy { Proxy } +enum storage { storage(word) } -forall a rep . class a:Generic(rep) { - function from(x:a) -> rep; - function to(x:rep) -> a; +trait Generic { + function from(x: a) returns (rep) ; + function to(x: rep) returns (a) ; } -forall self . class self:StorageDeriving {} -forall self . class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageDeriving {} +trait StorageSize { + function size(x: Proxy) returns (word) ; } -forall slot value . class slot:CanStore(value) { - function store(r:slot, v:value) -> (); - function load(r:slot) -> value; +trait CanStore { + function store(r: slot, v: value) ; + function load(r: slot) returns (value) ; } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { assembly { sstore(0, 1) } return 1; } } -instance storage(word):CanStore(word) { - function store(r:storage(word), v:word) -> () { - match r { - | storage(slot) => assembly { sstore(slot, v) } - } +impl CanStore, word> { + function store(r: storage, v: word) { + match (r) { +case storage(slot) { +assembly { sstore(slot, v) } +} +} } - function load(r:storage(word)) -> word { - match r { - | storage(slot) => - let result:word; + function load(r: storage) returns (word) { + match (r) { +case storage(slot) { +let result:word; assembly { result := sload(slot) } return result; - } +} +} } } diff --git a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.sol b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.sol index c8260a6c..b000e6cb 100644 --- a/crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.sol +++ b/crates/specialize/tests/fixtures/derived_storage_evidence_replay/types.sol @@ -1,5 +1,5 @@ -import storage_support.{*}; +import * from storage_support; export { Box(*) }; -data Box(a) = Box(a); +enum Box { Box(a) } diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.sol b/crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.sol index be86bb9e..c6a1ec98 100644 --- a/crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.sol +++ b/crates/specialize/tests/fixtures/storage_field_definition_evidence/competitor.sol @@ -1,17 +1,17 @@ -import api.{storage, uint256, CanStore}; +import {storage, uint256, CanStore} from api; export { keepCompetitorReachable }; -instance storage(uint256):CanStore(uint256) { - function store(r:storage(uint256), v:uint256) -> () { +impl CanStore, uint256> { + function store(r: storage, v: uint256) { assembly { sstore(99, 99) } } - function load(r:storage(uint256)) -> uint256 { + function load(r: storage) returns (uint256) { let result:word; assembly { result := sload(99) } return uint256(99); } } -function keepCompetitorReachable() -> word { return 0; } +function keepCompetitorReachable() returns (word) { return 0; } diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.sol b/crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.sol index 86e8d750..9e5af42b 100644 --- a/crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.sol +++ b/crates/specialize/tests/fixtures/storage_field_definition_evidence/lib.sol @@ -1,13 +1,13 @@ -import std.{*}; +import * from std; export { keepLibReachable }; -function keepLibReachable() -> word { return 0; } +function keepLibReachable() returns (word) { return 0; } contract C { value : uint256; - function main() -> uint256 { + function main() returns (uint256) { return value; } } diff --git a/crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol b/crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol index b2e2f14f..751e3ab2 100644 --- a/crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol +++ b/crates/specialize/tests/fixtures/storage_field_definition_evidence/main.sol @@ -1,5 +1,5 @@ -import lib.{keepLibReachable}; -import competitor.{keepCompetitorReachable}; +import {keepLibReachable} from lib; +import {keepCompetitorReachable} from competitor; // This module intentionally has no local contract. The reachable contract // main in lib is still a specialization root, while this module's trait env From b3509e50af61a6aac9561dbb2022d4378fc3156f Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 086/110] Switch the compiler and fixtures to canonical syntax: standard library Co-authored-by: Codex --- std/ABIGeneric.sol | 187 ++++++++++++++--------------- std/Generic.sol | 9 +- std/README.md | 27 +++-- std/StorageGeneric.sol | 237 +++++++++++++++++++------------------ std/dispatch.sol | 258 +++++++++++++++++++---------------------- std/eip712.sol | 13 +-- std/eip7951.sol | 18 +-- std/opcodes.sol | 160 ++++++++++++------------- 8 files changed, 453 insertions(+), 456 deletions(-) diff --git a/std/ABIGeneric.sol b/std/ABIGeneric.sol index 84349cd5..c4406998 100644 --- a/std/ABIGeneric.sol +++ b/std/ABIGeneric.sol @@ -8,46 +8,49 @@ export { decode }; -import std.{*}; -import std.opcodes.{mstore}; -import std.Generic.{*}; +import * from std; +import {mstore} from std.opcodes; +import * from std.Generic; -// Marker class. Importing this module brings ABIDeriving into scope, which is +// Marker trait. Importing this module brings ABIDeriving into scope, which is // the signal DeriveGeneric looks for to auto-derive a per-type ABIDecode -// instance for local data types. ABIAttribs / ABIEncode are provided generically +// impl for local data types. ABIAttribs / ABIEncode are provided generically // via the default Generic bridges below, but ABIDecode cannot be a default -// instance (its decode returns the head variable `a` via Generic.to, a +// impl (its decode returns the head variable `a` via Generic.to, a // result-position type variable the specializer cannot monomorphize), so a -// concrete per-type instance is emitted instead — exactly as for storage. -forall self. class self : ABIDeriving {} +// concrete per-type impl is emitted instead — exactly as for storage. +trait ABIDeriving {} // ─── ABIAttribs for the primitive sum(f, g) type ───────────────────────── // headSize = 32 (tag word) + max(headSize(f), headSize(g)) -forall f g . f:ABIAttribs, g:ABIAttribs => -instance sum(f, g) : ABIAttribs { +impl ABIAttribs> where f: ABIAttribs, g: ABIAttribs { // Head footprint. A *dynamic* sum occupies a single offset word in the head // (its tag + branch payload live in the tail), exactly like any other // dynamic type. Only a fully *static* sum is laid out inline as // tag + widest branch; there both branches are static, so their headSize is // their full size and 32 + max(...) is the correct inline footprint. - function headSize(ty : Proxy(sum(f, g))) -> word { - let pf : Proxy(f); - let pg : Proxy(g); - match and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg)) { - | false => return 32; - | true => return 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); - } + function headSize(ty: Proxy>) returns (word) { + let pf : Proxy; + let pg : Proxy; + match (and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg))) { +case false { +return 32; +} +case true { +return 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); +} +} } - function isStatic(ty : Proxy(sum(f, g))) -> bool { - let pf : Proxy(f); - let pg : Proxy(g); + function isStatic(ty: Proxy>) returns (bool) { + let pf : Proxy; + let pg : Proxy; return and(ABIAttribs.isStatic(pf), ABIAttribs.isStatic(pg)); } } // ─── ABIEncode for sum(f, g) ───────────────────────────────────────────── -// This is the exact mirror of `ABIDecoder(sum(f, g), reader):ABIDecode` below. +// This is the exact mirror of `ABIDecoder, reader>: ABIDecode` below. // // A STATIC sum is laid out inline in the head: // [offset + 0 .. offset + 31] : tag word (0 = inl, 1 = inr) @@ -61,41 +64,46 @@ instance sum(f, g) : ABIAttribs { // The tail body is itself an inline [tag][branch] sum, so decode follows the // offset and reads it exactly as it reads a static sum. -forall f g . f:ABIAttribs, f:ABIEncode, g:ABIAttribs, g:ABIEncode => -instance sum(f, g) : ABIEncode { - function encodeInto(x : sum(f, g), basePtr : word, offset : word, tail : word) -> word { - let prx : Proxy(sum(f, g)); - match ABIAttribs.isStatic(prx) { - // STATIC sum: inline tag at basePtr+offset, branch at offset + 32. - | true => - match x { - | inl(v) => - mstore(basePtr + offset, 0); +impl ABIEncode> where f: ABIAttribs, f: ABIEncode, g: ABIAttribs, g: ABIEncode { + function encodeInto(x: sum, basePtr: word, offset: word, tail: word) returns (word) { + let prx : Proxy>; + match (ABIAttribs.isStatic(prx)) { +// STATIC sum: inline tag at basePtr+offset, branch at offset + 32. +case true { +match (x) { +case inl(v) { +mstore(basePtr + offset, 0); return ABIEncode.encodeInto(v, basePtr, offset + 32, tail); - | inr(v) => - mstore(basePtr + offset, 1); +} +case inr(v) { +mstore(basePtr + offset, 1); return ABIEncode.encodeInto(v, basePtr, offset + 32, tail); - } +} +} // DYNAMIC sum: head slot holds a relative offset to the sum body, which // is laid out inline in the tail. headSize(prx) is 32 here (the offset // word), so the inline head footprint is computed from the branches: // 32 (tag) + max(headSize(f), headSize(g)). - | false => - let pf : Proxy(f); - let pg : Proxy(g); +} +case false { +let pf : Proxy; + let pg : Proxy; mstore(basePtr + offset, tail - basePtr); let newBase = tail; let innerHead = 32 + maxWord(ABIAttribs.headSize(pf), ABIAttribs.headSize(pg)); let newTail = tail + innerHead; - match x { - | inl(v) => - mstore(newBase, 0); + match (x) { +case inl(v) { +mstore(newBase, 0); return ABIEncode.encodeInto(v, newBase, 32, newTail); - | inr(v) => - mstore(newBase, 1); +} +case inr(v) { +mstore(newBase, 1); return ABIEncode.encodeInto(v, newBase, 32, newTail); - } - } +} +} +} +} } } @@ -111,85 +119,80 @@ instance sum(f, g) : ABIEncode { // field, or as a `T[]` element alongside a bare `bytes`/`string` leaf, which // follows its offset the same way. -forall f g reader . - reader : WordReader, - f : ABIAttribs, - g : ABIAttribs, - ABIDecoder(f, reader) : ABIDecode(f), - ABIDecoder(g, reader) : ABIDecode(g) => -instance ABIDecoder(sum(f, g), reader) : ABIDecode(sum(f, g)) { - function decode(ptr : ABIDecoder(sum(f, g), reader), headOffset : word) -> sum(f, g) { - match ptr { - | ABIDecoder(rdr) => - let prx : Proxy(sum(f, g)); +impl ABIDecode, reader>, sum> where reader: WordReader, f: ABIAttribs, g: ABIAttribs, ABIDecoder: ABIDecode, ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder, reader>, headOffset: word) returns (sum) { + match (ptr) { +case ABIDecoder(rdr) { +let prx : Proxy>; // Byte offset (relative to rdr) of this sum's own start. A static sum // is inline at headOffset; a dynamic sum's head slot holds a 32-byte // offset to it, which we follow. We then rebase a decoder onto the // sum start and read [tag][branch] inline — so the tag match (and its // inl/inr) has a single, uniform shape regardless of static/dynamic. let sumStartOff : word; - match ABIAttribs.isStatic(prx) { - | true => sumStartOff = headOffset; - | false => sumStartOff = WordReader.read(WordReader.advance(rdr, headOffset)); - } + match (ABIAttribs.isStatic(prx)) { +case true { +sumStartOff = headOffset; +} +case false { +sumStartOff = WordReader.read(WordReader.advance(rdr, headOffset)); +} +} let sumRdr = WordReader.advance(rdr, sumStartOff); let tag = WordReader.read(sumRdr); - match tag { - | 0 => - let dec_f : ABIDecoder(f, reader) = ABIDecoder(sumRdr); + match (tag) { +case 0 { +let dec_f : ABIDecoder = ABIDecoder(sumRdr); return inl(ABIDecode.decode(dec_f, 32)); - | _ => - let dec_g : ABIDecoder(g, reader) = ABIDecoder(sumRdr); +} +default { +let dec_g : ABIDecoder = ABIDecoder(sumRdr); return inr(ABIDecode.decode(dec_g, 32)); - } - } +} +} +} +} } } // ─── Default bridges: ABIAttribs and ABIEncode via Generic ─────────────── -// Any type 'a' with Generic(rep) inherits its ABI layout from rep. +// Any type `a` with `a: Generic` inherits its ABI layout from `rep`. -forall a rep . a:Generic(rep), rep:ABIAttribs => -default instance a : ABIAttribs { - function headSize(ty : Proxy(a)) -> word { - let prx : Proxy(rep); +default impl ABIAttribs where a: Generic, rep: ABIAttribs { + function headSize(ty: Proxy) returns (word) { + let prx : Proxy; return ABIAttribs.headSize(prx); } - function isStatic(ty : Proxy(a)) -> bool { - let prx : Proxy(rep); + function isStatic(ty: Proxy) returns (bool) { + let prx : Proxy; return ABIAttribs.isStatic(prx); } } -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -default instance a : ABIEncode { - function encodeInto(x : a, basePtr : word, offset : word, tail : word) -> word { +default impl ABIEncode where a: Generic, rep: ABIAttribs, rep: ABIEncode { + function encodeInto(x: a, basePtr: word, offset: word, tail: word) returns (word) { return ABIEncode.encodeInto(Generic.from(x), basePtr, offset, tail); } } // ─── Top-level generic encode function ─────────────────────────────────── -// Serialises any 'a' that has a Generic(rep) instance. -// Only the Generic instance is required — ABIEncode is resolved via the bridge. +// Serialises any `a` that has a `Generic` impl. +// Only the Generic impl is required — ABIEncode is resolved via the bridge. -forall a rep . a:Generic(rep), rep:ABIAttribs, rep:ABIEncode => -function encode(x : a, basePtr : word, offset : word, tail : word) -> word { +function encode(x: a, basePtr: word, offset: word, tail: word) returns (word) where a: Generic, rep: ABIAttribs, rep: ABIEncode { let xrep : rep = Generic.from(x); return ABIEncode.encodeInto(xrep, basePtr, offset, tail); } // ─── Top-level generic decode function ─────────────────────────────────── -// Deserialises any 'a' that has a Generic(rep) instance. -// Only the Generic instance is required — ABIDecode is resolved via the bridge. - -forall a rep reader . - a : Generic(rep), - reader : WordReader, - ABIDecoder(rep, reader) : ABIDecode(rep) => -function decode(ptr : ABIDecoder(a, reader), headOffset : word) -> a { - match ptr { - | ABIDecoder(rdr) => - let rep_ptr : ABIDecoder(rep, reader) = ABIDecoder(rdr); +// Deserialises any `a` that has a `Generic` impl. +// Only the Generic impl is required — ABIDecode is resolved via the bridge. + +function decode(ptr: ABIDecoder, headOffset: word) returns (a) where a: Generic, reader: WordReader, ABIDecoder: ABIDecode { + match (ptr) { +case ABIDecoder(rdr) { +let rep_ptr : ABIDecoder = ABIDecoder(rdr); return Generic.to(ABIDecode.decode(rep_ptr, headOffset)); - } +} +} } diff --git a/std/Generic.sol b/std/Generic.sol index ba30049d..46a56996 100644 --- a/std/Generic.sol +++ b/std/Generic.sol @@ -3,15 +3,14 @@ pragma no-bounded-variable-condition; export { Generic }; -import std.{*}; +import * from std; // MPTC: isomorphism between a user type and its SOP representation. // The representation 'rep' is built from primitive Solcore types: // sum(f, g) with constructors inl / inr // (f, g) pair (product) // () unit -forall a rep. -class a : Generic(rep) { - function from(x : a) -> rep; - function to(x : rep) -> a; +trait Generic { + function from(x: a) returns (rep) ; + function to(x: rep) returns (a) ; } diff --git a/std/README.md b/std/README.md index 19f49cf3..0aef4ccb 100644 --- a/std/README.md +++ b/std/README.md @@ -1,33 +1,36 @@ # Solcore standard library snapshot -The `.solc` files in this directory are vendored from the Haskell reference -implementation at revision `2f372bde2801612814015a22319d0bc51486cbf0`: +The `.sol` files in this directory are syntax-migrated ports of the Haskell +reference standard library at revision +`2f372bde2801612814015a22319d0bc51486cbf0`: ```text https://github.com/argotorg/solcore/tree/2f372bde2801612814015a22319d0bc51486cbf0/std ``` -They are kept byte-for-byte identical to that reference snapshot. The copies -under `crates/parser/tests/fixtures/corpus/ok/std/` are parser fixtures and must -also remain byte-for-byte identical to the files here. +The migration changes surface syntax only; supported semantics remain pinned to +that reference snapshot. The copies under +`crates/parser/tests/fixtures/corpus/ok/std/` are parser fixtures and must remain +byte-for-byte identical to the files here. This README is Rust-repository metadata; it is not part of the upstream std snapshot. ## Synchronization policy -Do not apply Rust-only semantic fixes directly to these `.solc` files. +Do not apply Rust-only semantic fixes directly to these `.sol` files. When a shared standard-library defect is found: 1. reproduce it with the Haskell compiler and the upstream std; 2. fix it in the Haskell reference implementation first; 3. record the new upstream revision; -4. re-vendor the complete upstream std change here and in the parser corpus; -5. verify both backends against the updated snapshot. +4. re-vendor the complete upstream std change and apply the canonical syntax + migration to it here and in the parser corpus; +5. verify both backends against the updated semantic snapshot. -Compiler-side compatibility code may differ between the Haskell and Rust -implementations, but the vendored std source should not. +Compiler-side code and surface spelling may differ between the Haskell and Rust +implementations, but changes to the library's meaning should not. ## Compatibility decisions @@ -42,8 +45,8 @@ spelling, calldata decoding, and result encoding aligned. After every std update, verify at least: ```sh -for file in ABIGeneric.solc Generic.solc StorageGeneric.solc dispatch.solc \ - eip712.solc eip7951.solc opcodes.solc std.solc; do +for file in ABIGeneric.sol Generic.sol StorageGeneric.sol dispatch.sol \ + eip712.sol eip7951.sol opcodes.sol std.sol; do cmp "std/$file" "crates/parser/tests/fixtures/corpus/ok/std/$file" || exit 1 done cargo test -p solcore-parser -p solcore-hir-ty -p solcore-specialize --locked diff --git a/std/StorageGeneric.sol b/std/StorageGeneric.sol index 38e855c5..631b665f 100644 --- a/std/StorageGeneric.sol +++ b/std/StorageGeneric.sol @@ -7,26 +7,26 @@ export { storeGeneric }; -import std.{*}; -import std.opcodes.{sload, sstore}; -import std.Generic.{*}; +import * from std; +import {sload, sstore} from std.opcodes; +import * from std.Generic; -// Marker class. Importing this module brings StorageDeriving into scope, which +// Marker trait. Importing this module brings StorageDeriving into scope, which // is the signal DeriveGeneric looks for to auto-derive StorageSize / CanStore -// instances for local data types (alongside their Generic instance). It carries +// impls for local data types (alongside their Generic impl). It carries // no methods — its mere visibility enables storage derivation. -forall self. class self : StorageDeriving {} +trait StorageDeriving {} // ─── Storage layout for algebraic data types ───────────────────────────── // // This module is the storage analogue of std.ABIGeneric: it teaches the -// StorageSize / StorageType / CanStore classes how to deal with the +// StorageSize / StorageType / CanStore traits how to deal with the // primitive SOP types that `Generic` maps user data types onto // sum(f, g) with constructors inl / inr (choice / tagged union) // (f, g) pair (product) // () unit -// and then bridges every type with a `Generic(rep)` instance to those -// layouts. `Generic` instances are auto-derived for local data types, so +// and then bridges every type with a `Generic` impl to those +// layouts. `Generic` impls are auto-derived for local data types, so // no per-type boilerplate is needed at the use site. // ─── StorageSize for the primitive sum(f, g) type ──────────────────────── @@ -34,11 +34,10 @@ forall self. class self : StorageDeriving {} // largest branch: size = 1 + max(size(f), size(g)). // (StorageSize for () and (a, b) is already provided by std.) -forall f g . f:StorageSize, g:StorageSize => -instance sum(f, g):StorageSize { - function size(x : Proxy(sum(f, g))) -> word { - let f_sz : word = StorageSize.size(Proxy : Proxy(f)); - let g_sz : word = StorageSize.size(Proxy : Proxy(g)); +impl StorageSize> where f: StorageSize, g: StorageSize { + function size(x: Proxy>) returns (word) { + let f_sz : word = StorageSize.size(@f); + let g_sz : word = StorageSize.size(@g); return 1 + maxWord(f_sz, g_sz); } } @@ -46,11 +45,11 @@ instance sum(f, g):StorageSize { // ─── StorageType for () ────────────────────────────────────────────────── // The unit type occupies no slots, so load/store are no-ops. -instance ():StorageType { - function load(ptr : word) -> () { +impl StorageType<()> { + function load(ptr: word) { return (); } - function store(ptr : word, value : ()) -> () { + function store(ptr: word, value: ()) { return (); } } @@ -59,21 +58,21 @@ instance ():StorageType { // Layout: [ptr .. ptr + size(a) - 1] : a // [ptr + size(a) .. ] : b -forall a b . a:StorageType, a:StorageSize, b:StorageType => -instance (a, b):StorageType { - function load(ptr : word) -> (a, b) { - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); +impl StorageType<(a, b)> where a: StorageType, a: StorageSize, b: StorageType { + function load(ptr: word) returns (a, b) { + let a_sz : word = StorageSize.size(@a); let x : a = StorageType.load(ptr); let y : b = StorageType.load(ptr + a_sz); return (x, y); } - function store(ptr : word, value : (a, b)) -> () { - match value { - | (x, y) => - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); + function store(ptr: word, value: (a, b)) { + match (value) { +case (x, y) { +let a_sz : word = StorageSize.size(@a); StorageType.store(ptr, x); StorageType.store(ptr + a_sz, y); - } +} +} } } @@ -82,96 +81,106 @@ instance (a, b):StorageType { // [ptr] : tag word (0 = inl, 1 = inr) // [ptr + 1 .. ] : encoded branch payload -forall f g . f:StorageType, g:StorageType => -instance sum(f, g):StorageType { - function load(ptr : word) -> sum(f, g) { +impl StorageType> where f: StorageType, g: StorageType { + function load(ptr: word) returns (sum) { let tag : word = sload(ptr); - match tag { - | 0 => - let v : f = StorageType.load(ptr + 1); + match (tag) { +case 0 { +let v : f = StorageType.load(ptr + 1); return inl(v); - | _ => - let v : g = StorageType.load(ptr + 1); +} +default { +let v : g = StorageType.load(ptr + 1); return inr(v); - } +} +} } - function store(ptr : word, value : sum(f, g)) -> () { - match value { - | inl(v) => - sstore(ptr, 0); + function store(ptr: word, value: sum) { + match (value) { +case inl(v) { +sstore(ptr, 0); StorageType.store(ptr + 1, v); - | inr(v) => - sstore(ptr, 1); +} +case inr(v) { +sstore(ptr, 1); StorageType.store(ptr + 1, v); - } +} +} } } // ─── Storage layout via CanStore ───────────────────────────────────────── // -// The structural instances above teach StorageType the fixed-slot encoding of +// The structural impls above teach StorageType the fixed-slot encoding of // the SOP primitives. But StorageType can only describe word-packed types: a -// dynamically-sized field such as memory(bytes) has a StorageSize (one slot, -// Solidity-style) and a CanStore instance (storage(bytes):CanStore(memory(bytes))) -// but NO StorageType instance. Routing an ADT's storage through StorageType +// dynamically-sized field such as memory has a StorageSize (one slot, +// Solidity-style) and a CanStore impl (`storage: CanStore>`) +// but NO StorageType impl. Routing an ADT's storage through StorageType // therefore rejects any data type carrying such a field, even though the field // is perfectly storable. // // So we give CanStore the same structural treatment, decomposing the SOP -// representation and storing each leaf through the leaf's OWN CanStore instance. -// Fixed leaves resolve to storage(word)/storage(uint256)/… (which delegate to -// StorageType); dynamic leaves resolve to storage(bytes)/storage(string). Each +// representation and storing each leaf through the leaf's OWN CanStore impl. +// Fixed leaves resolve to storage/storage/… (which delegate to +// StorageType); dynamic leaves resolve to storage/storage. Each // field occupies StorageSize-many slots, so offsets are computed exactly as in // the StorageType layout. The slot handle for a value of type `t` is uniformly -// `storage(t)`, which is why the dynamic leaves below are mirrored at that +// `storage`, which is why the dynamic leaves below are mirrored at that // handle. // The unit type occupies no slots. -instance storage(()) : CanStore(()) { - function store(r : storage(()), v : ()) -> () { +impl CanStore, ()> { + function store(r: storage<()>, v: ()) { return (); } - function load(r : storage(())) -> () { + function load(r: storage<()>) { return (); } } // Product: store `a` at the base slot, `b` size(a) slots later. -forall a b . storage(a):CanStore(a), a:StorageSize, storage(b):CanStore(b) => -instance storage((a, b)) : CanStore((a, b)) { - function store(r : storage((a, b)), v : (a, b)) -> () { - match v { - | (x, y) => - let base : word = Typedef.rep(r); - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); - CanStore.store(storage(base) : storage(a), x); - CanStore.store(storage(base + a_sz) : storage(b), y); - } - } - function load(r : storage((a, b))) -> (a, b) { +impl CanStore, (a, b)> where storage: CanStore, a: StorageSize, storage: CanStore { + function store(r: storage<(a, b)>, v: (a, b)) { + match (v) { +case (x, y) { +let base : word = Typedef.rep(r); + let a_sz : word = StorageSize.size(@a); + let xSlot : storage = storage(base); + let ySlot : storage = storage(base + a_sz); + CanStore.store(xSlot, x); + CanStore.store(ySlot, y); +} +} + } + function load(r: storage<(a, b)>) returns (a, b) { let base : word = Typedef.rep(r); - let a_sz : word = StorageSize.size(Proxy : Proxy(a)); - let x : a = CanStore.load(storage(base) : storage(a)); - let y : b = CanStore.load(storage(base + a_sz) : storage(b)); + let a_sz : word = StorageSize.size(@a); + let xSlot : storage = storage(base); + let ySlot : storage = storage(base + a_sz); + let x : a = CanStore.load(xSlot); + let y : b = CanStore.load(ySlot); return (x, y); } } // Tagged union: slot 0 holds the tag, the branch payload follows. -forall f g . storage(f):CanStore(f), storage(g):CanStore(g) => -instance storage(sum(f, g)) : CanStore(sum(f, g)) { - function store(r : storage(sum(f, g)), v : sum(f, g)) -> () { +impl CanStore>, sum> where storage: CanStore, storage: CanStore { + function store(r: storage>, v: sum) { let base : word = Typedef.rep(r); - match v { - | inl(x) => - sstore(base, 0); - CanStore.store(storage(base + 1) : storage(f), x); - | inr(y) => - sstore(base, 1); - CanStore.store(storage(base + 1) : storage(g), y); - } - } - function load(r : storage(sum(f, g))) -> sum(f, g) { + match (v) { +case inl(x) { +sstore(base, 0); + let slot : storage = storage(base + 1); + CanStore.store(slot, x); +} +case inr(y) { +sstore(base, 1); + let slot : storage = storage(base + 1); + CanStore.store(slot, y); +} +} + } + function load(r: storage>) returns (sum) { let base : word = Typedef.rep(r); let tag : word = sload(base); // NOTE: the loaded payload is inlined directly into inl(...) / inr(...) @@ -181,63 +190,69 @@ instance storage(sum(f, g)) : CanStore(sum(f, g)) { // of the full sum(f, g), so it emits e.g. `inr(y)` and Yul codegen // rejects it (sum nesting off by one). Inlining matches the working // ABIGeneric.decode pattern, so inl/inr pick up the full sum(f, g). - match tag { - | 0 => - return inl(CanStore.load(storage(base + 1) : storage(f))); - | _ => - return inr(CanStore.load(storage(base + 1) : storage(g))); - } + match (tag) { +case 0 { +let slot : storage = storage(base + 1); +return inl(CanStore.load(slot)); +} +default { +let slot : storage = storage(base + 1); +return inr(CanStore.load(slot)); +} +} } } -// Dynamic leaves at the uniform storage(t) handle. std provides the storage(bytes) -// / storage(string) instances (data lives at keccak(slot)); these mirror them at -// the storage(memory(bytes)) / storage(memory(string)) handle the structural -// decomposition asks for, so a memory(bytes) field inside an ADT is storable. -instance storage(memory(bytes)) : CanStore(memory(bytes)) { - function store(r : storage(memory(bytes)), v : memory(bytes)) -> () { - CanStore.store(storage(Typedef.rep(r)) : storage(bytes), v); +// Dynamic leaves at the uniform storage handle. std provides the storage +// / storage impls (data lives at keccak(slot)); these mirror them at +// the storage> / storage> handle the structural +// decomposition asks for, so a memory field inside an ADT is storable. +impl CanStore>, memory> { + function store(r: storage>, v: memory) { + let slot : storage = storage(Typedef.rep(r)); + CanStore.store(slot, v); } - function load(r : storage(memory(bytes))) -> memory(bytes) { - return CanStore.load(storage(Typedef.rep(r)) : storage(bytes)); + function load(r: storage>) returns (memory) { + let slot : storage = storage(Typedef.rep(r)); + return CanStore.load(slot); } } -instance storage(memory(string)) : CanStore(memory(string)) { - function store(r : storage(memory(string)), v : memory(string)) -> () { - CanStore.store(storage(Typedef.rep(r)) : storage(string), v); +impl CanStore>, memory> { + function store(r: storage>, v: memory) { + let slot : storage = storage(Typedef.rep(r)); + CanStore.store(slot, v); } - function load(r : storage(memory(string))) -> memory(string) { - return CanStore.load(storage(Typedef.rep(r)) : storage(string)); + function load(r: storage>) returns (memory) { + let slot : storage = storage(Typedef.rep(r)); + return CanStore.load(slot); } } // StorageType / CanStore for an ADT are NOT provided here as blanket bridges. // -// A `default instance a:StorageType` would have its `load` return the head +// A `default impl StorageType` would have its `load` return the head // variable `a` via Generic.to — but the specializer cannot monomorphize a -// result-position type variable of a default instance (it is not pinned by the +// result-position type variable of a default impl (it is not pinned by the // arguments), so loads panic. Likewise a tyvar-headed `default a:CanStore(b)` // is non-functional (accepts any storable b), so contract field access cannot // infer the stored type from the slot type. // -// Instead, DeriveGeneric emits a concrete, per-type storage(T):CanStore(T) -// instance (see Solcore.Desugarer.DeriveGeneric) where the data type is fixed -// in the instance head; it delegates to the structural CanStore instances above +// Instead, DeriveGeneric emits a concrete, per-type +// `storage: CanStore` impl (see Solcore.Desugarer.DeriveGeneric) where the +// data type is fixed in the impl head; it delegates to the structural CanStore impls above // via the type's Generic representation. StorageSize is likewise derived // per-type for the field layout. // ─── Top-level helpers ─────────────────────────────────────────────────── // Convenience wrappers mirroring std.ABIGeneric's encode / decode: persist or -// read back any 'a' that has a Generic(rep) instance at a raw storage slot. +// read back any `a` that has a `Generic` impl at a raw storage slot. -forall a rep . a:Generic(rep), rep:StorageType => -function storeGeneric(slot : word, value : a) -> () { +function storeGeneric(slot: word, value: a) where a: Generic, rep: StorageType { StorageType.store(slot, Generic.from(value)); } -forall a rep . a:Generic(rep), rep:StorageType => -function loadGeneric(slot : word) -> a { +function loadGeneric(slot: word) returns (a) where a: Generic, rep: StorageType { let r : rep = StorageType.load(slot); return Generic.to(r); } diff --git a/std/dispatch.sol b/std/dispatch.sol index ef9672a3..408c1415 100644 --- a/std/dispatch.sol +++ b/std/dispatch.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.opcodes.{callvalue, calldatasize, calldataload, shr, return_}; -import std.Generic.{*}; +import * from std; +import {callvalue, calldatasize, calldataload, shr, return_} from std.opcodes; +import * from std.Generic; export { ABIString, @@ -29,38 +29,36 @@ pragma no-bounded-variable-condition ; // A contract contains a tuple of methods and a single fallback // TODO: implement receive() -data Contract(methods, fb) = Contract(methods,fb); +enum Contract { Contract(methods, fb) } // A method contains an implementation (fn) as well as it's name and type signature -data Method(name, payability, args, rets, fn) = Method(Proxy(name), Proxy(payability), Proxy(args), Proxy(rets), fn); +enum Method { Method(Proxy, Proxy, Proxy, Proxy, fn) } // Contains the implementation for the fallback (fn) as well as it's type signature -data Fallback(payability, args, rets, fn) = Fallback(Proxy(payability), Proxy(args), Proxy(rets), fn); +enum Fallback { Fallback(Proxy, Proxy, Proxy, fn) } // --- Method Selectors --- -forall ty . class ty:ABIString { // deprecated - function append(head : word, tail : word, prx : Proxy(ty)) -> word; +trait ABIString { // deprecated + function append(head: word, tail: word, prx: Proxy) returns (word) ; } -forall t.class t:SigString { function sigStr(x:Proxy(t)) -> string; } +trait SigString { function sigStr(x: Proxy) returns (string) ; } -forall t. t: SigString => -function sigStr(p:Proxy(t)) -> string { SigString.sigStr(p) } +function sigStr(p: Proxy) returns (string) where t: SigString { SigString.sigStr(p) } -instance uint256 : SigString { function sigStr(x:Proxy(uint256)) -> string { "uint256" }} -instance bytes32 : SigString { function sigStr(x:Proxy(bytes32)) -> string { "bytes32" }} -instance bytes4 : SigString { function sigStr(x:Proxy(bytes4)) -> string { "bytes4" }} -instance address : SigString { function sigStr(x:Proxy(address)) -> string { "address" }} -instance bool : SigString { function sigStr(x:Proxy(bool)) -> string { "bool" }} -instance memory(string) : SigString { function sigStr(x:Proxy(memory(string))) -> string { "string" }} -instance memory(bytes) : SigString { function sigStr(x:Proxy(memory(bytes))) -> string { "bytes" }} -instance ():SigString { function sigStr(x:Proxy(())) -> string { "" } } +impl SigString { function sigStr(x: Proxy) returns (string) { "uint256" }} +impl SigString { function sigStr(x: Proxy) returns (string) { "bytes32" }} +impl SigString { function sigStr(x: Proxy) returns (string) { "bytes4" }} +impl SigString
{ function sigStr(x: Proxy
) returns (string) { "address" }} +impl SigString { function sigStr(x: Proxy) returns (string) { "bool" }} +impl SigString> { function sigStr(x: Proxy>) returns (string) { "string" }} +impl SigString> { function sigStr(x: Proxy>) returns (string) { "bytes" }} +impl SigString<()> { function sigStr(x: Proxy<()>) returns (string) { "" } } -forall a b. a:SigString, b: SigString => -instance (a,b):SigString { - function sigStr(x:Proxy((a,b))) -> string { - SigString.sigStr( Proxy:Proxy(a) ) + "," + SigString.sigStr( Proxy:Proxy(b) ) +impl SigString<(a, b)> where a: SigString, b: SigString { + function sigStr(x: Proxy<(a, b)>) returns (string) { + SigString.sigStr( @a ) + "," + SigString.sigStr( @b ) } } @@ -71,10 +69,9 @@ instance (a,b):SigString { // `sum(uint256,uint256)` and `(uint256,uint256)` hash to distinct selectors. It // makes ADT-typed parameters produce a deterministic selector; refine here if a // specific on-the-wire sum convention is needed. -forall f g. f:SigString, g: SigString => -instance sum(f,g):SigString { - function sigStr(x:Proxy(sum(f,g))) -> string { - "sum(" + SigString.sigStr( Proxy:Proxy(f) ) + "," + SigString.sigStr( Proxy:Proxy(g) ) + ")" +impl SigString> where f: SigString, g: SigString { + function sigStr(x: Proxy>) returns (string) { + "sum(" + SigString.sigStr( @f ) + "," + SigString.sigStr( @g ) + ")" } } @@ -82,47 +79,40 @@ instance sum(f,g):SigString { // The element carries its own (structural, for ADTs) signature, so an array of a // sum type reads `sum(l,r)[]`. Location is transparent to the ABI, so this keys // on the calldata form the dispatch decodes from. -forall t. t:SigString => -instance calldata(array(t)):SigString { - function sigStr(x:Proxy(calldata(array(t)))) -> string { - SigString.sigStr( Proxy:Proxy(t) ) + "[]" +impl SigString>> where t: SigString { + function sigStr(x: Proxy>>) returns (string) { + SigString.sigStr( @t ) + "[]" } } // Any data type inherits its ABI signature from its Generic representation, the // same way ABIAttribs / ABIEncode bridge through Generic in std.ABIGeneric. This // lets the dispatch take ADT-typed parameters (e.g. a Signature) without a -// hand-written SigString instance per type. -forall a rep. a:Generic(rep), rep:SigString => -default instance a:SigString { - function sigStr(x:Proxy(a)) -> string { - SigString.sigStr( Proxy:Proxy(rep) ) +// hand-written SigString impl per type. +default impl SigString where a: Generic, rep: SigString { + function sigStr(x: Proxy) returns (string) { + SigString.sigStr( @rep ) } } -forall name f args rets payability. - f: invokable(args,rets), name:SigString, args:SigString, rets:SigString => -instance Method(name,payability,args,rets,f):SigString { - function sigStr(x:Proxy(Method(name,payability,args,rets,f))) -> string { - sigStr(Proxy:Proxy(name)) + "(" + sigStr(Proxy:Proxy(args)) + ")" +impl SigString> where f: invokable, name: SigString, args: SigString, rets: SigString { + function sigStr(x: Proxy>) returns (string) { + sigStr(@name) + "(" + sigStr(@args) + ")" } } -forall ty . class ty:Selector { - function compute(prx : Proxy(ty)) -> bytes4; +trait Selector { + function compute(prx: Proxy) returns (bytes4) ; } // Computes the selector hash for a given method -// this is a class with a single instance since it made some of the downstream definitions a bit cleaner to define +// This trait has a single impl, which keeps downstream definitions simpler. // NOTE: for efficiency purposes this leaves dirty data past the end of the free memory pointer -forall name payability args rets fn - . name:SigString - , args:SigString -=> instance Method(name,payability,args,rets,fn):Selector { - function compute(prx : Proxy(Method(name,payability,args,rets,fn))) -> bytes4 { +impl Selector> where name: SigString, args: SigString { + function compute(prx: Proxy>) returns (bytes4) { // let hash : word = keccakLit(sigStr(prx)); - let hash = keccakLit(sigStr(Proxy:Proxy(name)) + "(" + sigStr(Proxy:Proxy(args)) + ")"); + let hash = keccakLit(sigStr(@name) + "(" + sigStr(@args) + ")"); return bytes4(shr(224, hash)); } } @@ -130,81 +120,63 @@ forall name payability args rets fn // --- Method Execution --- // Describes how to execute a given method / fallback -forall ty . class ty:ExecMethod { - function exec(x: ty) -> (); +trait ExecMethod { + function exec(x: ty) ; } // If fn matches the provided args/ret types, then we can execute any non-payable method -forall name args rets fn - . fn:invokable(args,rets) - , args:ABIAttribs - , rets:ABIAttribs - , ABIDecoder(args,CalldataWordReader):ABIDecode(args) - , rets:ABIEncode -=> instance Method(name,NonPayable,args,rets,fn):ExecMethod { - function exec(m : Method(name,NonPayable,args,rets,fn)) -> () { - match m { - | Method(pnm,ppayability,pargs,prets,fn) => - // non-payable methods must reject any callvalue before running - MethodLevelCallvalueCheck.checkCallvalue(Proxy : Proxy(NonPayable)); +impl ExecMethod> where fn: invokable, args: ABIAttribs, rets: ABIAttribs, ABIDecoder: ABIDecode, rets: ABIEncode { + function exec(m: Method) { + match (m) { +case Method(pnm,ppayability,pargs,prets,fn) { +// non-payable methods must reject any callvalue before running + MethodLevelCallvalueCheck.checkCallvalue(@NonPayable); do_exec(pargs, prets, fn); - } +} +} } } // If fn matches the provided args/ret types, then we can execute any payable method // payable methods skip the callvalue check entirely -forall name args rets fn - . fn:invokable(args,rets) - , args:ABIAttribs - , rets:ABIAttribs - , ABIDecoder(args,CalldataWordReader):ABIDecode(args) - , rets:ABIEncode -=> instance Method(name,Payable,args,rets,fn):ExecMethod { - function exec(m : Method(name,Payable,args,rets,fn)) -> () { - match m { - | Method(pnm,ppayability,pargs,prets,fn) => - do_exec(pargs, prets, fn); - } +impl ExecMethod> where fn: invokable, args: ABIAttribs, rets: ABIAttribs, ABIDecoder: ABIDecode, rets: ABIEncode { + function exec(m: Method) { + match (m) { +case Method(pnm,ppayability,pargs,prets,fn) { +do_exec(pargs, prets, fn); +} +} } } -// Fallbacks have no ABI-decoded inputs or outputs, so the instance is +// Fallbacks have no ABI-decoded inputs or outputs, so the impl is // specialised to args = rets = () and bypasses the calldata length check // and ABI decode/encode entirely. -forall payability fn - . fn:invokable((),()) - , payability:MethodLevelCallvalueCheck -=> instance Fallback(payability,(),(),fn):ExecMethod { - function exec(fb : Fallback(payability,(),(),fn)) -> () { - match fb { - | Fallback(ppayability, pargs, prets, fn) => - MethodLevelCallvalueCheck.checkCallvalue(Proxy : Proxy(payability)); +impl ExecMethod> where fn: invokable<(), ()>, payability: MethodLevelCallvalueCheck { + function exec(fb: Fallback) { + match (fb) { +case Fallback(ppayability, pargs, prets, fn) { +MethodLevelCallvalueCheck.checkCallvalue(@payability); fn(()); assembly { stop() } - } +} +} } } -forall args rets fn - . fn:invokable(args,rets) - , args:ABIAttribs - , rets:ABIAttribs - , ABIDecoder(args,CalldataWordReader):ABIDecode(args) - , rets:ABIEncode -=> function do_exec(pargs : Proxy(args), prets : Proxy(rets), fn : fn) -> () { +function do_exec(pargs: Proxy, prets: Proxy, fn: fn) where fn: invokable, args: ABIAttribs, rets: ABIAttribs, ABIDecoder: ABIDecode, rets: ABIEncode { // check we have enough calldata for the head of args require(calldatasize() >= (ABIAttribs.headSize(pargs) + 4), Error(0x08638556)); // ABIInputTruncated() // TODO: calldatasize checks for dynamic types // abi decode args from calldata - let ptr : calldata(bytes) = calldata(4); + let ptr : calldata = calldata(4); // TODO: this needs entirely too many type annotations - let args : args = abi_decode(ptr, pargs, Proxy : Proxy(CalldataWordReader)); + let args : args = abi_decode(ptr, pargs, @CalldataWordReader); // call fn with args // TODO: why are type annotations needed here? @@ -218,44 +190,50 @@ forall args rets fn // --- Method Dispatch --- // For a given tuple of methods this executes the method specified by the first four bytes of calldata -forall ty . class ty:RunDispatch { - function go(methods : ty) -> (); +trait RunDispatch { + function go(methods: ty) ; } // We can dispatch to a single executable method with a known selector -forall name payability args rets fn - . Method(name,payability,args,rets,fn):ExecMethod - , Method(name,payability,args,rets,fn):Selector -=> instance Method(name,payability,args,rets,fn):RunDispatch { - function go(method : Method(name,payability,args,rets,fn)) -> () { - match selector_matches(Proxy : Proxy(Method(name,payability,args,rets,fn))) { - | true => ExecMethod.exec(method); - | false => return (); - } +impl RunDispatch> where Method: ExecMethod, Method: Selector { + function go(method: Method) { + match (selector_matches(@Method)) { +case true { +ExecMethod.exec(method); +} +case false { +return (); +} +} } } // Base case: a contract with no methods has nothing to dispatch to -instance ():RunDispatch { - function go(methods : ()) -> () { } -} - -// Recursive instance -forall n m . n:ExecMethod, n:Selector, m:RunDispatch => instance (n,m):RunDispatch { - function go(methods : (n,m)) -> () { - match methods { - | (method_n, rest) => - match selector_matches(Proxy : Proxy(n)) { - | true => ExecMethod.exec(method_n); - | false => RunDispatch.go(rest); - } - } +impl RunDispatch<()> { + function go(methods: ()) { } +} + +// Recursive impl. +impl RunDispatch<(n, m)> where n: ExecMethod, n: Selector, m: RunDispatch { + function go(methods: (n, m)) { + match (methods) { +case (method_n, rest) { +match (selector_matches(@n)) { +case true { +ExecMethod.exec(method_n); +} +case false { +RunDispatch.go(rest); +} +} +} +} } } // TODO: we only wanna do the calldataload once // Given evidence of a type with a known selector, we can check if it matches the selector in the first four bytes of calldata -forall ty . ty:Selector => function selector_matches(prx : Proxy(ty)) -> bool { +function selector_matches(prx: Proxy) returns (bool) where ty: Selector { let candidate = Typedef.rep(Selector.compute(prx)); let selector = shr(224, calldataload(0)); return selector == candidate; @@ -263,20 +241,20 @@ forall ty . ty:Selector => function selector_matches(prx : Proxy(ty)) -> bool { // --- Callvalue Checks --- -data Payable; -data NonPayable; +enum Payable {} +enum NonPayable {} -forall ty . class ty:MethodLevelCallvalueCheck { - function checkCallvalue(pty : Proxy(ty)) -> (); +trait MethodLevelCallvalueCheck { + function checkCallvalue(pty: Proxy) ; } // no callvalue check for Payable methods -instance Payable:MethodLevelCallvalueCheck { - function checkCallvalue(prx : Proxy(Payable)) -> () { } +impl MethodLevelCallvalueCheck { + function checkCallvalue(prx: Proxy) { } } // NonPayable methods revert if passed value -instance NonPayable:MethodLevelCallvalueCheck { - function checkCallvalue(prx : Proxy(NonPayable)) -> () { +impl MethodLevelCallvalueCheck { + function checkCallvalue(prx: Proxy) { let NonPayableReceivedValue = Error(0xb5988ea3); require(callvalue() == 0, NonPayableReceivedValue); } @@ -285,17 +263,16 @@ instance NonPayable:MethodLevelCallvalueCheck { // --- Contract Execution --- // Describes how to execute a given contract -forall c . class c:RunContract { - function exec(v : c) -> (); +trait RunContract { + function exec(v: c) ; } // If we have a dispatch for the contracts methods, and we know how to execute it's fallback, then we can define an entrypoint -forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(methods, fb):RunContract { - function exec(c : Contract(methods, fb)) -> () { - match c { - | Contract(ms, fb) => - - // TODO: if all methods are non payable then we should life the callvalue check here +impl RunContract> where methods: RunDispatch, fb: ExecMethod { + function exec(c: Contract) { + match (c) { +case Contract(ms, fb) { +// TODO: if all methods are non payable then we should life the callvalue check here // set free memory pointer to the output of memoryguard // https://docs.soliditylang.org/en/v0.8.30/yul.html#memoryguard @@ -311,12 +288,13 @@ forall methods fb . methods:RunDispatch, fb:ExecMethod => instance Contract(meth // fallthrough to fallback -- this will be reached upon short input // or no matching selector ExecMethod.exec(fb); - } +} +} } } // This is the default fallback used if none is defined. -function fallback_default_implementation() -> () { +function fallback_default_implementation() { let NoSelectorMatchedWithoutFallback = Error(0x4924aef0); revertWithError(NoSelectorMatchedWithoutFallback); } diff --git a/std/eip712.sol b/std/eip712.sol index 9e6f687b..7218ef29 100644 --- a/std/eip712.sol +++ b/std/eip712.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.opcodes.{mstore, keccak256, shl}; +import * from std; +import {mstore, keccak256, shl} from std.opcodes; export { eip712Digest, @@ -25,12 +25,7 @@ export { // keccak256 of the (dynamic) name / version strings — typically compile-time // constants produced with `keccakLit`. `chainId` / `verifyingContract` are // encoded as their left-padded 32-byte words. -function eip712DomainSeparator( - nameHash: bytes32, - versionHash: bytes32, - chainId: uint256, - verifyingContract: address -) -> bytes32 { +function eip712DomainSeparator(nameHash: bytes32, versionHash: bytes32, chainId: uint256, verifyingContract: address) returns (bytes32) { let typeHash = keccakLit("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Lay the five 32-byte words out contiguously and hash them. We borrow the // area above the free-memory pointer as scratch (as `ecrecover` does): the @@ -48,7 +43,7 @@ function eip712DomainSeparator( // Binds a domain separator to a message's struct hash, yielding the final // EIP-712 digest: keccak256(0x19 0x01 ‖ domainSeparator ‖ structHash). The // two-byte 0x1901 prefix occupies the leading bytes of the first word. -function eip712Digest(domainSeparator: bytes32, structHash: bytes32) -> bytes32 { +function eip712Digest(domainSeparator: bytes32, structHash: bytes32) returns (bytes32) { let ptr = get_free_memory(); mstore(ptr, shl(240, 0x1901)); // 0x1901 in the leading two bytes mstore(ptr + 2, Typedef.rep(domainSeparator)); diff --git a/std/eip7951.sol b/std/eip7951.sol index 16f2ca50..a5ae3fe4 100644 --- a/std/eip7951.sol +++ b/std/eip7951.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.opcodes.{mstore, mload, gas, staticcall}; +import * from std; +import {mstore, mload, gas, staticcall} from std.opcodes; export { p256verify }; @@ -9,7 +9,7 @@ export { p256verify }; // returns a 32-byte word equal to 1 on a valid signature and empty output on an // invalid one; we pre-clear the [0, 32) scratch slot so the failing case reads // back as 0. -function p256verify(hash: bytes32, r: bytes32, s: bytes32, qx: bytes32, qy: bytes32) -> bool { +function p256verify(hash: bytes32, r: bytes32, s: bytes32, qx: bytes32, qy: bytes32) returns (bool) { let hash_ = Typedef.rep(hash); let r_ = Typedef.rep(r); let s_ = Typedef.rep(s); @@ -27,8 +27,12 @@ function p256verify(hash: bytes32, r: bytes32, s: bytes32, qx: bytes32, qy: byte let ret = staticcall(gas(), 0x100, ptr, 160, 0, 32); require(ret != 0, Error(0x1fb6bf04)); // P256VerifyCallFailed() // NOTE: we are doing the inverse check here for safety, so not using tobool() - match mload(0) { - | 1 => return true; - | _ => return false; - } + match (mload(0)) { +case 1 { +return true; +} +default { +return false; +} +} } diff --git a/std/opcodes.sol b/std/opcodes.sol index 991d18eb..d17ff757 100644 --- a/std/opcodes.sol +++ b/std/opcodes.sol @@ -84,13 +84,13 @@ export { selfdestruct }; -function stop() -> () { +function stop() { assembly { stop() } } -function add(a: word, b: word) -> word { +function add(a: word, b: word) returns (word) { let res; assembly { res := add(a, b) @@ -98,7 +98,7 @@ function add(a: word, b: word) -> word { return res; } -function mul(a: word, b: word) -> word { +function mul(a: word, b: word) returns (word) { let res; assembly { res := mul(a, b) @@ -106,7 +106,7 @@ function mul(a: word, b: word) -> word { return res; } -function sub(a: word, b: word) -> word { +function sub(a: word, b: word) returns (word) { let res; assembly { res := sub(a, b) @@ -114,7 +114,7 @@ function sub(a: word, b: word) -> word { return res; } -function div(a: word, b: word) -> word { +function div(a: word, b: word) returns (word) { let res; assembly { res := div(a, b) @@ -122,7 +122,7 @@ function div(a: word, b: word) -> word { return res; } -function sdiv(a: word, b: word) -> word { +function sdiv(a: word, b: word) returns (word) { let res; assembly { res := sdiv(a, b) @@ -130,7 +130,7 @@ function sdiv(a: word, b: word) -> word { return res; } -function mod(a: word, b: word) -> word { +function mod(a: word, b: word) returns (word) { let res; assembly { res := mod(a, b) @@ -138,7 +138,7 @@ function mod(a: word, b: word) -> word { return res; } -function smod(a: word, b: word) -> word { +function smod(a: word, b: word) returns (word) { let res; assembly { res := smod(a, b) @@ -146,7 +146,7 @@ function smod(a: word, b: word) -> word { return res; } -function addmod(a: word, b: word, c: word) -> word { +function addmod(a: word, b: word, c: word) returns (word) { let res; assembly { res := addmod(a, b, c) @@ -154,7 +154,7 @@ function addmod(a: word, b: word, c: word) -> word { return res; } -function mulmod(a: word, b: word, c: word) -> word { +function mulmod(a: word, b: word, c: word) returns (word) { let res; assembly { res := mulmod(a, b, c) @@ -162,7 +162,7 @@ function mulmod(a: word, b: word, c: word) -> word { return res; } -function exp(a: word, b: word) -> word { +function exp(a: word, b: word) returns (word) { let res; assembly { res := exp(a, b) @@ -170,7 +170,7 @@ function exp(a: word, b: word) -> word { return res; } -function signextend(a: word, b: word) -> word { +function signextend(a: word, b: word) returns (word) { let res; assembly { res := signextend(a, b) @@ -178,7 +178,7 @@ function signextend(a: word, b: word) -> word { return res; } -function lt(a: word, b: word) -> word { +function lt(a: word, b: word) returns (word) { let res; assembly { res := lt(a, b) @@ -186,7 +186,7 @@ function lt(a: word, b: word) -> word { return res; } -function gt(a: word, b: word) -> word { +function gt(a: word, b: word) returns (word) { let res; assembly { res := gt(a, b) @@ -194,7 +194,7 @@ function gt(a: word, b: word) -> word { return res; } -function slt(a: word, b: word) -> word { +function slt(a: word, b: word) returns (word) { let res; assembly { res := slt(a, b) @@ -202,7 +202,7 @@ function slt(a: word, b: word) -> word { return res; } -function sgt(a: word, b: word) -> word { +function sgt(a: word, b: word) returns (word) { let res; assembly { res := sgt(a, b) @@ -210,7 +210,7 @@ function sgt(a: word, b: word) -> word { return res; } -function eq(a: word, b: word) -> word { +function eq(a: word, b: word) returns (word) { let res; assembly { res := eq(a, b) @@ -218,7 +218,7 @@ function eq(a: word, b: word) -> word { return res; } -function iszero(a: word) -> word { +function iszero(a: word) returns (word) { let res; assembly { res := iszero(a) @@ -226,7 +226,7 @@ function iszero(a: word) -> word { return res; } -function and(a: word, b: word) -> word { +function and(a: word, b: word) returns (word) { let res; assembly { res := and(a, b) @@ -234,7 +234,7 @@ function and(a: word, b: word) -> word { return res; } -function or(a: word, b: word) -> word { +function or(a: word, b: word) returns (word) { let res; assembly { res := or(a, b) @@ -242,7 +242,7 @@ function or(a: word, b: word) -> word { return res; } -function xor(a: word, b: word) -> word { +function xor(a: word, b: word) returns (word) { let res; assembly { res := xor(a, b) @@ -250,7 +250,7 @@ function xor(a: word, b: word) -> word { return res; } -function not(a: word) -> word { +function not(a: word) returns (word) { let res; assembly { res := not(a) @@ -258,7 +258,7 @@ function not(a: word) -> word { return res; } -function byte(a: word, b: word) -> word { +function byte(a: word, b: word) returns (word) { let res; assembly { res := byte(a, b) @@ -266,7 +266,7 @@ function byte(a: word, b: word) -> word { return res; } -function shl(a: word, b: word) -> word { +function shl(a: word, b: word) returns (word) { let res; assembly { res := shl(a, b) @@ -274,7 +274,7 @@ function shl(a: word, b: word) -> word { return res; } -function shr(a: word, b: word) -> word { +function shr(a: word, b: word) returns (word) { let res; assembly { res := shr(a, b) @@ -282,7 +282,7 @@ function shr(a: word, b: word) -> word { return res; } -function sar(a: word, b: word) -> word { +function sar(a: word, b: word) returns (word) { let res; assembly { res := sar(a, b) @@ -290,7 +290,7 @@ function sar(a: word, b: word) -> word { return res; } -function clz(a: word) -> word { +function clz(a: word) returns (word) { let res; assembly { res := clz(a) @@ -298,7 +298,7 @@ function clz(a: word) -> word { return res; } -function keccak256(a: word, b: word) -> word { +function keccak256(a: word, b: word) returns (word) { let res; assembly { res := keccak256(a, b) @@ -306,7 +306,7 @@ function keccak256(a: word, b: word) -> word { return res; } -function address() -> word { +function address() returns (word) { let res; assembly { res := address() @@ -314,7 +314,7 @@ function address() -> word { return res; } -function balance(a: word) -> word { +function balance(a: word) returns (word) { let res; assembly { res := balance(a) @@ -322,7 +322,7 @@ function balance(a: word) -> word { return res; } -function origin() -> word { +function origin() returns (word) { let res; assembly { res := origin() @@ -330,7 +330,7 @@ function origin() -> word { return res; } -function caller() -> word { +function caller() returns (word) { let res; assembly { res := caller() @@ -338,7 +338,7 @@ function caller() -> word { return res; } -function callvalue() -> word { +function callvalue() returns (word) { let res; assembly { res := callvalue() @@ -346,7 +346,7 @@ function callvalue() -> word { return res; } -function calldataload(a: word) -> word { +function calldataload(a: word) returns (word) { let res; assembly { res := calldataload(a) @@ -354,7 +354,7 @@ function calldataload(a: word) -> word { return res; } -function calldatasize() -> word { +function calldatasize() returns (word) { let res; assembly { res := calldatasize() @@ -362,13 +362,13 @@ function calldatasize() -> word { return res; } -function calldatacopy(a: word, b: word, c: word) -> () { +function calldatacopy(a: word, b: word, c: word) { assembly { calldatacopy(a, b, c) } } -function codesize() -> word { +function codesize() returns (word) { let res; assembly { res := codesize() @@ -376,13 +376,13 @@ function codesize() -> word { return res; } -function codecopy(a: word, b: word, c: word) -> () { +function codecopy(a: word, b: word, c: word) { assembly { codecopy(a, b, c) } } -function gasprice() -> word { +function gasprice() returns (word) { let res; assembly { res := gasprice() @@ -390,7 +390,7 @@ function gasprice() -> word { return res; } -function extcodesize(a: word) -> word { +function extcodesize(a: word) returns (word) { let res; assembly { res := extcodesize(a) @@ -398,13 +398,13 @@ function extcodesize(a: word) -> word { return res; } -function extcodecopy(a: word, b: word, c: word, d: word) -> () { +function extcodecopy(a: word, b: word, c: word, d: word) { assembly { extcodecopy(a, b, c, d) } } -function returndatasize() -> word { +function returndatasize() returns (word) { let res; assembly { res := returndatasize() @@ -412,13 +412,13 @@ function returndatasize() -> word { return res; } -function returndatacopy(a: word, b: word, c: word) -> () { +function returndatacopy(a: word, b: word, c: word) { assembly { returndatacopy(a, b, c) } } -function extcodehash(a: word) -> word { +function extcodehash(a: word) returns (word) { let res; assembly { res := extcodehash(a) @@ -426,7 +426,7 @@ function extcodehash(a: word) -> word { return res; } -function blockhash(a: word) -> word { +function blockhash(a: word) returns (word) { let res; assembly { res := blockhash(a) @@ -434,7 +434,7 @@ function blockhash(a: word) -> word { return res; } -function coinbase() -> word { +function coinbase() returns (word) { let res; assembly { res := coinbase() @@ -442,7 +442,7 @@ function coinbase() -> word { return res; } -function timestamp() -> word { +function timestamp() returns (word) { let res; assembly { res := timestamp() @@ -450,7 +450,7 @@ function timestamp() -> word { return res; } -function number() -> word { +function number() returns (word) { let res; assembly { res := number() @@ -458,7 +458,7 @@ function number() -> word { return res; } -function prevrandao() -> word { +function prevrandao() returns (word) { let res; assembly { res := prevrandao() @@ -466,7 +466,7 @@ function prevrandao() -> word { return res; } -function gaslimit() -> word { +function gaslimit() returns (word) { let res; assembly { res := gaslimit() @@ -474,7 +474,7 @@ function gaslimit() -> word { return res; } -function chainid() -> word { +function chainid() returns (word) { let res; assembly { res := chainid() @@ -482,7 +482,7 @@ function chainid() -> word { return res; } -function selfbalance() -> word { +function selfbalance() returns (word) { let res; assembly { res := selfbalance() @@ -490,7 +490,7 @@ function selfbalance() -> word { return res; } -function basefee() -> word { +function basefee() returns (word) { let res; assembly { res := basefee() @@ -498,7 +498,7 @@ function basefee() -> word { return res; } -function blobhash(a: word) -> word { +function blobhash(a: word) returns (word) { let res; assembly { res := blobhash(a) @@ -506,7 +506,7 @@ function blobhash(a: word) -> word { return res; } -function blobbasefee() -> word { +function blobbasefee() returns (word) { let res; assembly { res := blobbasefee() @@ -514,13 +514,13 @@ function blobbasefee() -> word { return res; } -function pop(a: word) -> () { +function pop(a: word) { assembly { pop(a) } } -function mload(a: word) -> word { +function mload(a: word) returns (word) { let res; assembly { res := mload(a) @@ -528,19 +528,19 @@ function mload(a: word) -> word { return res; } -function mstore(a: word, b: word) -> () { +function mstore(a: word, b: word) { assembly { mstore(a, b) } } -function mstore8(a: word, b: word) -> () { +function mstore8(a: word, b: word) { assembly { mstore8(a, b) } } -function sload(a: word) -> word { +function sload(a: word) returns (word) { let res; assembly { res := sload(a) @@ -548,13 +548,13 @@ function sload(a: word) -> word { return res; } -function sstore(a: word, b: word) -> () { +function sstore(a: word, b: word) { assembly { sstore(a, b) } } -function msize() -> word { +function msize() returns (word) { let res; assembly { res := msize() @@ -562,7 +562,7 @@ function msize() -> word { return res; } -function gas() -> word { +function gas() returns (word) { let res; assembly { res := gas() @@ -570,7 +570,7 @@ function gas() -> word { return res; } -function tload(a: word) -> word { +function tload(a: word) returns (word) { let res; assembly { res := tload(a) @@ -578,49 +578,49 @@ function tload(a: word) -> word { return res; } -function tstore(a: word, b: word) -> () { +function tstore(a: word, b: word) { assembly { tstore(a, b) } } -function mcopy(a: word, b: word, c: word) -> () { +function mcopy(a: word, b: word, c: word) { assembly { mcopy(a, b, c) } } -function log0(a: word, b: word) -> () { +function log0(a: word, b: word) { assembly { log0(a, b) } } -function log1(a: word, b: word, c: word) -> () { +function log1(a: word, b: word, c: word) { assembly { log1(a, b, c) } } -function log2(a: word, b: word, c: word, d: word) -> () { +function log2(a: word, b: word, c: word, d: word) { assembly { log2(a, b, c, d) } } -function log3(a: word, b: word, c: word, d: word, e: word) -> () { +function log3(a: word, b: word, c: word, d: word, e: word) { assembly { log3(a, b, c, d, e) } } -function log4(a: word, b: word, c: word, d: word, e: word, f: word) -> () { +function log4(a: word, b: word, c: word, d: word, e: word, f: word) { assembly { log4(a, b, c, d, e, f) } } -function create(a: word, b: word, c: word) -> word { +function create(a: word, b: word, c: word) returns (word) { let res; assembly { res := create(a, b, c) @@ -628,7 +628,7 @@ function create(a: word, b: word, c: word) -> word { return res; } -function call(a: word, b: word, c: word, d: word, e: word, f: word, g: word) -> word { +function call(a: word, b: word, c: word, d: word, e: word, f: word, g: word) returns (word) { let res; assembly { res := call(a, b, c, d, e, f, g) @@ -636,7 +636,7 @@ function call(a: word, b: word, c: word, d: word, e: word, f: word, g: word) -> return res; } -function callcode(a: word, b: word, c: word, d: word, e: word, f: word, g: word) -> word { +function callcode(a: word, b: word, c: word, d: word, e: word, f: word, g: word) returns (word) { let res; assembly { res := callcode(a, b, c, d, e, f, g) @@ -644,13 +644,13 @@ function callcode(a: word, b: word, c: word, d: word, e: word, f: word, g: word) return res; } -function return_(a: word, b: word) -> () { +function return_(a: word, b: word) { assembly { return(a, b) } } -function delegatecall(a: word, b: word, c: word, d: word, e: word, f: word) -> word { +function delegatecall(a: word, b: word, c: word, d: word, e: word, f: word) returns (word) { let res; assembly { res := delegatecall(a, b, c, d, e, f) @@ -658,7 +658,7 @@ function delegatecall(a: word, b: word, c: word, d: word, e: word, f: word) -> w return res; } -function create2(a: word, b: word, c: word, d: word) -> word { +function create2(a: word, b: word, c: word, d: word) returns (word) { let res; assembly { res := create2(a, b, c, d) @@ -666,7 +666,7 @@ function create2(a: word, b: word, c: word, d: word) -> word { return res; } -function staticcall(a: word, b: word, c: word, d: word, e: word, f: word) -> word { +function staticcall(a: word, b: word, c: word, d: word, e: word, f: word) returns (word) { let res; assembly { res := staticcall(a, b, c, d, e, f) @@ -674,13 +674,13 @@ function staticcall(a: word, b: word, c: word, d: word, e: word, f: word) -> wor return res; } -function revert(a: word, b: word) -> () { +function revert(a: word, b: word) { assembly { revert(a, b) } } -function invalid() -> () { +function invalid() { assembly { invalid() } From e41d80ff77bed727d3eee197a51e920cc08abfb6 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 087/110] Switch the compiler and fixtures to canonical syntax: standard library Co-authored-by: Codex --- std/opcodes.sol | 2 +- std/std.sol | 888 ++++++++++++++++++++++++++---------------------- 2 files changed, 485 insertions(+), 405 deletions(-) diff --git a/std/opcodes.sol b/std/opcodes.sol index d17ff757..a8193fb5 100644 --- a/std/opcodes.sol +++ b/std/opcodes.sol @@ -686,7 +686,7 @@ function invalid() { } } -function selfdestruct(a: word) -> () { +function selfdestruct(a: word) { assembly { selfdestruct(a) } diff --git a/std/std.sol b/std/std.sol index e095c148..697beb0f 100644 --- a/std/std.sol +++ b/std/std.sol @@ -1,4 +1,4 @@ -import std.opcodes.{add, sub, mul, div, mod, addmod as addmod_, mulmod as mulmod_, and as and_, or as or_, xor as xor_, shl, shr, eq, not as not_, gt as gt_, iszero, keccak256, mstore, mload, mcopy, sstore, sload, gas, calldataload, calldatacopy, returndatasize, returndatacopy, log1 as log1_, call, staticcall, revert as revert_, invalid}; +import {add, sub, mul, div, mod, addmod as addmod_, mulmod as mulmod_, and as and_, or as or_, xor as xor_, shl, shr, eq, not as not_, gt as gt_, iszero, keccak256, mstore, mload, mcopy, sstore, sload, gas, calldataload, calldatacopy, returndatasize, returndatacopy, log1 as log1_, call, staticcall, revert as revert_, invalid} from std.opcodes; pragma no-patterson-condition ABIEncode, Num, Array, ArrayPush, Eq, Ord; pragma no-coverage-condition ABIDecode, MemoryType, Array, ArrayPush, RValueIdxAccess; @@ -175,19 +175,18 @@ export { */ -forall t.t:Typedef(word) => -function log1(v:t, topic:word) -> () { +function log1(v: t, topic: word) where t: Typedef { let w : word = Typedef.rep(v); mstore(0, w); log1_(0, 32, topic); } -function unimplemented() -> () { +function unimplemented() { let Unimplemented = Error(0x6e128399); revertWithError(Unimplemented); } -function out_of_bounds() -> () { +function out_of_bounds() { let OutOfBounds = Error(0xb4120f14); revertWithError(OutOfBounds); } @@ -197,65 +196,68 @@ function out_of_bounds() -> () { // ------------------------------------------------------------------ // EmitHull has special handling for `revertLit("...")` after MastEval has // constant-folded the argument to a string literal. -function revertLit(comptime s: string) -> () { +function revertLit(comptime s: string) { unimplemented(); // Sanity check if folding ignores it. return (); } // Empty revert. -function revertEmpty() -> () { +function revertEmpty() { revert_(0, 0); } // Bottom: a value of any type. absurd never returns, it reverts, so it can -// stand in for a result of any type. Used to derive class instances for empty +// stand in for a result of any type. Used to derive trait impls for empty // data types (which have no values, so the method bodies are unreachable). The -// recursive tail satisfies the forall a . a return type; execution never +// recursive tail satisfies the generic result type `a`; execution never // reaches it because revertEmpty() aborts first. -forall a . function absurd() -> a { +function absurd() returns (a) { // Despite looking like an infinite loop, this reverts: revertEmpty() // aborts execution on the first line, so the recursive return absurd() // is never actually run. The recursion exists only to give the body a - // value of type a, satisfying the forall a . a return type. + // value of type `a`, satisfying the generic result type. revertEmpty(); return absurd(); } // TODO: use bytes4 -data Error = Error(word) | Empty | Msg(memory(string)); +enum Error { Error(word), Empty, Msg(memory) } // A string literal can be used as an Error: `require(cond, "message")` reverts -// with the message. The literal is materialized into memory(string) here; MastEval +// with the message. The literal is materialized into memory here; MastEval // erases the comptime-only parameter by cloning this method per literal, so // the materializer sees a literal rather than a parameter. -instance Error : Str { - function fromString(s: string) -> Error { +impl Str { + function fromString(s: string) returns (Error) { return Error.Msg(Str.fromString(s)); } } // Revert with Error selector. -function revertWithError(e:Error) -> () { - match e { - | .Error(selector) => - mstore(0, selector); +function revertWithError(e: Error) { + match (e) { +case .Error(selector) { +mstore(0, selector); // We only care about the BE MSB. revert_(28, 4); - | .Empty => - revert_(0, 0); - | .Msg(msg) => - let msg_ = Typedef.rep(msg); +} +case .Empty { +revert_(0, 0); +} +case .Msg(msg) { +let msg_ = Typedef.rep(msg); revert_(msg_ + 32, mload(msg_)); - } +} +} } -function assert(cond: bool) -> () { +function assert(cond: bool) { if (!cond) { invalid(); } } -function require(cond: bool, e: Error) -> () { +function require(cond: bool, e: Error) { if (!cond) { revertWithError(e); } @@ -264,271 +266,316 @@ function require(cond: bool, e: Error) -> () { // --- booleans --- // TODO: this should short circuit. probably needs some compiler magic to do so. -function and(x: bool, y: bool) -> bool { - match x, y { - | true, y => return y; - | false, _ => return false; - } +function and(x: bool, y: bool) returns (bool) { + match (x, y) { +case (true, y) { +return y; +} +case (false, _) { +return false; +} +} } // TODO: this should short circuit. probably needs some compiler magic to do so. -function or(x: bool, y: bool) -> bool { - match x, y { - | true, _ => return true; - | false, y => return y; - } +function or(x: bool, y: bool) returns (bool) { + match (x, y) { +case (true, _) { +return true; +} +case (false, y) { +return y; +} +} } -function not(b:bool) -> bool { - match b { - | false => return true; - | true => return false; - } +function not(b: bool) returns (bool) { + match (b) { +case false { +return true; +} +case true { +return false; +} +} } -function frombool(b : bool) -> word { - match b { - | false => return 0; - | true => return 1; - } +function frombool(b: bool) returns (word) { + match (b) { +case false { +return 0; +} +case true { +return 1; +} +} } -function tobool(x: word) -> bool { - match x { - | 0 => return false; - | _ => return true; - } +function tobool(x: word) returns (bool) { + match (x) { +case 0 { +return false; +} +default { +return true; +} +} } // --- Tuple projections --- -forall a b . function fst(p: (a, b)) -> a { - match p { - | (a, _) => return a; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (a, _) { +return a; +} +} } -forall a b . function snd(p: (a, b)) -> b { - match p { - | (_, b) => return b; - } +function snd(p: (a, b)) returns (b) { + match (p) { +case (_, b) { +return b; +} +} } // --- Proxy --- // Proxy is a unit type that can be used to pass Types as paramaters at runtime -data Proxy(t) = Proxy; +enum Proxy { Proxy } // --- Type Abstraction --- -forall abs rep . class abs:Typedef(rep) { - function abs(x:rep) -> abs; - function rep(x:abs) -> rep; +trait Typedef { + function abs(x: rep) returns (abs) ; + function rep(x: abs) returns (rep) ; } -forall t. -default instance t:Typedef(t) { - function abs(x:t) -> t { return x; } - function rep(x:t) -> t { return x; } +default impl Typedef { + function abs(x: t) returns (t) { return x; } + function rep(x: t) returns (t) { return x; } } // --- Equality --- // Note: All these are used by the compiler by name. -forall a. -class a:Eq { - function eq(x:a, y:a) -> bool; +trait Eq { + function eq(x: a, y: a) returns (bool) ; } -forall a. a:Eq => -function ne(x:a, y:a) -> bool { +function ne(x: a, y: a) returns (bool) where a: Eq { return not(Eq.eq(x,y)); } // --- Ordering --- // Note: All these are used by the compiler by name. -forall a. a:Eq => -class a:Ord { - function gt(x:a, y:a) -> bool; +trait Ord where a: Eq { + function gt(x: a, y: a) returns (bool) ; } -forall a. a:Ord => -function gt(x:a, y:a) -> bool { +function gt(x: a, y: a) returns (bool) where a: Ord { return Ord.gt(x,y); } -forall a. a:Ord => -function le(x:a, y:a) -> bool { +function le(x: a, y: a) returns (bool) where a: Ord { return not(Ord.gt(x,y)); } -forall a. a:Ord => -function ge(x:a, y:a) -> bool { +function ge(x: a, y: a) returns (bool) where a: Ord { return le(y,x); } -forall a. a:Ord => -function lt(x:a, y:a) -> bool { +function lt(x: a, y: a) returns (bool) where a: Ord { return Ord.gt(y,x); } -// --- Generic deriving: structural instances over the representation universe --- +// --- Generic deriving: structural impls over the representation universe --- // These let `#[derive(Eq)]` / `#[derive(Ord)]` work for any data type through -// its Generic(rep) instance, where rep is built from (), sum(f, g) and (f, g). +// its `Generic` impl, where `rep` is built from `()`, `sum` and +// `(f, g)`. -instance () : Eq { - function eq(x : (), y : ()) -> bool { +impl Eq<()> { + function eq(x: (), y: ()) returns (bool) { return true; } } -forall f g . f:Eq, g:Eq => -instance sum(f, g) : Eq { - function eq(x : sum(f, g), y : sum(f, g)) -> bool { - match x { - | inl(a) => - match y { - | inl(b) => return Eq.eq(a, b); - | inr(b) => return false; - } - | inr(a) => - match y { - | inl(b) => return false; - | inr(b) => return Eq.eq(a, b); - } - } +impl Eq> where f: Eq, g: Eq { + function eq(x: sum, y: sum) returns (bool) { + match (x) { +case inl(a) { +match (y) { +case inl(b) { +return Eq.eq(a, b); +} +case inr(b) { +return false; +} +} +} +case inr(a) { +match (y) { +case inl(b) { +return false; +} +case inr(b) { +return Eq.eq(a, b); +} +} +} +} } } -forall f g . f:Eq, g:Eq => -instance (f, g) : Eq { - function eq(x : (f, g), y : (f, g)) -> bool { - match x { - | (a1, b1) => - match y { - | (a2, b2) => - match Eq.eq(a1, a2) { - | true => return Eq.eq(b1, b2); - | false => return false; - } - } - } +impl Eq<(f, g)> where f: Eq, g: Eq { + function eq(x: (f, g), y: (f, g)) returns (bool) { + match (x) { +case (a1, b1) { +match (y) { +case (a2, b2) { +match (Eq.eq(a1, a2)) { +case true { +return Eq.eq(b1, b2); +} +case false { +return false; +} +} +} +} +} +} } } -instance () : Ord { - function gt(x : (), y : ()) -> bool { +impl Ord<()> { + function gt(x: (), y: ()) returns (bool) { return false; } } -forall f g . f:Ord, g:Ord => -instance sum(f, g) : Ord { - function gt(x : sum(f, g), y : sum(f, g)) -> bool { - match x { - | inl(a) => - match y { - | inl(b) => return Ord.gt(a, b); - | inr(b) => return false; - } - | inr(a) => - match y { - | inl(b) => return true; - | inr(b) => return Ord.gt(a, b); - } - } +impl Ord> where f: Ord, g: Ord { + function gt(x: sum, y: sum) returns (bool) { + match (x) { +case inl(a) { +match (y) { +case inl(b) { +return Ord.gt(a, b); +} +case inr(b) { +return false; +} +} +} +case inr(a) { +match (y) { +case inl(b) { +return true; +} +case inr(b) { +return Ord.gt(a, b); +} +} +} +} } } -forall f g . f:Ord, g:Ord => -instance (f, g) : Ord { - function gt(x : (f, g), y : (f, g)) -> bool { - match x { - | (a1, b1) => - match y { - | (a2, b2) => - match Ord.gt(a1, a2) { - | true => return true; - | false => - match Eq.eq(a1, a2) { - | true => return Ord.gt(b1, b2); - | false => return false; - } - } - } - } +impl Ord<(f, g)> where f: Ord, g: Ord { + function gt(x: (f, g), y: (f, g)) returns (bool) { + match (x) { +case (a1, b1) { +match (y) { +case (a2, b2) { +match (Ord.gt(a1, a2)) { +case true { +return true; +} +case false { +match (Eq.eq(a1, a2)) { +case true { +return Ord.gt(b1, b2); +} +case false { +return false; +} +} +} +} +} +} +} +} } } // --- Arithmetic --- // Note: All these are used by the compiler by name. -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Sub { - function sub(l: t, r: t) -> t; +trait Sub { + function sub(l: t, r: t) returns (t) ; } -forall t . class t:Mul { - function mul(l: t, r: t) -> t; +trait Mul { + function mul(l: t, r: t) returns (t) ; } -forall t . class t:Div { - function div(l: t, r: t) -> t; +trait Div { + function div(l: t, r: t) returns (t) ; } -forall t . class t:Mod { - function mod(l: t, r: t) -> t; +trait Mod { + function mod(l: t, r: t) returns (t) ; } -forall t . class t:BitAnd { - function band(l: t, r: t) -> t; +trait BitAnd { + function band(l: t, r: t) returns (t) ; } -forall t . class t:BitOr { - function bor(l: t, r: t) -> t; +trait BitOr { + function bor(l: t, r: t) returns (t) ; } -forall t . class t:BitXor { - function bxor(l: t, r: t) -> t; +trait BitXor { + function bxor(l: t, r: t) returns (t) ; } -forall t . class t:BitNot { - function bnot(x: t) -> t; +trait BitNot { + function bnot(x: t) returns (t) ; } -forall t . class t:Bounded { - function minVal() -> t; - function maxVal() -> t; +trait Bounded { + function minVal() returns (t) ; + function maxVal() returns (t) ; } -forall t . t:Bounded => -function maxVal() -> t { return Bounded.maxVal(); } +function maxVal() returns (t) where t: Bounded { return Bounded.maxVal(); } -// umbrella class -forall a. a:Add, a:Sub, a:Bounded, a:Eq, a:Ord, a:Typedef(word) => -class a:Num { - function maxVal() -> a; - function toWord(x:a) -> word; - function fromWord(x:word) -> a; - function fromInteger(comptime x:integer) -> comptime a; - function add(x:a, y:a) -> a; - function sub(x:a, y:a) -> a; - function gt(x:a, y:a) -> bool; +// Umbrella trait. +trait Num where a: Add, a: Sub, a: Bounded, a: Eq, a: Ord, a: Typedef { + function maxVal() returns (a) ; + function toWord(x: a) returns (word) ; + function fromWord(x: word) returns (a) ; + function fromInteger(comptime x: integer) returns (comptime) ; + function add(x: a, y: a) returns (a) ; + function sub(x: a, y: a) returns (a) ; + function gt(x: a, y: a) returns (bool) ; } -forall a. a:Add, a:Sub, a:Bounded, a:Eq, a:Ord, a:Typedef(word) => -default instance a:Num { - function maxVal() -> a { return Bounded.maxVal(); } - function toWord(x:a) -> word { return Typedef.rep(x); } - function fromWord(x:word) -> a { return Typedef.abs(x); } - function fromInteger(comptime x:integer) -> comptime a { return Typedef.abs(wordFromInteger(x)); } - function add(x:a, y:a) -> a { return Add.add(x,y); } - function sub(x:a, y:a) -> a { return Sub.sub(x,y); } - function gt(x: a, y: a) -> bool { return Ord.gt(x, y); } +default impl Num where a: Add, a: Sub, a: Bounded, a: Eq, a: Ord, a: Typedef { + function maxVal() returns (a) { return Bounded.maxVal(); } + function toWord(x: a) returns (word) { return Typedef.rep(x); } + function fromWord(x: word) returns (a) { return Typedef.abs(x); } + function fromInteger(comptime x: integer) returns (comptime) { return Typedef.abs(wordFromInteger(x)); } + function add(x: a, y: a) returns (a) { return Add.add(x,y); } + function sub(x: a, y: a) returns (a) { return Sub.sub(x,y); } + function gt(x: a, y: a) returns (bool) { return Ord.gt(x, y); } } // --- Word Arithmetic & Logic --- @@ -536,181 +583,189 @@ default instance a:Num { // These are intended to be folded by MastEval when their arguments are // statically known word values. -function eqWord(x:word, y:word) -> bool { +function eqWord(x: word, y: word) returns (bool) { return tobool(eq(x, y)); } -function gtWord(x:word, y:word) -> bool { +function gtWord(x: word, y: word) returns (bool) { return tobool(gt_(x, y)); } -function maxWord(a : word, b : word) -> word { - match gtWord(a, b) { - | true => return a; - | false => return b; - } +function maxWord(a: word, b: word) returns (word) { + match (gtWord(a, b)) { +case true { +return a; +} +case false { +return b; +} +} } -function minWord(a : word, b : word) -> word { - match gtWord(a, b) { - | true => return b; - | false => return a; - } +function minWord(a: word, b: word) returns (word) { + match (gtWord(a, b)) { +case true { +return b; +} +case false { +return a; +} +} } -function addWord(l: word, r: word) -> word { +function addWord(l: word, r: word) returns (word) { return add(l, r); } -function subWord(l: word, r: word) -> word { +function subWord(l: word, r: word) returns (word) { return sub(l, r); } // Bitwise AND -function bandWord(x: word, y: word) -> word { +function bandWord(x: word, y: word) returns (word) { return and_(x, y); } // Bitwise OR -function borWord(x: word, y: word) -> word { +function borWord(x: word, y: word) returns (word) { return or_(x, y); } // Bitwise XOR -function bxorWord(x: word, y: word) -> word { +function bxorWord(x: word, y: word) returns (word) { return xor_(x, y); } // Bitwise NOT -function bnotWord(x: word) -> word { +function bnotWord(x: word) returns (word) { return not_(x); } // Bitwise SHL -function bshlWord(x: word, y: word) -> word { +function bshlWord(x: word, y: word) returns (word) { return shl(x, y); } // Bitwise SHR -function bshrWord(x: word, y: word) -> word { +function bshrWord(x: word, y: word) returns (word) { return shr(x, y); } -instance word:Eq { - function eq(x:word, y:word) -> bool { +impl Eq { + function eq(x: word, y: word) returns (bool) { return eqWord(x, y); } } -instance word:Ord { - function gt(x:word, y:word) -> bool { +impl Ord { + function gt(x: word, y: word) returns (bool) { return gtWord(x, y); } } -instance word:Add { - function add(l: word, r: word) -> word { +impl Add { + function add(l: word, r: word) returns (word) { return addWord(l, r); } } -instance word:Sub { - function sub(l: word, r: word) -> word { +impl Sub { + function sub(l: word, r: word) returns (word) { return subWord(l, r); } } -function mulWord(l: word, r: word) -> word { +function mulWord(l: word, r: word) returns (word) { return mul(l, r); } -instance word:Mul { - function mul(l: word, r: word) -> word { +impl Mul { + function mul(l: word, r: word) returns (word) { return mulWord(l, r); } } -instance word:Div { - function div(l: word, r: word) -> word { +impl Div { + function div(l: word, r: word) returns (word) { return div(l, r); } } -instance word:Mod { - function mod (l : word, r : word) -> word { +impl Mod { + function mod(l: word, r: word) returns (word) { return mod(l, r); } } -instance word:BitAnd { - function band(l: word, r: word) -> word { +impl BitAnd { + function band(l: word, r: word) returns (word) { return bandWord(l, r); } } -instance word:BitOr { - function bor(l: word, r: word) -> word { +impl BitOr { + function bor(l: word, r: word) returns (word) { return borWord(l, r); } } -instance word:BitXor { - function bxor(l: word, r: word) -> word { +impl BitXor { + function bxor(l: word, r: word) returns (word) { return bxorWord(l, r); } } -instance word:BitNot { - function bnot(x: word) -> word { +impl BitNot { + function bnot(x: word) returns (word) { return bnotWord(x); } } -instance integer : Eq { - function eq(x : integer, y : integer) -> bool { +impl Eq { + function eq(x: integer, y: integer) returns (bool) { return integerEq(x, y); } } -instance integer : Ord { - function gt(x : integer, y : integer) -> bool { +impl Ord { + function gt(x: integer, y: integer) returns (bool) { return integerLt(y, x); } } -instance integer : Add { - function add(l : integer, r : integer) -> integer { +impl Add { + function add(l: integer, r: integer) returns (integer) { return integerAdd(l, r); } } -instance integer : Sub { - function sub(l : integer, r : integer) -> integer { +impl Sub { + function sub(l: integer, r: integer) returns (integer) { return integerSub(l, r); } } -instance integer : Mul { - function mul(l : integer, r : integer) -> integer { +impl Mul { + function mul(l: integer, r: integer) returns (integer) { return integerMul(l, r); } } -instance word:Bounded { - function maxVal() -> word { +impl Bounded { + function maxVal() returns (word) { return 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; } - function minVal () -> word { + function minVal() returns (word) { return 0; } } -function hash1(x: word) -> word { +function hash1(x: word) returns (word) { mstore(0, x); return keccak256(0, 32); } -function hash2(x: word, y: word) -> word { +function hash2(x: word, y: word) returns (word) { mstore(0, x); mstore(32, y); return keccak256(0, 64); @@ -718,249 +773,270 @@ function hash2(x: word, y: word) -> word { // --- Value Types --- -forall t. t:Typedef(word) => -function toWord(x:t) -> word { return Typedef.rep(x); } +function toWord(x: t) returns (word) where t: Typedef { return Typedef.rep(x); } -data uint256 = uint256(word); -instance uint256:Typedef(word) { - function abs(w: word) -> uint256 { +enum uint256 { uint256(word) } +impl Typedef { + function abs(w: word) returns (uint256) { return uint256(w); } - function rep(x: uint256) -> word { - match x { - | uint256(w) => return w; - } + function rep(x: uint256) returns (word) { + match (x) { +case uint256(w) { +return w; +} +} } } -instance uint256:Add { - function add(x : uint256, y : uint256) -> uint256 { +impl Add { + function add(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Add.add(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Sub { - function sub(x : uint256, y : uint256) -> uint256 { +impl Sub { + function sub(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Sub.sub(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Mul { - function mul(x : uint256, y : uint256) -> uint256 { +impl Mul { + function mul(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Mul.mul(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Div { - function div(x : uint256, y : uint256) -> uint256 { +impl Div { + function div(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Div.div(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:Mod { - function mod(x : uint256, y : uint256) -> uint256 { +impl Mod { + function mod(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(Mod.mod(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitAnd { - function band(x : uint256, y : uint256) -> uint256 { +impl BitAnd { + function band(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(BitAnd.band(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitOr { - function bor(x : uint256, y : uint256) -> uint256 { +impl BitOr { + function bor(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(BitOr.bor(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitXor { - function bxor(x : uint256, y : uint256) -> uint256 { +impl BitXor { + function bxor(x: uint256, y: uint256) returns (uint256) { return Typedef.abs(BitXor.bxor(Typedef.rep(x), Typedef.rep(y))); } } -instance uint256:BitNot { - function bnot(x : uint256) -> uint256 { +impl BitNot { + function bnot(x: uint256) returns (uint256) { return Typedef.abs(BitNot.bnot(Typedef.rep(x))); } } -instance uint256:Eq { - function eq(x : uint256, y : uint256) -> bool { +impl Eq { + function eq(x: uint256, y: uint256) returns (bool) { return Eq.eq(Typedef.rep(x), Typedef.rep(y)); } } -instance uint256:Ord { - function gt(x : uint256, y : uint256) -> bool { +impl Ord { + function gt(x: uint256, y: uint256) returns (bool) { return Ord.gt(Typedef.rep(x), Typedef.rep(y)); } } -instance uint256:Bounded { - function maxVal() -> uint256 { +impl Bounded { + function maxVal() returns (uint256) { return uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); } - function minVal () -> uint256 { + function minVal() returns (uint256) { return uint256(0); } } -instance uint256:Int { - function fromInteger(x:integer) -> uint256 { +impl Int { + function fromInteger(x: integer) returns (uint256) { return uint256(wordFromInteger(x)); } } -function addmod(x: uint256, y: uint256, k: uint256) -> uint256 { +function addmod(x: uint256, y: uint256, k: uint256) returns (uint256) { require(k != uint256(0), Error(0x7125cbb9)); // AddModWithZero() return Typedef.abs(addmod_(Typedef.rep(x), Typedef.rep(y), Typedef.rep(k))); } -function mulmod(x: uint256, y: uint256, k: uint256) -> uint256 { +function mulmod(x: uint256, y: uint256, k: uint256) returns (uint256) { require(k != uint256(0), Error(0xdaea23b9)); // MulModWithZero() return Typedef.abs(mulmod_(Typedef.rep(x), Typedef.rep(y), Typedef.rep(k))); } -data byte = byte(word); -instance byte:Typedef(word) { - function abs(w: word) -> byte { +enum byte { byte(word) } +impl Typedef { + function abs(w: word) returns (byte) { return byte(w); } - function rep(x: byte) -> word { - match x { - | byte(w) => return w; - } + function rep(x: byte) returns (word) { + match (x) { +case byte(w) { +return w; +} +} } } // --- Address --- -data address = address(word); +enum address { address(word) } -instance address:Typedef(word) { - function rep(x:address) -> word { - match x { - | address(y) => return y; - } +impl Typedef { + function rep(x: address) returns (word) { + match (x) { +case address(y) { +return y; +} +} } - function abs(x:word) -> address { + function abs(x: word) returns (address) { return address(x); } } -instance address:Eq { - function eq(x : address , y : address) -> bool { +impl Eq
{ + function eq(x: address, y: address) returns (bool) { return Eq.eq(Typedef.rep(x), Typedef.rep(y)); } } // --- Bytes4 --- -data bytes4 = bytes4(word); +enum bytes4 { bytes4(word) } -instance bytes4:Typedef(word) { - function rep(b : bytes4) -> word { - match b { - | bytes4(w) => return w; - } +impl Typedef { + function rep(b: bytes4) returns (word) { + match (b) { +case bytes4(w) { +return w; +} +} } - function abs(w : word) -> bytes4 { + function abs(w: word) returns (bytes4) { return bytes4(w); } } // --- Bytes32 --- -data bytes32 = bytes32(word); +enum bytes32 { bytes32(word) } -instance bytes32:Typedef(word) { - function rep(b : bytes32) -> word { - match b { - | bytes32(w) => return w; - } +impl Typedef { + function rep(b: bytes32) returns (word) { + match (b) { +case bytes32(w) { +return w; +} +} } - function abs(w : word) -> bytes32 { + function abs(w: word) returns (bytes32) { return bytes32(w); } } -instance bytes32:Eq { - function eq(x : bytes32, y : bytes32) -> bool { +impl Eq { + function eq(x: bytes32, y: bytes32) returns (bool) { return Eq.eq(Typedef.rep(x), Typedef.rep(y)); } } -instance bytes32:Ord { - function gt(x : bytes32, y : bytes32) -> bool { +impl Ord { + function gt(x: bytes32, y: bytes32) returns (bool) { return Ord.gt(Typedef.rep(x), Typedef.rep(y)); } } // --- Pointers --- -data memory(t) = memory(word); -forall t . instance memory(t) : Typedef(word) { - function abs(x: word) -> memory(t) { +enum memory { memory(word) } +impl Typedef, word> { + function abs(x: word) returns (memory) { return memory(x); } - function rep(x: memory(t)) -> word { - match x { - | memory(w) => return w; - } + function rep(x: memory) returns (word) { + match (x) { +case memory(w) { +return w; +} +} } } -data storage(t) = storage(word); -forall t . instance storage(t) : Typedef(word) { - function abs(x: word) -> storage(t) { +enum storage { storage(word) } +impl Typedef, word> { + function abs(x: word) returns (storage) { return storage(x); } - function rep(x: storage(t)) -> word { - match x { - | storage(w) => return w; - } + function rep(x: storage) returns (word) { + match (x) { +case storage(w) { +return w; +} +} } } -data calldata(t) = calldata(word); -forall t . instance calldata(t) : Typedef(word) { - function abs(x: word) -> calldata(t) { +enum calldata { calldata(word) } +impl Typedef, word> { + function abs(x: word) returns (calldata) { return calldata(x); } - function rep(x: calldata(t)) -> word { - match x { - | calldata(w) => return w; - } + function rep(x: calldata) returns (word) { + match (x) { +case calldata(w) { +return w; +} +} } } -data returndata(t) = returndata(word); -forall t . instance returndata(t) : Typedef(word) { - function abs(x: word) -> returndata(t) { +enum returndata { returndata(word) } +impl Typedef, word> { + function abs(x: word) returns (returndata) { return returndata(x); } - function rep(x: returndata(t)) -> word { - match x { - | returndata(w) => return w; - } + function rep(x: returndata) returns (word) { + match (x) { +case returndata(w) { +return w; +} +} } } -data mapping(member, index) = mapping(word) ; +enum mapping { mapping(word) } -data array(member) = array(word) ; +enum array { array(word) } // --- Low-level memory ops -function strlen(s:memory(string)) -> word { - match s { | memory(a) => return mload(a); } +function strlen(s: memory) returns (word) { + match (s) { +case memory(a) { +return mload(a); +} +} } // --- Memory Utilities --- @@ -969,35 +1045,35 @@ function strlen(s:memory(string)) -> word { // The word stored in memory at index 0x40 is used to store the start of the currently unused memory region // returns the value stored in memory(0x40) -function get_free_memory() -> word { +function get_free_memory() returns (word) { return mload(0x40); } // set the value stored in memory(0x40) -function set_free_memory(loc : word) -> () { +function set_free_memory(loc: word) { mstore(0x40, loc); } // Allocate memory and update the memory pointer. -function allocate_memory(size : word) -> word { +function allocate_memory(size: word) returns (word) { let ptr = get_free_memory(); set_free_memory(ptr + size); return ptr; } -function allocate_zeroed_memory(size: word) -> word { +function allocate_zeroed_memory(size: word) returns (word) { let ptr = allocate_memory(size); zeroize_memory(ptr, size); return ptr; } // Clears a memory area. -function zeroize_memory(ptr: word, len: word) -> () { +function zeroize_memory(ptr: word, len: word) { let end_ptr = ptr + len; // Zero out 32-byte words. for (let i = 0; i < len / 32; i += 1, ptr += 32) { - mstore(ptr, 0) + mstore(ptr, 0); } // Zero out trailing bytes. We rely on the zero-slot (0x60-0x7f). @@ -1008,9 +1084,9 @@ function zeroize_memory(ptr: word, len: word) -> () { // types that can be written to and read from at a uint256 index // TODO: this needs to be split into LValue / RValue variants for `=` desugaring -forall t val . class t:IndexAccess(val) { - function get(c: t, i: uint256) -> val; - function set(c: t, i: uint256, v: val) -> (); +trait IndexAccess { + function get(c: t, i: uint256) returns (val) ; + function set(c: t, i: uint256, v: val) ; } // --- DynArray --- @@ -1018,18 +1094,18 @@ forall t val . class t:IndexAccess(val) { // Word arrays with a size known only at runtime // types with a size smaller than `word` will not be packed, so a `DynArray(byte)` will waste a lot of space // TODO: storage representation -data DynArray(t); +enum DynArray {} // Layout: the length lives at `loc`, so element i lives at `loc + 32 + i*32`. // An index is in bounds when i < length. -forall t . t:Typedef(word) => instance memory(DynArray(t)):IndexAccess(t) { - function get(ptr : memory(DynArray(t)), i : uint256) -> t { +impl IndexAccess>, t> where t: Typedef { + function get(ptr: memory>, i: uint256) returns (t) { let i_: word = Typedef.rep(i); let loc : word = Typedef.rep(ptr); if (i_ >= mload(loc)) { out_of_bounds(); } return Typedef.abs(mload(loc + 32 + (i_ * 32))); } - function set(arr : memory(DynArray(t)), i : uint256, val : t) -> () { + function set(arr: memory>, i: uint256, val: t) { let i_ : word = Typedef.rep(i); let loc : word = Typedef.rep(arr); if (i_ >= mload(loc)) { out_of_bounds(); } @@ -1043,19 +1119,17 @@ forall t . t:Typedef(word) => instance memory(DynArray(t)):IndexAccess(t) { // arrayLitInit(... arrayLitInit(arrayLitNew(n), 0, e1) ..., n-1, en) // The chain is a plain expression: each step returns the array it wrote to. -forall t . t:Typedef(word) => -function arrayLitNew(n : uint256) -> memory(DynArray(t)) { - let prx : Proxy(t); +function arrayLitNew(n: uint256) returns (memory>) where t: Typedef { + let prx : Proxy; return allocateDynamicArray(prx, Typedef.rep(n)); } -forall t . t:Typedef(word) => -function arrayLitInit(arr : memory(DynArray(t)), i : uint256, v : t) -> memory(DynArray(t)) { +function arrayLitInit(arr: memory>, i: uint256, v: t) returns (memory>) where t: Typedef { IndexAccess.set(arr, i, v); return arr; } -forall t . function allocateDynamicArray(prx : Proxy(t), length : word) -> memory(DynArray(t)) { +function allocateDynamicArray(prx: Proxy, length: word) returns (memory>) { // size of allocation in bytes let sz : word = (length + 1) * 32; @@ -1065,7 +1139,7 @@ forall t . function allocateDynamicArray(prx : Proxy(t), length : word) -> memor // write array length and return mstore(free, length); - let res : memory(DynArray(t)) = Typedef.abs(free); + let res : memory> = Typedef.abs(free); return res; } @@ -1074,18 +1148,18 @@ forall t . function allocateDynamicArray(prx : Proxy(t), length : word) -> memor // tightly packed byte arrays // bytes does not have a runtime representation since it can only ever exist in // memory / calldata / storage and serves only as a type tag for pointer types -// TODO: IndexAccess for memory(bytes) -// TODO: IndexAccess for calldata(bytes) -// TODO: IndexAccess for storage(bytes) -data bytes; +// TODO: IndexAccess for memory +// TODO: IndexAccess for calldata +// TODO: IndexAccess for storage +enum bytes {} // --- strings --- // TODO: should this be a typedef over `bytes`? -data string; +enum string {} -instance string:Add { - function add(l: string, r: string) -> string { +impl Add { + function add(l: string, r: string) returns (string) { return concatLit(l, r); } } @@ -1096,25 +1170,25 @@ instance string:Add { // These are intended to be folded by MastEval when their arguments are // statically known string literals. -function concatLit(comptime a: string, comptime b: string) -> string { +function concatLit(comptime a: string, comptime b: string) returns (string) { unimplemented(); // Sanity check if folding ignores it. return ""; } -function strlenLit(comptime a: string) -> word { +function strlenLit(comptime a: string) returns (word) { unimplemented(); // Sanity check if folding ignores it. return 0; } // Keccak-256 hash of the string-literal as UTF-8 bytes. -function keccakLit(comptime a: string) -> word { +function keccakLit(comptime a: string) returns (word) { unimplemented(); // Sanity check if folding ignores it. return 0; } // Keccak-256 hash of a word's 32-byte big-endian representation. // NOTE: this could be deprecated if we have comptime `to_bytes`. -function keccakWordLit(comptime a: word) -> word { +function keccakWordLit(comptime a: word) returns (word) { unimplemented(); // Sanity check if folding ignores it. return 0; } @@ -1123,43 +1197,49 @@ function keccakWordLit(comptime a: word) -> word { // A slice is a wrapper around an existing pointer type that extends the // underlying type with information about the size of the data pointed to by `t` -data slice(ptr) = slice(ptr, word); +enum slice { slice(ptr, word) } // --- Word Reader --- // A WordReader is an abstraction over byte indexed structure that can be read in word sized chunks (e.g. calldata / memory) // These let us use the same abi decoding routines for calldata / memory -forall ty . class ty:WordReader { +trait WordReader { // returns the word currently pointed to by the WordReader - function read(reader:ty) -> word; + function read(reader: ty) returns (word) ; // returns a new WordReader that points to a location `offset` bytes further into the array - function advance(reader:ty, offset:word) -> ty; + function advance(reader: ty, offset: word) returns (ty) ; // copies a block from the underlying source to memory - function copyToMem(reader:ty, dst: word, cnt: word) -> (); + function copyToMem(reader: ty, dst: word, cnt: word) ; } // WordReader for memory -data MemoryWordReader = MemoryWordReader(word); -instance MemoryWordReader:WordReader { - function read(reader:MemoryWordReader) -> word { - match reader { - | MemoryWordReader(ptr) => return mload(ptr); - } +enum MemoryWordReader { MemoryWordReader(word) } +impl WordReader { + function read(reader: MemoryWordReader) returns (word) { + match (reader) { +case MemoryWordReader(ptr) { +return mload(ptr); +} +} } - function advance(reader:MemoryWordReader, offset:word) -> MemoryWordReader { - match reader { - | MemoryWordReader(ptr) => return MemoryWordReader(ptr + offset); - } + function advance(reader: MemoryWordReader, offset: word) returns (MemoryWordReader) { + match (reader) { +case MemoryWordReader(ptr) { +return MemoryWordReader(ptr + offset); +} +} } - function copyToMem(reader:MemoryWordReader, dst:word, cnt: word) -> () { - match reader { - | MemoryWordReader(ptr) => mcopy(dst, ptr, cnt); - } + function copyToMem(reader: MemoryWordReader, dst: word, cnt: word) { + match (reader) { +case MemoryWordReader(ptr) { +mcopy(dst, ptr, cnt); +} +} } } // WordReader for calldata -data CalldataWordReader = CalldataWordReader(word); +enum CalldataWordReader { CalldataWordReader(word) } instance CalldataWordReader : Typedef(word) { function abs(a:word) -> CalldataWordReader { return CalldataWordReader(a); } From b944bd73a76f58039a1c2c3943f1cdad385dfff3 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 088/110] Switch the compiler and fixtures to canonical syntax: standard library Co-authored-by: Codex --- std/std.sol | 903 ++++++++++++++++++++++++++-------------------------- 1 file changed, 449 insertions(+), 454 deletions(-) diff --git a/std/std.sol b/std/std.sol index 697beb0f..30da458b 100644 --- a/std/std.sol +++ b/std/std.sol @@ -1241,218 +1241,233 @@ mcopy(dst, ptr, cnt); // WordReader for calldata enum CalldataWordReader { CalldataWordReader(word) } -instance CalldataWordReader : Typedef(word) { - function abs(a:word) -> CalldataWordReader { return CalldataWordReader(a); } - function rep(r:CalldataWordReader) -> word { - match r { - | CalldataWordReader(a) => return a; - } +impl Typedef { + function abs(a: word) returns (CalldataWordReader) { return CalldataWordReader(a); } + function rep(r: CalldataWordReader) returns (word) { + match (r) { +case CalldataWordReader(a) { +return a; +} +} } } -instance CalldataWordReader:WordReader { - function read(reader:CalldataWordReader) -> word { - match reader { - | CalldataWordReader(ptr) => return calldataload(ptr); - } +impl WordReader { + function read(reader: CalldataWordReader) returns (word) { + match (reader) { +case CalldataWordReader(ptr) { +return calldataload(ptr); +} +} } - function advance(reader:CalldataWordReader, offset:word) -> CalldataWordReader { - match reader { - | CalldataWordReader(ptr) => return CalldataWordReader(ptr + offset); - } + function advance(reader: CalldataWordReader, offset: word) returns (CalldataWordReader) { + match (reader) { +case CalldataWordReader(ptr) { +return CalldataWordReader(ptr + offset); +} +} } - function copyToMem(reader:CalldataWordReader, dst:word, cnt: word) -> () { - match reader { - | CalldataWordReader(ptr) => calldatacopy(dst, ptr, cnt); - } + function copyToMem(reader: CalldataWordReader, dst: word, cnt: word) { + match (reader) { +case CalldataWordReader(ptr) { +calldatacopy(dst, ptr, cnt); +} +} } } // --- HasWordReader --- -// The HasWordReader class defines the types for which a WordReader can be produced -// We define instances for memory(bytes) and calldata(bytes) -forall self reader . class self:HasWordReader(reader) { - function getWordReader(x:self) -> reader; +// The HasWordReader trait defines the types for which a WordReader can be produced. +// We define impls for memory and calldata. +trait HasWordReader { + function getWordReader(x: self) returns (reader) ; } -instance memory(bytes):HasWordReader(MemoryWordReader) { - function getWordReader(x:memory(bytes)) -> MemoryWordReader { +impl HasWordReader, MemoryWordReader> { + function getWordReader(x: memory) returns (MemoryWordReader) { return MemoryWordReader(Typedef.rep(x)); } } -instance calldata(bytes):HasWordReader(CalldataWordReader) { - function getWordReader(x:calldata(bytes)) -> CalldataWordReader { +impl HasWordReader, CalldataWordReader> { + function getWordReader(x: calldata) returns (CalldataWordReader) { return CalldataWordReader(Typedef.rep(x)); } } // --- MemoryType --- -// A MemoryType instance abstracts over type specific logic related to memory -// layout, allowing us to write code that is generic over which type is held in memory -forall self loadedType. class self:MemoryType(loadedType) { - // Proxy needed becaused class methods must mention strong type params - // loads an instance of `loadedType` from an instance of `self` located at `loc` in memory - function loadFromMemory(p:Proxy(self), loc:word) -> loadedType; +// A MemoryType impl abstracts over type-specific memory layout, allowing us to +// write code that is generic over the type held in memory. +trait MemoryType { + // Proxy is needed because trait methods must mention strong type parameters. + // Loads a `loadedType` value from a `self` value located at `loc` in memory. + function loadFromMemory(p: Proxy, loc: word) returns (loadedType) ; } // A uint256 can be loaded from memory and pushed straight onto the stack -instance uint256:MemoryType(uint256) { - function loadFromMemory(p:Proxy(uint256), loc:word) -> uint256 { +impl MemoryType { + function loadFromMemory(p: Proxy, loc: word) returns (uint256) { return uint256(mload(loc)); } } // We load a DynArray into a sized pointer to the first element /* -forall ty ret . ty:MemoryType(ret) => instance DynArray(ty):MemoryType(slice(memory(ret))) { - function loadFromMemory(p : Proxy (DynArray(ty)), loc:word) -> slice(memory(ret)) { +impl MemoryType, slice>> where ty: MemoryType { + function loadFromMemory(p: Proxy>, loc: word) returns (slice>) { let length = mload(loc); - return slice(Typedef.abs(loc) : memory(ret), length); + let ptr: memory = memory(Typedef.abs(loc)); + return slice(ptr, length); } } */ // FAIL: patterson // FAIL: bound variable -// if we ty is a MemoryType that returns deref and deref is ABIEncode, then we can encode a memory(ty) +// If `ty: MemoryType` and `deref: ABIEncode`, then memory can be +// encoded by loading and encoding its dereferenced value. // by loading it and then running the ABI encoding for the loaded value /* -forall ty deref . ty:MemoryType(deref), deref:ABIEncode => instance memory(ty):ABIEncode { - function encodeInto(x:memory(ty), basePtr:word, offset:word, tail:word) -> word { - let prx : Proxy(ty); // FIXED: before was Proxy(deref) - return ABIEncode.encodeInto(MemoryType.loadFromMemory(prx, Typedef.rep(x)) : deref, basePtr, offset, tail); +impl ABIEncode> where ty: MemoryType, deref: ABIEncode { + function encodeInto(x: memory, basePtr: word, offset: word, tail: word) returns (word) { + let prx: Proxy; // FIXED: before was Proxy + return ABIEncode.encodeInto(MemoryType.loadFromMemory(prx, Typedef.rep(x)): deref, basePtr, offset, tail); } } */ // --- ABI Tuples --- // Tuples in Solidity are always desugared to nested pairs (to allow for -// inductive typeclass instance constructions) . +// inductive trait-impl constructions). // This is an issue for the ABI routines since the ABI spec differentiates // between `(1,1,1)` and `(1,(1,1))`, but the language treats both identically. // The ABITuple type lets us reiintroduce this distinction: // `ABITuple((1,(1,1))` should be treated as `(1,1,1)` for the purposes of ABI // encoding / decoding. -data ABITuple(tuple) = ABITuple(tuple); +enum ABITuple { ABITuple(tuple) } -forall t . instance ABITuple(t):Typedef(t) { - function abs(t: t) -> ABITuple(t) { +impl Typedef, t> { + function abs(t: t) returns (ABITuple) { return ABITuple(t); } - function rep(x: ABITuple(t)) -> t { - match x { - | ABITuple(v) => return v; - } + function rep(x: ABITuple) returns (t) { + match (x) { +case ABITuple(v) { +return v; +} +} } } // --- ABI Metadata --- // Statically knowable ABI related metadata about `self` -forall self . class self:ABIAttribs { +trait ABIAttribs { // how many bytes should be used for the head portion of the abi encoding of `self` - function headSize(ty:Proxy(self)) -> word; + function headSize(ty: Proxy) returns (word) ; // whether or not `self` is a fully static type - function isStatic(ty:Proxy(self)) -> bool; + function isStatic(ty: Proxy) returns (bool) ; } -forall t. -default instance t:ABIAttribs { - function headSize(ty : Proxy(t)) -> word { return 32; } - function isStatic(ty : Proxy(t)) -> bool { return true; } +default impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return true; } } -instance ():ABIAttribs { - function headSize(ty : Proxy(())) -> word { return 0; } - function isStatic(ty : Proxy(())) -> bool { return true; } +impl ABIAttribs<()> { + function headSize(ty: Proxy<()>) returns (word) { return 0; } + function isStatic(ty: Proxy<()>) returns (bool) { return true; } } -instance uint256:ABIAttribs { - function headSize(ty : Proxy(uint256)) -> word { return 32; } - function isStatic(ty : Proxy(uint256)) -> bool { return true; } +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return true; } } -instance address:ABIAttribs { - function headSize(ty : Proxy(address)) -> word { return 32; } - function isStatic(ty : Proxy(address)) -> bool { return true; } +impl ABIAttribs
{ + function headSize(ty: Proxy
) returns (word) { return 32; } + function isStatic(ty: Proxy
) returns (bool) { return true; } } -forall t . instance DynArray(t):ABIAttribs { - function headSize(ty : Proxy(DynArray(t))) -> word { return 32; } - function isStatic(ty : Proxy(DynArray(t))) -> bool { return false; } +impl ABIAttribs> { + function headSize(ty: Proxy>) returns (word) { return 32; } + function isStatic(ty: Proxy>) returns (bool) { return false; } } // A dynamic array is encoded head-first as a 32-byte offset into the tail, so // its head is one word and it is never static (matching DynArray above). This -// covers `array(t)` under any location qualifier via the `calldata(ty)` / -// `memory(ty)` ABIAttribs bridges. -forall t . instance array(t):ABIAttribs { - function headSize(ty : Proxy(array(t))) -> word { return 32; } - function isStatic(ty : Proxy(array(t))) -> bool { return false; } -} -instance string:ABIAttribs { - function headSize(ty: Proxy(string)) -> word { return 32; } - function isStatic(ty : Proxy(string)) -> bool { return false; } -} -// bytes is dynamic, exactly like string — without this instance it falls to the -// default (isStatic = true), which wrongly marks memory(bytes) (and any ADT +// covers `array` under any location qualifier via the `calldata` / +// `memory` ABIAttribs bridges. +impl ABIAttribs> { + function headSize(ty: Proxy>) returns (word) { return 32; } + function isStatic(ty: Proxy>) returns (bool) { return false; } +} +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return false; } +} +// bytes is dynamic, exactly like string — without this impl it falls to the +// default (isStatic = true), which wrongly marks memory (and any ADT // carrying it) static, so calldata arrays/sums take the inline decode path over // what is really an offset-referenced value. -instance bytes:ABIAttribs { - function headSize(ty: Proxy(bytes)) -> word { return 32; } - function isStatic(ty : Proxy(bytes)) -> bool { return false; } +impl ABIAttribs { + function headSize(ty: Proxy) returns (word) { return 32; } + function isStatic(ty: Proxy) returns (bool) { return false; } } // computes the attribs for a pair of two types that implement attribs -forall a b . a:ABIAttribs, b:ABIAttribs => instance (a,b):ABIAttribs { - function headSize(ty : Proxy((a,b))) -> word { - let pa : Proxy(a); - let pb : Proxy(b); +impl ABIAttribs<(a, b)> where a: ABIAttribs, b: ABIAttribs { + function headSize(ty: Proxy<(a, b)>) returns (word) { + let pa : Proxy; + let pb : Proxy; let sza = ABIAttribs.headSize(pa); let szb = ABIAttribs.headSize(pb); return sza + szb; } - function isStatic(ty : Proxy((a,b))) -> bool { - let pa : Proxy(a); - let pb : Proxy(b); + function isStatic(ty: Proxy<(a, b)>) returns (bool) { + let pa : Proxy; + let pb : Proxy; return and(ABIAttribs.isStatic(pa), ABIAttribs.isStatic(pb)); } } // if an abi tuple contains dynamic elems we store it in the tail, otherwise we // treat it the same as a series of nested pairs -forall tuple . tuple:ABIAttribs => instance ABITuple(tuple):ABIAttribs { - function headSize(ty : Proxy(ABITuple(tuple))) -> word { - let px : Proxy(tuple); - match ABIAttribs.isStatic(px) { - | true => return ABIAttribs.headSize(px); - | false => return 32; - } +impl ABIAttribs> where tuple: ABIAttribs { + function headSize(ty: Proxy>) returns (word) { + let px : Proxy; + match (ABIAttribs.isStatic(px)) { +case true { +return ABIAttribs.headSize(px); +} +case false { +return 32; +} +} } - function isStatic(ty : Proxy(ABITuple(tuple))) -> bool { - let px : Proxy(tuple); + function isStatic(ty: Proxy>) returns (bool) { + let px : Proxy; return ABIAttribs.isStatic(px); } } // for pointer types we fetch the attribs of the pointed to type, not the pointer itself -forall ty . ty:ABIAttribs => instance memory(ty):ABIAttribs { - function headSize(p : Proxy(memory(ty))) -> word { - let px : Proxy(ty); +impl ABIAttribs> where ty: ABIAttribs { + function headSize(p: Proxy>) returns (word) { + let px : Proxy; return ABIAttribs.headSize(px); } - function isStatic(p : Proxy(memory(ty))) -> bool { - let px : Proxy(ty); + function isStatic(p: Proxy>) returns (bool) { + let px : Proxy; return ABIAttribs.isStatic(px); } } -forall ty . ty:ABIAttribs => instance calldata(ty):ABIAttribs { - function headSize(p : Proxy(calldata(ty))) -> word { - let px : Proxy(ty); +impl ABIAttribs> where ty: ABIAttribs { + function headSize(p: Proxy>) returns (word) { + let px : Proxy; return ABIAttribs.headSize(px); } - function isStatic(ty : Proxy(calldata(ty))) -> bool { - let px : Proxy(ty); + function isStatic(ty: Proxy>) returns (bool) { + let px : Proxy; return ABIAttribs.isStatic(px); } } @@ -1461,74 +1476,74 @@ forall ty . ty:ABIAttribs => instance calldata(ty):ABIAttribs { // TODO: make these generic over the location being written to (i.e. memory or returndata) // top level encoding function. -// abi encodes an instance of `ty` and returns a pointer to the result -forall ty . ty:ABIAttribs, ty:ABIEncode => function abi_encode(val : ty) -> memory(bytes) { +// ABI-encodes a `ty` value and returns a pointer to the result. +function abi_encode(val: ty) returns (memory) where ty: ABIAttribs, ty: ABIEncode { let ret = get_free_memory(); let start = ret + 32; - let tail = ABIEncode.encodeInto(val, start, 0, start + ABIAttribs.headSize(Proxy : Proxy(ty))); + let tail = ABIEncode.encodeInto(val, start, 0, start + ABIAttribs.headSize(@ty)); mstore(ret, tail - start); set_free_memory(tail); return memory(ret); } // types that can be abi encoded -forall self . class self:ABIEncode { - // abi encodes an instance of self into a memory region starting at basePtr +trait ABIEncode { + // ABI-encodes a `self` value into a memory region starting at basePtr. // offset gives the offset in memory from basePtr to the first empty byte of the head // tail gives the index in memory of the first empty byte of the tail - function encodeInto(x:self, basePtr:word, offset:word, tail:word) -> word /* newTail */; + function encodeInto(x: self, basePtr: word, offset: word, tail: word) returns (word) ; } -instance uint256:ABIEncode { +impl ABIEncode { // a unit256 is written directly into the head - function encodeInto(x:uint256, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: uint256, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance address:ABIEncode { +impl ABIEncode
{ // an address is written directly into the head (into a full 32-byte slot) - function encodeInto(x:address, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: address, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance bytes32:ABIEncode { +impl ABIEncode { // a bytes32 is written directly into the head - function encodeInto(x:bytes32, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: bytes32, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance bytes4:ABIEncode { +impl ABIEncode { // bytes4's word rep is right-aligned (e.g. `bytes4(shr(224, h))`), // so it is written directly into the head like bytes32 - function encodeInto(x:bytes4, basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: bytes4, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = Typedef.rep(x); mstore(basePtr + offset, repx); return tail; } } -instance bool:ABIEncode { - function encodeInto(x:bool, basePtr:word, offset:word, tail:word) -> word { +impl ABIEncode { + function encodeInto(x: bool, basePtr: word, offset: word, tail: word) returns (word) { let repx : word = frombool(x); mstore(basePtr + offset, repx); return tail; } } -function round_up_to_mul_of_32(value:word) -> word { +function round_up_to_mul_of_32(value: word) returns (word) { return (value + 31) & ~31; } -function encodeIntoFromBytesLike(srcPtr:word, basePtr:word, offset:word, tail:word) -> word { +function encodeIntoFromBytesLike(srcPtr: word, basePtr: word, offset: word, tail: word) returns (word) { let length = mload(srcPtr); let total = length + 32; mstore(basePtr + offset, tail - basePtr); @@ -1538,14 +1553,14 @@ function encodeIntoFromBytesLike(srcPtr:word, basePtr:word, offset:word, tail:wo return tail + rounded; } -instance memory(string):ABIEncode { - function encodeInto(x:memory(string), basePtr:word, offset:word, tail:word) -> word { +impl ABIEncode> { + function encodeInto(x: memory, basePtr: word, offset: word, tail: word) returns (word) { return encodeIntoFromBytesLike(Typedef.rep(x), basePtr, offset, tail); } } -instance memory(bytes):ABIEncode { - function encodeInto(x:memory(bytes), basePtr:word, offset:word, tail:word) -> word { +impl ABIEncode> { + function encodeInto(x: memory, basePtr: word, offset: word, tail: word) returns (word) { return encodeIntoFromBytesLike(Typedef.rep(x), basePtr, offset, tail); } } @@ -1553,11 +1568,10 @@ instance memory(bytes):ABIEncode { // ABI encoding for a memory dynamic array whose elements fit in a single word. // Assumes memory layout `[ length | elem_0 | elem_1 | ... ]`, which matches the // on-the-wire tail of `t[]` so the body can be `mcopy`d verbatim. -// `memory(DynArray(t)):ABIAttribs` is already derivable from the generic -// `memory(ty):ABIAttribs` + `DynArray(t):ABIAttribs` instances above. -forall t . t:Typedef(word) => -instance memory(DynArray(t)):ABIEncode { - function encodeInto(x:memory(DynArray(t)), basePtr:word, offset:word, tail:word) -> word { +// `memory>: ABIAttribs` is already derivable from the generic +// `memory: ABIAttribs` + `DynArray: ABIAttribs` impls above. +impl ABIEncode>> where t: Typedef { + function encodeInto(x: memory>, basePtr: word, offset: word, tail: word) returns (word) { let srcPtr : word = Typedef.rep(x); let len : word = mload(srcPtr); let totalBytes : word = (len + 1) * 32; @@ -1574,114 +1588,123 @@ instance memory(DynArray(t)):ABIEncode { } } -instance ():ABIEncode { +impl ABIEncode<()> { // a unit256 is written directly into the head - function encodeInto(x:(), basePtr:word, offset:word, tail:word) -> word { + function encodeInto(x: (), basePtr: word, offset: word, tail: word) returns (word) { return tail; } } // abi encoding for a pair of two encodable types -forall a b . a:ABIAttribs, a:ABIEncode, b:ABIEncode => instance (a,b):ABIEncode { - function encodeInto(x: (a,b), basePtr: word, offset: word, tail: word) -> word { - match x { - | (l,r) => - let newTail = ABIEncode.encodeInto(l, basePtr, offset, tail); - let pa : Proxy(a); +impl ABIEncode<(a, b)> where a: ABIAttribs, a: ABIEncode, b: ABIEncode { + function encodeInto(x: (a, b), basePtr: word, offset: word, tail: word) returns (word) { + match (x) { +case (l,r) { +let newTail = ABIEncode.encodeInto(l, basePtr, offset, tail); + let pa : Proxy; let a_sz = ABIAttribs.headSize(pa); return ABIEncode.encodeInto(r, basePtr, offset + a_sz, newTail); - } +} +} } } // abi encoding for an ABITuple of encodable types // TODO: is this correct? -forall tuple . tuple:ABIEncode, tuple:ABIAttribs => instance ABITuple(tuple):ABIEncode { - function encodeInto(x:ABITuple(tuple), basePtr:word, offset:word, tail:word) -> word { - let prx : Proxy(tuple); - match ABIAttribs.isStatic(prx) { - // if the tuple contains only static elements then we encode it in the head - | true => return ABIEncode.encodeInto(Typedef.rep(x), basePtr, offset, tail); +impl ABIEncode> where tuple: ABIEncode, tuple: ABIAttribs { + function encodeInto(x: ABITuple, basePtr: word, offset: word, tail: word) returns (word) { + let prx : Proxy; + match (ABIAttribs.isStatic(prx)) { +// if the tuple contains only static elements then we encode it in the head +case true { +return ABIEncode.encodeInto(Typedef.rep(x), basePtr, offset, tail); // if the tuple contains dynamically sized elements then we store a // pointer in the head, and encode the tuple into the tail - | false => - // store the length of the head in basePtr +} +case false { +// store the length of the head in basePtr mstore(basePtr, tail - basePtr); // encode the underlying tuple into the tail - let headSize = ABIAttribs.headSize(Proxy : Proxy(tuple)); + let headSize = ABIAttribs.headSize(@tuple); basePtr = tail; tail += headSize; return ABIEncode.encodeInto(Typedef.rep(x), basePtr, 0, tail); - } +} +} } } // --- ABI Decoding --- // Top level decoding function. -// abi decodes an instance of `decodable` into a `ty` -forall decodable reader ty decoded . decodable:HasWordReader(reader), ABIDecoder(ty, reader):ABIDecode(decoded) => -function abi_decode(decodable:decodable, pty:Proxy(ty), prdr:Proxy(reader)) -> decoded { - let decoder : ABIDecoder(ty, reader) = ABIDecoder(HasWordReader.getWordReader(decodable)); +// ABI-decodes a `decodable` value into a `ty` value. +function abi_decode(decodable: decodable, pty: Proxy, prdr: Proxy) returns (decoded) where decodable: HasWordReader, ABIDecoder: ABIDecode { + let decoder : ABIDecoder = ABIDecoder(HasWordReader.getWordReader(decodable)); return ABIDecode.decode(decoder, 0); } -forall decoder decoded . class decoder:ABIDecode(decoded) { - function decode(ptr:decoder, currentHeadOffset:word) -> decoded; +trait ABIDecode { + function decode(ptr: decoder, currentHeadOffset: word) returns (decoded) ; } // An ABI Decoder for `ty` from `reader` // This lets us abstract over memory and calldata when decoding -data ABIDecoder(ty, reader) = ABIDecoder(reader); +enum ABIDecoder { ABIDecoder(reader) } // If `reader` is a `WordReader` then so is our `ABIDecoder` -forall ty reader . reader:WordReader => instance ABIDecoder(ty, reader):WordReader { - function read(decoder:ABIDecoder(ty, reader)) -> word { - match decoder { - | ABIDecoder(ptr) => return WordReader.read(ptr); - } +impl WordReader> where reader: WordReader { + function read(decoder: ABIDecoder) returns (word) { + match (decoder) { +case ABIDecoder(ptr) { +return WordReader.read(ptr); +} +} } - function advance(decoder:ABIDecoder(ty, reader), offset:word) -> ABIDecoder(ty, reader) { - match decoder { - | ABIDecoder(ptr) => return ABIDecoder(WordReader.advance(ptr, offset)); - } + function advance(decoder: ABIDecoder, offset: word) returns (ABIDecoder) { + match (decoder) { +case ABIDecoder(ptr) { +return ABIDecoder(WordReader.advance(ptr, offset)); +} +} } - function copyToMem(decoder:ABIDecoder(ty, reader), dst:word, cnt: word) -> () { - match decoder { - | ABIDecoder(ptr) => WordReader.copyToMem(ptr, dst, cnt); - } + function copyToMem(decoder: ABIDecoder, dst: word, cnt: word) { + match (decoder) { +case ABIDecoder(ptr) { +WordReader.copyToMem(ptr, dst, cnt); +} +} } } // ABI Decoding for uint256 -forall reader . reader:WordReader => instance ABIDecoder(uint256, reader):ABIDecode(uint256) { - function decode(ptr:ABIDecoder(uint256, reader), currentHeadOffset:word) -> uint256 { - return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) : uint256; +impl ABIDecode, uint256> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (uint256) { + return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) ; } } // ABI Decoding for bytes32 -forall reader . reader:WordReader => instance ABIDecoder(bytes32, reader):ABIDecode(bytes32) { - function decode(ptr:ABIDecoder(bytes32, reader), currentHeadOffset:word) -> bytes32 { - return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) : bytes32; +impl ABIDecode, bytes32> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (bytes32) { + return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) ; } } // ABI Decoding for bytes4 -forall reader . reader:WordReader => instance ABIDecoder(bytes4, reader):ABIDecode(bytes4) { - function decode(ptr:ABIDecoder(bytes4, reader), currentHeadOffset:word) -> bytes4 { - return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) : bytes4; +impl ABIDecode, bytes4> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (bytes4) { + return Typedef.abs(WordReader.read(WordReader.advance(ptr, currentHeadOffset))) ; } } // ABI Decoding for bool // bool is a builtin (not a Typedef(word)), so it round-trips through word via -// tobool, mirroring the bool:ABIEncode instance which uses frombool. -forall reader . reader:WordReader => instance ABIDecoder(bool, reader):ABIDecode(bool) { - function decode(ptr:ABIDecoder(bool, reader), currentHeadOffset:word) -> bool { +// tobool, mirroring the `bool: ABIEncode` impl which uses frombool. +impl ABIDecode, bool> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (bool) { let v = WordReader.read(WordReader.advance(ptr, currentHeadOffset)); require(v <= 1, Error(0x0557dbbf)); // DirtyHigherBitsForBool() return tobool(v); @@ -1689,23 +1712,22 @@ forall reader . reader:WordReader => instance ABIDecoder(bool, reader):ABIDecode } // ABI Decoding for address -forall reader . reader:WordReader => instance ABIDecoder(address, reader):ABIDecode(address) { - function decode(ptr:ABIDecoder(address, reader), currentHeadOffset:word) -> address { +impl ABIDecode, address> where reader: WordReader { + function decode(ptr: ABIDecoder, currentHeadOffset: word) returns (address) { let raw = WordReader.read(WordReader.advance(ptr, currentHeadOffset)); require(shr(160, raw) == 0, Error(0x7cc04fa7)); // DirtyHigherBitsForAddress() - return Typedef.abs(raw) : address; + return Typedef.abs(raw) ; } } -forall reader . reader:WordReader => instance ABIDecoder((), reader):ABIDecode(()) { - function decode(ptr:ABIDecoder((), reader), currentHeadOffset:word) -> () { +impl ABIDecode, ()> where reader: WordReader { + function decode(ptr: ABIDecoder<(), reader>, currentHeadOffset: word) { return (); } } // ABI decoding for bytes/strings (only in memory) -forall a ptrtype reader. reader:WordReader => -function decodeBytesLike(ptr:ABIDecoder(memory(a), reader), currentHeadOffset:word) -> memory(a) { +function decodeBytesLike(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (memory) where reader: WordReader { let tmp:word; let headRdr = WordReader.advance(ptr, currentHeadOffset); let tailPtr : word = WordReader.read(headRdr); @@ -1721,82 +1743,78 @@ function decodeBytesLike(ptr:ABIDecoder(memory(a), reader), currentHeadOffset:wo } // ABI decoding for strings (only in memory) -forall reader. reader : WordReader => -instance ABIDecoder(memory(string), reader):ABIDecode(memory(string)) -{ - function decode(ptr:ABIDecoder(memory(string), reader), currentHeadOffset:word) -> memory(string) { +impl ABIDecode, reader>, memory> where reader: WordReader { + function decode(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (memory) { return decodeBytesLike(ptr, currentHeadOffset); } } // ABI decoding for bytes (only in memory) -forall reader. reader : WordReader => -instance ABIDecoder(memory(bytes), reader):ABIDecode(memory(bytes)) -{ - function decode(ptr:ABIDecoder(memory(bytes), reader), currentHeadOffset:word) -> memory(bytes) { +impl ABIDecode, reader>, memory> where reader: WordReader { + function decode(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (memory) { return decodeBytesLike(ptr, currentHeadOffset); } } // ABI decoding for a pair of decodable values // FAIL: Coverage -forall a b a_decoded b_decoded reader . reader:WordReader, ABIDecoder(b,reader):ABIDecode(b_decoded), ABIDecoder(a,reader):ABIDecode(a_decoded), a:ABIAttribs => instance ABIDecoder((a,b), reader):ABIDecode((a_decoded,b_decoded)) -{ - function decode(ptr:ABIDecoder((a,b), reader), currentHeadOffset:word) -> (a_decoded, b_decoded) { - match ptr { - | ABIDecoder(rdr) => - let prx : Proxy(a); - let decoder_a : ABIDecoder(a, reader) = ABIDecoder(rdr); - let decoder_b : ABIDecoder(b, reader) = ABIDecoder(rdr); +impl ABIDecode, (a_decoded, b_decoded)> where reader: WordReader, ABIDecoder: ABIDecode, ABIDecoder: ABIDecode, a: ABIAttribs { + function decode(ptr: ABIDecoder<(a, b), reader>, currentHeadOffset: word) returns (a_decoded, b_decoded) { + match (ptr) { +case ABIDecoder(rdr) { +let prx : Proxy; + let decoder_a : ABIDecoder = ABIDecoder(rdr); + let decoder_b : ABIDecoder = ABIDecoder(rdr); let a_val : a_decoded = ABIDecode.decode(decoder_a, currentHeadOffset); let b_val : b_decoded = ABIDecode.decode(decoder_b, currentHeadOffset + ABIAttribs.headSize(prx)); return (a_val, b_val); - } +} +} } } -forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_decoded), tuple:ABIAttribs => - instance ABIDecoder(ABITuple(tuple), reader):ABIDecode(tuple_decoded) -{ - function decode(ptr:ABIDecoder(ABITuple(tuple), reader), currentHeadOffset:word) -> tuple_decoded { - let prx : Proxy(tuple); - match ABIAttribs.isStatic(prx) { - | true => return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); - | false => - let tailPtr = WordReader.read(ptr); +impl ABIDecode, reader>, tuple_decoded> where reader: WordReader, tuple: ABIDecode, tuple: ABIAttribs { + function decode(ptr: ABIDecoder, reader>, currentHeadOffset: word) returns (tuple_decoded) { + let prx : Proxy; + match (ABIAttribs.isStatic(prx)) { +case true { +return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); +} +case false { +let tailPtr = WordReader.read(ptr); return ABIDecode.decode(WordReader.advance(ptr, tailPtr), 0); - } +} +} } } -forall reader tuple tuple_decoded . reader:WordReader, tuple:ABIDecode(tuple_decoded), tuple:ABIAttribs => - instance ABIDecoder(memory(ABITuple(tuple)), reader):ABIDecode(memory(tuple_decoded)) -{ - function decode(ptr:ABIDecoder(memory(ABITuple(tuple)), reader), currentHeadOffset:word) -> memory(tuple_decoded) { - let prx : Proxy(tuple); - match ABIAttribs.isStatic(prx) { - | true => return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); - | false => - let tailPtr = WordReader.read(ptr); +impl ABIDecode>, reader>, memory> where reader: WordReader, tuple: ABIDecode, tuple: ABIAttribs { + function decode(ptr: ABIDecoder>, reader>, currentHeadOffset: word) returns (memory) { + let prx : Proxy; + match (ABIAttribs.isStatic(prx)) { +case true { +return ABIDecode.decode(WordReader.advance(ptr, currentHeadOffset), 0); +} +case false { +let tailPtr = WordReader.read(ptr); return ABIDecode.decode(WordReader.advance(ptr, tailPtr), 0); - } +} +} } } -forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReader, ABIDecoder(baseType, reader):ABIDecode(baseType_decoded) => - instance ABIDecoder(memory(DynArray(baseType)), reader):ABIDecode(memory(DynArray(baseType_decoded))) -{ - function decode(ptr:ABIDecoder(memory(DynArray(baseType)), reader), currentHeadOffset:word) -> memory(DynArray(baseType_decoded)) { +impl ABIDecode>, reader>, memory>> where baseType: ABIAttribs, reader: WordReader, ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder>, reader>, currentHeadOffset: word) returns (memory>) { let arrayPtr = WordReader.advance(ptr, currentHeadOffset); let length = WordReader.read(arrayPtr); // this trigger a missing typedef constraint // let elementPtr:ABIDecoder(baseType, reader) = Typedef.abs(WordReader.advance(arrayPtr, 32)); arrayPtr = WordReader.advance(arrayPtr, 32); - let prx : Proxy(baseType_decoded); - let result : memory(DynArray(baseType_decoded)) = allocateDynamicArray(prx, length); + let prx : Proxy; + let result : memory> = allocateDynamicArray(prx, length); let offset : word = 0; - let prx : Proxy(baseType); + let prx : Proxy; let elementHeadSize : word = ABIAttribs.headSize(prx); // TODO: surface level loops @@ -1810,18 +1828,16 @@ forall reader baseType baseType_decoded .baseType : ABIAttribs, reader:WordReade } } -forall ty reader. -function getReader(d:ABIDecoder(ty, reader)) -> reader { - match d { - | ABIDecoder(rdr) => return rdr; - } +function getReader(d: ABIDecoder) returns (reader) { + match (d) { +case ABIDecoder(rdr) { +return rdr; +} +} } -forall baseType baseType_decoded . ABIDecoder(baseType, CalldataWordReader):ABIDecode(baseType_decoded), - baseType : WordReader => - instance ABIDecoder(calldata(DynArray(baseType)), CalldataWordReader):ABIDecode(calldata(DynArray(baseType_decoded))) - { - function decode(ptr:ABIDecoder(calldata(DynArray(baseType)), CalldataWordReader), currentHeadOffset:word) -> calldata(DynArray(baseType_decoded)) { +impl ABIDecode>, CalldataWordReader>, calldata>> where ABIDecoder: ABIDecode, baseType: WordReader { + function decode(ptr: ABIDecoder>, CalldataWordReader>, currentHeadOffset: word) returns (calldata>) { let newptr = WordReader.advance(ptr, currentHeadOffset); let reader: CalldataWordReader = getReader(newptr); let addr: word = Typedef.rep(reader); @@ -1835,12 +1851,9 @@ forall baseType baseType_decoded . ABIDecoder(baseType, CalldataWordReader):ABID // to that length word, so the elements are left in calldata and decoded on // demand (abiArrayLength / abiArrayGet). Because nothing is materialised here, // this works for any decodable element type — including multi-word ADTs such as -// a sum(...) — which the word-per-slot memory(DynArray(...)) path cannot hold. -forall baseType baseType_decoded . - ABIDecoder(baseType, CalldataWordReader):ABIDecode(baseType_decoded) => - instance ABIDecoder(calldata(array(baseType)), CalldataWordReader):ABIDecode(calldata(array(baseType_decoded))) - { - function decode(ptr:ABIDecoder(calldata(array(baseType)), CalldataWordReader), currentHeadOffset:word) -> calldata(array(baseType_decoded)) { +// a `sum<...>` — which the word-per-slot `memory>` path cannot hold. +impl ABIDecode>, CalldataWordReader>, calldata>> where ABIDecoder: ABIDecode { + function decode(ptr: ABIDecoder>, CalldataWordReader>, currentHeadOffset: word) returns (calldata>) { let headRdr = WordReader.advance(ptr, currentHeadOffset); let dataOffset : word = WordReader.read(headRdr); let dataRdr = WordReader.advance(ptr, dataOffset); @@ -1851,7 +1864,7 @@ forall baseType baseType_decoded . } // Length of a decoded calldata array: the handle points at the length word. -forall t . function abiArrayLength(a : calldata(array(t))) -> uint256 { +function abiArrayLength(a: calldata>) returns (uint256) { let rdr : CalldataWordReader = CalldataWordReader(Typedef.rep(a)); return uint256(WordReader.read(rdr)); } @@ -1871,32 +1884,31 @@ forall t . function abiArrayLength(a : calldata(array(t))) -> uint256 { // head offset; the element's own dynamic decoder follows that offset. This // is uniform across element kinds: a dynamic sum follows it and rebases to // the element start, a bare bytes/string leaf follows it to its length word. -forall t t_decoded . - t : ABIAttribs, - ABIDecoder(t, CalldataWordReader):ABIDecode(t_decoded) => -function abiArrayGet(a : calldata(array(t)), i : uint256) -> t_decoded { +function abiArrayGet(a: calldata>, i: uint256) returns (t_decoded) where t: ABIAttribs, ABIDecoder: ABIDecode { // Bounds check: valid indices are [0, length); i == length is already past // the last element, so reject i >= length (mirrors the storage-array guard). require(i < abiArrayLength(a), Error(0x7f52b2bf)); // ArrayOutOfBounds() let base : word = Typedef.rep(a); let elemRegion : word = base + 32; - let prx : Proxy(t); + let prx : Proxy; let idx : word = Typedef.rep(i); - match ABIAttribs.isStatic(prx) { - | true => - let elemRdr : CalldataWordReader = CalldataWordReader(elemRegion); - let dec : ABIDecoder(t, CalldataWordReader) = ABIDecoder(elemRdr); + match (ABIAttribs.isStatic(prx)) { +case true { +let elemRdr : CalldataWordReader = CalldataWordReader(elemRegion); + let dec : ABIDecoder = ABIDecoder(elemRdr); return ABIDecode.decode(dec, idx * ABIAttribs.headSize(prx)); - | false => - // Dynamic elements: the region is a table of 32-byte offsets (relative +} +case false { +// Dynamic elements: the region is a table of 32-byte offsets (relative // to the region base), one per element. Hand the element decoder the // region base and element i's slot as its head offset; the element's own // (dynamic) decoder follows that offset — uniformly for a dynamic sum - // element or a bare bytes/string element (calldata(array(bytes))). + // element or a bare bytes/string element (`calldata>`). let elemRdr : CalldataWordReader = CalldataWordReader(elemRegion); - let dec : ABIDecoder(t, CalldataWordReader) = ABIDecoder(elemRdr); + let dec : ABIDecoder = ABIDecoder(elemRdr); return ABIDecode.decode(dec, idx * 32); - } +} +} } @@ -1919,149 +1931,145 @@ pragma no-bounded-variable-condition LVA, RVA; // Zeroes the storage slots in [start, endSlot). Mirrors solc's // clear_storage_range, used when a dynamic array shrinks so that regrowing it // cannot resurrect the old elements. -function clearStorageRange(start: word, endSlot: word) -> () { +function clearStorageRange(start: word, endSlot: word) { for (; start < endSlot; start += 1) { sstore(start, 0); } } -forall self. -class self:StorageSize { - function size(x:Proxy(self)) -> word; +trait StorageSize { + function size(x: Proxy) returns (word) ; } -forall self. -default instance self:StorageSize { - function size(x:Proxy(self)) -> word { +default impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance ():StorageSize { - function size(x:Proxy(())) -> word { +impl StorageSize<()> { + function size(x: Proxy<()>) returns (word) { return 0; } } -instance word:StorageSize { - function size(x:Proxy(word)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } /* -instance uint:StorageSize { - function size(x:Proxy(uint)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } */ -instance uint256:StorageSize { - function size(x:Proxy(uint256)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance bytes32:StorageSize { - function size(x:Proxy(bytes32)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance address:StorageSize { - function size(x:Proxy(address)) -> word { +impl StorageSize
{ + function size(x: Proxy
) returns (word) { return 1; } } -instance string:StorageSize { - function size(x:Proxy(string)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance memory(string):StorageSize { - function size(x:Proxy(memory(string))) -> word { +impl StorageSize> { + function size(x: Proxy>) returns (word) { return 1; } } -instance bytes:StorageSize { - function size(x:Proxy(bytes)) -> word { +impl StorageSize { + function size(x: Proxy) returns (word) { return 1; } } -instance memory(bytes):StorageSize { - function size(x:Proxy(memory(bytes))) -> word { +impl StorageSize> { + function size(x: Proxy>) returns (word) { return 1; } } -forall a b. a:StorageSize, b:StorageSize => instance (a,b):StorageSize { - function size(x:Proxy((a,b))) -> word { - let a_sz:word = StorageSize.size(Proxy:Proxy(a)); - let b_sz:word = StorageSize.size(Proxy:Proxy(b)); +impl StorageSize<(a, b)> where a: StorageSize, b: StorageSize { + function size(x: Proxy<(a, b)>) returns (word) { + let a_sz:word = StorageSize.size(@a); + let b_sz:word = StorageSize.size(@b); return a_sz + b_sz; } } -forall self. -class self:StorageType { - function load(ptr:word) -> self; - function store(ptr:word, value:self) -> (); +trait StorageType { + function load(ptr: word) returns (self) ; + function store(ptr: word, value: self) ; } // How to copy one element of type self from one storage slot to another. -// Whole-array assignment (a = b) copies element by element through this class, +// Whole-array assignment (a = b) copies element by element through this trait, // the way solc's copy_array_to_storage calls the element's own copy routine. // The constraint lives on the *element* type, so it can gate CanStore.store for -// storage(array(self)) without also gating CanStore.load, which must stay +// storage> without also gating CanStore.load, which must stay // unconstrained, a field read has to yield the array's storage reference. -// Instances live below, next to the CanStore instances the dynamic ones rely on. -forall self. -class self:StorageCopy { - function copySlot(dst:storage(self), src:storage(self)) -> (); +// Impls live below, next to the CanStore impls the dynamic ones rely on. +trait StorageCopy { + function copySlot(dst: storage, src: storage) ; } -instance word:StorageType { - function load(ptr:word) -> word { +impl StorageType { + function load(ptr: word) returns (word) { return sload(ptr); } - function store(ptr:word, value:word) -> () { + function store(ptr: word, value: word) { sstore(ptr, value); } } -instance uint256:StorageType { - function load(ptr:word) -> uint256 { return uint256(StorageType.load(ptr):word); } - function store(ptr:word, value:uint256) -> () { StorageType.store(ptr, Typedef.rep(value):word); } +impl StorageType { + function load(ptr: word) returns (uint256) { return uint256(StorageType.load(ptr)); } + function store(ptr: word, value: uint256) { StorageType.store(ptr, Typedef.rep(value)); } } -instance bytes32:StorageType { - function load(ptr:word) -> bytes32 { return bytes32(StorageType.load(ptr):word); } - function store(ptr:word, value:bytes32) -> () { StorageType.store(ptr, Typedef.rep(value):word); } +impl StorageType { + function load(ptr: word) returns (bytes32) { return bytes32(StorageType.load(ptr)); } + function store(ptr: word, value: bytes32) { StorageType.store(ptr, Typedef.rep(value)); } } -instance address:StorageType { - function load(ptr:word) -> address { return address(StorageType.load(ptr):word); } - function store(ptr:word, value:address) -> () { StorageType.store(ptr, Typedef.rep(value):word); } +impl StorageType
{ + function load(ptr: word) returns (address) { return address(StorageType.load(ptr)); } + function store(ptr: word, value: address) { StorageType.store(ptr, Typedef.rep(value)); } } // -- structure fields (including contract fields) -forall self fieldType offsetType. -class self:CStructField(fieldType, offsetType) {} -data StructField(structType, fieldSelector) = StructField(structType); +trait CStructField {} +enum StructField { StructField(structType) } -data MemberAccessProxy(a, field, fieldtype, offset) = MemberAccessProxy(a, field); +enum MemberAccessProxy { MemberAccessProxy(a, field) } -forall a field fieldType storageType offset . -function memberAccessBase(x:MemberAccessProxy(a, field, fieldType, offset)) -> a { - match x { - | MemberAccessProxy(y,z) => return y; - } +function memberAccessBase(x: MemberAccessProxy) returns (a) { + match (x) { +case MemberAccessProxy(y,z) { +return y; +} +} } @@ -2069,141 +2077,135 @@ function memberAccessBase(x:MemberAccessProxy(a, field, fieldType, offset)) -> // Contract field access // ------------------------------------------------------------------ -forall cxt fieldSelector loadType offsetType storageType -. StructField(ContractStorage(cxt), fieldSelector) :CStructField(storage(storageType), offsetType) -, offsetType : StorageSize -, storage(storageType): CanStore(loadType) -=> instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType) : LVA (storage(storageType)) { - function acc (x : MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType)) -> storage(storageType) { - let offset : word = StorageSize.size(Proxy : Proxy(offsetType)) ; - return storage(offset):storage(storageType); +impl LVA, fieldSelector, loadType, offsetType>, storage> where StructField, fieldSelector>: CStructField, offsetType>, offsetType: StorageSize, storage: CanStore { + function acc(x: MemberAccessProxy, fieldSelector, loadType, offsetType>) returns (storage) { + let offset : word = StorageSize.size(@offsetType) ; + let result : storage = storage(offset); + return result; } } -forall cxt fieldSelector loadType offsetType storageType - . StructField(ContractStorage(cxt), fieldSelector):CStructField(storage(storageType), offsetType) - , storage(storageType):CanStore(loadType) - , offsetType:StorageSize - => instance MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType):RVA(loadType) { - function acc(x:MemberAccessProxy(ContractStorage(cxt), fieldSelector, loadType, offsetType)) -> loadType { - let offset:word = StorageSize.size(Proxy:Proxy(offsetType)); - return CanStore.load(storage(offset):storage(storageType)):loadType; +impl RVA, fieldSelector, loadType, offsetType>, loadType> where StructField, fieldSelector>: CStructField, offsetType>, storage: CanStore, offsetType: StorageSize { + function acc(x: MemberAccessProxy, fieldSelector, loadType, offsetType>) returns (loadType) { + let offset:word = StorageSize.size(@offsetType); + let slot : storage = storage(offset); + return CanStore.load(slot); } } // TODO: structures other than contract context /* -forall structType fieldSelector fieldType storageType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - => instance MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType):LVA(storage(fieldType)) { - function acc(x:MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType)) -> storage(fieldType) { +impl + LVA, fieldSelector, fieldType, offsetType>, storage> + where StructField: CStructField, + offsetType: StorageSize { + function acc(x: MemberAccessProxy, fieldSelector, fieldType, offsetType>) returns (storage) { let ptr:word = Typedef.rep(memberAccessBase(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); + let size:word = StorageSize.size(@offsetType); return storage(ptr + size); } } -forall structType fieldSelector fieldType storageType offsetType - . StructField(structType, fieldSelector):CStructField(fieldType, offsetType) - , offsetType:StorageSize - , fieldType:StorageType - => instance MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType):RVA(fieldType) { - function acc(x:MemberAccessProxy(storage(structType), fieldSelector, fieldType, offsetType)) -> fieldType { +impl + RVA, fieldSelector, fieldType, offsetType>, fieldType> + where StructField: CStructField, + offsetType: StorageSize, + fieldType: StorageType { + function acc(x: MemberAccessProxy, fieldSelector, fieldType, offsetType>) returns (fieldType) { let ptr:word = Typedef.rep(memberAccessBase(x)); - let size:word = StorageSize.size(Proxy:Proxy(offsetType)); - return CanStore.load(ptr + size); + let size:word = StorageSize.size(@offsetType); + let field: storage = storage(ptr + size); + return CanStore.load(field); } } */ -data ContractStorage(cxt) = ContractStorage(cxt); +enum ContractStorage { ContractStorage(cxt) } -forall member index . instance mapping(index, member):Typedef(word) { - function rep(x:mapping(index, member)) -> word { - match x { - | mapping(y) => return y; - } +impl Typedef member), word> { + function rep(x: mapping(index => member)) returns (word) { + match (x) { +case mapping(y) { +return y; +} +} } - function abs(x:word) -> mapping(index,member) { + function abs(x: word) returns (mapping(index => member)) { return mapping(x); } } // cf https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays -forall index member . -instance mapping(index, member):StorageSize { - function size(x:Proxy(mapping(index, member))) -> word { +impl StorageSize member)> { + function size(x: Proxy member)>) returns (word) { return 1; } } -forall member . instance array(member):Typedef(word) { - function rep(x:array(member)) -> word { - match x { - | array(y) => return y; - } +impl Typedef, word> { + function rep(x: array) returns (word) { + match (x) { +case array(y) { +return y; +} +} } - function abs(x:word) -> array(member) { + function abs(x: word) returns (array) { return array(x); } } // cf https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html#mappings-and-dynamic-arrays // the slot itself stores the array length; elements live at keccak256(slot) + i -forall member . -instance array(member):StorageSize { - function size(x:Proxy(array(member))) -> word { +impl StorageSize> { + function size(x: Proxy>) returns (word) { return 1; } } -forall self . class self:Length { - function length(arr:self) -> uint256; +trait Length { + function length(arr: self) returns (uint256) ; } // Dynamic storage arrays carry their length at the slot itself (matching the // Solidity convention) while elements live at keccak256(slot) + i. -forall self . class self:Array { - function setLength(arr:self, n:uint256) -> (); - function pop(arr:self) -> (); +trait Array { + function setLength(arr: self, n: uint256) ; + function pop(arr: self) ; } // push is split into its own MPTC so its element type only shows up where it // actually matters (the value being appended), without forcing `length`/ // `setLength`/`pop` to drag along an unconstrained `elem` parameter. -forall self elem . class self:ArrayPush(elem) { - function push(arr:self, val:elem) -> (); +trait ArrayPush { + function push(arr: self, val: elem) ; } -forall t . -instance storage(array(t)):Length { - function length(arr:storage(array(t))) -> uint256 { +impl Length>> { + function length(arr: storage>) returns (uint256) { return uint256(sload(Typedef.rep(arr))); } } // A lazily-decoded calldata array reports its length from the head length-word // of its handle (see abiArrayLength), so `arr.length()` resolves through the -// same Length class / UFCS as storage arrays. -forall t . -instance calldata(array(t)):Length { - function length(arr:calldata(array(t))) -> uint256 { +// same Length trait / UFCS as storage arrays. +impl Length>> { + function length(arr: calldata>) returns (uint256) { return abiArrayLength(arr); } } -forall t . -instance storage(array(t)):Array { +impl Array>> { // Shrinking clears the abandoned slots, matching solc's resize_array. // For string/bytes elements this zeroes the inline slot, which makes any // keccak-derived tail unreachable (reads are governed by the length word) but // does not reclaim it. - function setLength(arr:storage(array(t)), n:uint256) -> () { + function setLength(arr: storage>, n: uint256) { let slot : word = Typedef.rep(arr); let oldLen : word = sload(slot); let newLen : word = Typedef.rep(n); @@ -2214,7 +2216,7 @@ instance storage(array(t)):Array { sstore(slot, newLen); } // Zeroes the removed element before decrementing, as solc's array_pop does. - function pop(arr:storage(array(t))) -> () { + function pop(arr: storage>) { let slot : word = Typedef.rep(arr); let n : word = sload(slot); if (n == 0) { out_of_bounds(); } @@ -2224,138 +2226,129 @@ instance storage(array(t)):Array { } // The value pushed is whatever the element's storage reference can store, rather -// than the element tag type itself. That is what lets array(string) accept a -// memory(string), via storage(string):CanStore(memory(string)). For word-sized +// than the element tag type itself. That is what lets array accept a +// memory, via `storage: CanStore>`. For word-sized // elements v collapses to the element type and CanStore.store delegates to // StorageType.store, so the generated code is unchanged. -forall t v . storage(t):CanStore(v) => -instance storage(array(t)):ArrayPush(v) { - function push(arr:storage(array(t)), val:v) -> () { +impl ArrayPush>, v> where storage: CanStore { + function push(arr: storage>, val: v) { let slot : word = Typedef.rep(arr); let n : word = sload(slot); - CanStore.store(storage(hash1(slot) + n):storage(t), val); + let element : storage = storage(hash1(slot) + n); + CanStore.store(element, val); sstore(slot, n + 1); } } -forall self memberRefType. -class self:LVA(memberRefType) { - function acc(x:self) -> memberRefType; +trait LVA { + function acc(x: self) returns (memberRefType) ; } -forall self member. -class self:RVA(member) { - function acc(x:self) -> member; +trait RVA { + function acc(x: self) returns (member) ; } -forall a b. a:RVA(b) => -function rval(x:a) -> b { +function rval(x: a) returns (b) where a: RVA { return RVA.acc(x); } // TODO: consider merging CanStore and Assign -forall lhs rhs. -class lhs:Assign(rhs) { - function assign(l:lhs, r:rhs) -> (); +trait Assign { + function assign(l: lhs, r: rhs) ; } -// a can store b; e.g. storage(string) : memory(string) -forall a b. -class a:CanStore(b) { - function store(r:a, v:b) -> (); - function load(r:a) -> b; +// `a` can store `b`; e.g. `storage: CanStore>`. +trait CanStore { + function store(r: a, v: b) ; + function load(r: a) returns (b) ; } -forall a b. a:CanStore(b) => -instance a:Assign(b) { - function assign(l:a, r:b) -> () { +impl Assign where a: CanStore { + function assign(l: a, r: b) { CanStore.store(l, r); } } /* -forall a. a:StorageType => -default instance a:CanStore(a) { - function store(l:storage(a), r:a) -> () { +default impl CanStore, a> where a: StorageType { + function store(l: storage, r: a) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(a)) -> a { + function load(l: storage) returns (a) { return StorageType.load(Typedef.rep(l)); } } */ - instance storage(word):CanStore(word) { - function store(l:storage(word), r:word) -> () { + impl CanStore, word> { + function store(l: storage, r: word) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(word)) -> word { + function load(l: storage) returns (word) { return StorageType.load(Typedef.rep(l)); } } - instance storage(uint256):CanStore(uint256) { - function store(l:storage(uint256), r:uint256) -> () { + impl CanStore, uint256> { + function store(l: storage, r: uint256) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(uint256)) -> uint256 { + function load(l: storage) returns (uint256) { return StorageType.load(Typedef.rep(l)); } } - instance storage(bytes32):CanStore(bytes32) { - function store(l:storage(bytes32), r:bytes32) -> () { + impl CanStore, bytes32> { + function store(l: storage, r: bytes32) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(bytes32)) -> bytes32 { + function load(l: storage) returns (bytes32) { return StorageType.load(Typedef.rep(l)); } } - instance storage(address):CanStore(address) { - function store(l:storage(address), r:address) -> () { + impl CanStore, address> { + function store(l: storage
, r: address) { StorageType.store(Typedef.rep(l), r); } - function load(l:storage(address)) -> address { + function load(l: storage
) returns (address) { return StorageType.load(Typedef.rep(l)); } } -// bool has no StorageType instance (it is a builtin, not a Typedef(word)), but it +// bool has no StorageType impl (it is a builtin, not a Typedef), but it // round-trips through word via frombool / tobool, so it can still be stored. -instance storage(bool):CanStore(bool) { - function store(l:storage(bool), r:bool) -> () { +impl CanStore, bool> { + function store(l: storage, r: bool) { StorageType.store(Typedef.rep(l), frombool(r)); } - function load(l:storage(bool)) -> bool { + function load(l: storage) returns (bool) { return tobool(StorageType.load(Typedef.rep(l))); } } -forall k v. - instance storage(mapping(k,v)):CanStore(storage(mapping(k,v))) { - function store(l:storage(mapping(k,v)), r:storage(mapping(k,v))) -> () { +impl CanStore v)>, storage v)>> { + function store(l: storage v)>, r: storage v)>) { // StorageType.store(Typedef.rep(l), r); unimplemented(); } - function load(l:storage(mapping(k,v))) -> storage(mapping(k,v)) { + function load(l: storage v)>) returns (storage v)>) { // "Loading" a storage mapping field yields its storage reference (the // slot); indexed access / method calls consume that reference directly. return l; } } -forall v. v:StorageCopy => - instance storage(array(v)):CanStore(storage(array(v))) { +impl CanStore>, storage>> where v: StorageCopy { // Whole-array assignment is a deep copy, as in Solidity: a = b resizes a // to b's length and then copies every // element. Assigning an array to itself is a no-op. A *local* bound to an // array field stays an alias, because a let is not an Assign.assign. - function store(l:storage(array(v)), r:storage(array(v))) -> () { + function store(l: storage>, r: storage>) { let dst : word = Typedef.rep(l); let src : word = Typedef.rep(r); if (dst != src) { @@ -2368,11 +2361,13 @@ forall v. v:StorageCopy => sstore(dst, newLen); let srcBase : word = hash1(src); for (let i = 0; i < newLen; i += 1) { - StorageCopy.copySlot(storage(dstBase + i):storage(v), storage(srcBase + i):storage(v)); + let dstSlot : storage = storage(dstBase + i); + let srcSlot : storage = storage(srcBase + i); + StorageCopy.copySlot(dstSlot, srcSlot); } } } - function load(l:storage(array(v))) -> storage(array(v)) { + function load(l: storage>) returns (storage>) { // "Loading" a storage array field yields its storage reference (the // slot). push / pop / length / arr[i] all consume that reference, so a // field read like `ArrayPush.push(members, x)` must return the slot, From ff4362d8def96859d6410f0aafaab346d63c57e9 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 089/110] Switch the compiler and fixtures to canonical syntax: standard library Co-authored-by: Codex --- std/std.sol | 298 ++++++++++++++++++++++++++-------------------------- 1 file changed, 151 insertions(+), 147 deletions(-) diff --git a/std/std.sol b/std/std.sol index 30da458b..dc16c75e 100644 --- a/std/std.sol +++ b/std/std.sol @@ -2379,34 +2379,34 @@ impl CanStore>, storage>> where v: StorageCopy { // Assigning an array literal to a storage array field: `xs = [1,2,3]`. // // This is Solidity's memory -> storage array copy. It is a plain function, not -// a CanStore instance, on purpose: instance overlap is decided by the main type -// alone, so a second CanStore instance for storage(array(t)) would clash with +// a CanStore impl, on purpose: impl overlap is decided by the main type alone, +// so a second CanStore impl for storage> would clash with // the deep-copy one above. FieldAccess routes `field = ` here // instead of through Assign.assign. // // Array.setLength resizes and clears the abandoned tail, so old elements never // resurrect. The element types differ: `t` is the storage element tag and `v` // what a value of it looks like in memory (they coincide for word-sized -// elements; for array(string), t = string and v = memory(string)). -forall t v . storage(t):CanStore(v), v:Typedef(word) => -function storeArrayLit(dst : storage(array(t)), src : memory(DynArray(v))) -> () { +// elements; for array, t = string and v = memory). +function storeArrayLit(dst: storage>, src: memory>) where storage: CanStore, v: Typedef { let n : word = mload(Typedef.rep(src)); Array.setLength(dst, uint256(n)); let base : word = hash1(Typedef.rep(dst)); let i : word = 0; for (; i < n; i += 1) { - CanStore.store(storage(base + i) : storage(t), IndexAccess.get(src, uint256(i))); + let element : storage = storage(base + i); + CanStore.store(element, IndexAccess.get(src, uint256(i))); } } -instance storage(string):CanStore(memory(string)) { - function store(dst:storage(string), src:memory(string)) -> () { +impl CanStore, memory> { + function store(dst: storage, src: memory) { let srcPtr : word = Typedef.rep(src); let slot = Typedef.rep(dst); storeBytesFromMemory(slot, srcPtr); } - function load(src:storage(string)) -> memory(string) { + function load(src: storage) returns (memory) { let srcPtr : word = Typedef.rep(src); let dstPtr : word = get_free_memory(); let endPtr = loadBytesFromStorage(srcPtr, dstPtr); @@ -2417,14 +2417,14 @@ instance storage(string):CanStore(memory(string)) { // bytes share the same storage layout as string, so the same // storeBytesFromMemory / loadBytesFromStorage helpers apply. -instance storage(bytes):CanStore(memory(bytes)) { - function store(dst:storage(bytes), src:memory(bytes)) -> () { +impl CanStore, memory> { + function store(dst: storage, src: memory) { let srcPtr : word = Typedef.rep(src); let slot = Typedef.rep(dst); storeBytesFromMemory(slot, srcPtr); } - function load(src:storage(bytes)) -> memory(bytes) { + function load(src: storage) returns (memory) { let srcPtr : word = Typedef.rep(src); let dstPtr : word = get_free_memory(); let endPtr = loadBytesFromStorage(srcPtr, dstPtr); @@ -2436,23 +2436,23 @@ instance storage(bytes):CanStore(memory(bytes)) { // --- StorageCopy: per-element copy used by whole-array assignment --- // Word-sized elements are self-contained: the slot is the value. -instance word:StorageCopy { - function copySlot(dst:storage(word), src:storage(word)) -> () { +impl StorageCopy { + function copySlot(dst: storage, src: storage) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } -instance uint256:StorageCopy { - function copySlot(dst:storage(uint256), src:storage(uint256)) -> () { +impl StorageCopy { + function copySlot(dst: storage, src: storage) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } -instance bytes32:StorageCopy { - function copySlot(dst:storage(bytes32), src:storage(bytes32)) -> () { +impl StorageCopy { + function copySlot(dst: storage, src: storage) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } -instance address:StorageCopy { - function copySlot(dst:storage(address), src:storage(address)) -> () { +impl StorageCopy
{ + function copySlot(dst: storage
, src: storage
) { sstore(Typedef.rep(dst), sload(Typedef.rep(src))); } } @@ -2460,29 +2460,30 @@ instance address:StorageCopy { // Dynamic elements keep their payload at keccak256(elementSlot), so copying the // inline slot alone would leave the destination pointing at the *source's* tail. // Round-tripping through memory copies the payload too. -instance string:StorageCopy { - function copySlot(dst:storage(string), src:storage(string)) -> () { - CanStore.store(dst, CanStore.load(src):memory(string)); +impl StorageCopy { + function copySlot(dst: storage, src: storage) { + let value : memory = CanStore.load(src); + CanStore.store(dst, value); } } -instance bytes:StorageCopy { - function copySlot(dst:storage(bytes), src:storage(bytes)) -> () { - CanStore.store(dst, CanStore.load(src):memory(bytes)); +impl StorageCopy { + function copySlot(dst: storage, src: storage) { + let value : memory = CanStore.load(src); + CanStore.store(dst, value); } } -// Nested arrays recurse into the array CanStore instance above. The recursion is +// Nested arrays recurse into the array CanStore impl above. The recursion is // on the element type, so it terminates with the type's structure. -forall t . t:StorageCopy => -instance array(t):StorageCopy { - function copySlot(dst:storage(array(t)), src:storage(array(t))) -> () { +impl StorageCopy> where t: StorageCopy { + function copySlot(dst: storage>, src: storage>) { CanStore.store(dst, src); } } // Shamelessly stolen from function copy_byte_array_to_storage_from_t_bytes_memory_ptr_to_t_bytes_storage // TODO: consider wrapping behaviour at end of storage -function storeBytesFromMemory(slot: word, src: word) -> () { +function storeBytesFromMemory(slot: word, src: word) { assembly { let newLen := mload(src) // TODO: check old len, cleanup etc @@ -2522,7 +2523,7 @@ function storeBytesFromMemory(slot: word, src: word) -> () { // shamelessly stolen from abi_encode_t_string_storage_to_t_string_memory_ptr -function loadBytesFromStorage(slot:word, memPtr:word) -> word { +function loadBytesFromStorage(slot: word, memPtr: word) returns (word) { let pos = memPtr; let slotValue = sload(slot); let length = slotValue / 2; @@ -2532,47 +2533,49 @@ function loadBytesFromStorage(slot:word, memPtr:word) -> word { } mstore(pos, length); pos += 32; - match outOfPlaceEncoding { - | false => - // Short byte array + match (outOfPlaceEncoding) { +case false { +// Short byte array mstore(pos, slotValue & ~0xff); let empty = iszero(length); let notzero = iszero(empty); return pos + (notzero * 32); - | true => - // Long byte array +} +case true { +// Long byte array let dataPos = hash1(slot); let i = 0; for (; i < length; i += 32, dataPos += 1) { mstore(pos + i, sload(dataPos)); } return pos + i; - } +} +} } // -- Tuple-based indexed access: -forall col_idx val . class col_idx:RValueIdxAccess(val) { - function lookup(ci : col_idx) -> val; +trait RValueIdxAccess { + function lookup(ci: col_idx) returns (val) ; } -forall col_idx ref . class col_idx:LValueIdxAccess(ref) { - function lookup(ci : col_idx) -> ref; +trait LValueIdxAccess { + function lookup(ci: col_idx) returns (ref) ; } -forall i a . i:Typedef(word) => -instance (storage(mapping(i,a)), i): LValueIdxAccess(storage(a)) { - function lookup(xi : (storage(mapping(i,a)), i)) -> storage(a) { - match(xi) { - | (x, i) => return storage(hash2(Typedef.rep(x), Typedef.rep(i))); - } +impl LValueIdxAccess<(storage a)>, i), storage> where i: Typedef { + function lookup(xi: (storage a)>, i)) returns (storage) { + match (xi) { +case (x, i) { +return storage(hash2(Typedef.rep(x), Typedef.rep(i))); +} +} } } -forall i a . storage(a):CanStore(a), i:Typedef(word) => -instance (storage(mapping(i,a)), i): RValueIdxAccess(a) { - function lookup(xi : (storage(mapping(i,a)), i)) -> a { +impl RValueIdxAccess<(storage a)>, i), a> where storage: CanStore, i: Typedef { + function lookup(xi: (storage a)>, i)) returns (a) { /* match(xi) { | (x, i) => return StorageType.load(hash2(Typedef.rep(x), Typedef.rep(i))); @@ -2582,114 +2585,107 @@ instance (storage(mapping(i,a)), i): RValueIdxAccess(a) { } } -forall a i . i:Typedef(word) => -instance (storage(array(a)), i): LValueIdxAccess(storage(a)) { - function lookup(xi : (storage(array(a)), i)) -> storage(a) { - match(xi) { - | (x, i) => - let slot : word = Typedef.rep(x); +impl LValueIdxAccess<(storage>, i), storage> where i: Typedef { + function lookup(xi: (storage>, i)) returns (storage) { + match (xi) { +case (x, i) { +let slot : word = Typedef.rep(x); let idx : word = Typedef.rep(i); // Bounds check: idx must be in [0, length). Length lives at the // slot itself; inlined to avoid an Array(t) dispatch here. if (idx >= sload(slot)) { out_of_bounds(); } return storage(hash1(slot) + idx); - } +} +} } } // Reading arr[i] yields whatever the element's storage reference loads, rather // than the element tag type. For word-sized elements that is the element itself; -// for array(string) it is a memory(string); for a nested array(array(t)) it +// for array it is a memory; for a nested array> it // is the inner array's handle, which push/pop/length then consume. -forall a v i . storage(a):CanStore(v), i:Typedef(word) => -instance (storage(array(a)), i): RValueIdxAccess(v) { - function lookup(xi : (storage(array(a)), i)) -> v { +impl RValueIdxAccess<(storage>, i), v> where storage: CanStore, i: Typedef { + function lookup(xi: (storage>, i)) returns (v) { return CanStore.load(LValueIdxAccess.lookup(xi)); } } // Indexed read of a lazily-decoded calldata array: `arr[i]` desugars to // ridx(arr, i), which dispatches here and decodes element i on demand via -// abiArrayGet. There is deliberately no LValueIdxAccess instance — calldata is +// abiArrayGet. There is deliberately no LValueIdxAccess impl — calldata is // immutable, so `arr[i] = …` is (correctly) rejected at compile time. -forall t t_decoded i . - t : ABIAttribs, - ABIDecoder(t, CalldataWordReader):ABIDecode(t_decoded), - i : Typedef(word) => -instance (calldata(array(t)), i): RValueIdxAccess(t_decoded) { - function lookup(xi : (calldata(array(t)), i)) -> t_decoded { - match(xi) { - | (a, idx) => return abiArrayGet(a, uint256(Typedef.rep(idx))); - } +impl RValueIdxAccess<(calldata>, i), t_decoded> where t: ABIAttribs, ABIDecoder: ABIDecode, i: Typedef { + function lookup(xi: (calldata>, i)) returns (t_decoded) { + match (xi) { +case (a, idx) { +return abiArrayGet(a, uint256(Typedef.rep(idx))); +} +} } } // Memory arrays are read-only through `m[i]`: there is no memory cell reference -// type, so they get an RValue instance but no LValue one. -forall t i . t:Typedef(word), i:Typedef(word) => -instance (memory(DynArray(t)), i): RValueIdxAccess(t) { - function lookup(xi : (memory(DynArray(t)), i)) -> t { - match xi { - | (x, j) => return IndexAccess.get(x, uint256(Typedef.rep(j))); - } +// type, so they get an RValue impl but no LValue one. +impl RValueIdxAccess<(memory>, i), t> where t: Typedef, i: Typedef { + function lookup(xi: (memory>, i)) returns (t) { + match (xi) { +case (x, j) { +return IndexAccess.get(x, uint256(Typedef.rep(j))); +} +} } } // Mapping reads go through CanStore, matching the write side (Assign -> CanStore.store). -// This lets a mapping hold any value with a CanStore instance — including ADTs whose -// fields are dynamic (memory(bytes)) — not just the fixed-slot StorageType primitives. -forall a. storage(a):CanStore(a) => -function readStorage(x:storage(a)) -> a { +// This lets a mapping hold any value with a CanStore impl — including ADTs whose +// fields are dynamic (memory) — not just the fixed-slot StorageType primitives. +function readStorage(x: storage) returns (a) where storage: CanStore { return CanStore.load(x); } /* -forall r a. a:StorageType, r: RValueIdxAccess(a) => -function rval(x:r) -> a { +function rval(x: r) returns (a) where a: StorageType, r: RValueIdxAccess { return RValueIdxAccess.lookup(x); } -forall r a. r: LValueIdxAccess(a) => -function lval(x:r) -> a { +function lval(x: r) returns (a) where r: LValueIdxAccess { return LValueIdxAccess.lookup(x); } */ // lidx/ridx are the generic indexed-access helpers used by the `arr[i]` // desugaring. They dispatch through LValueIdxAccess / RValueIdxAccess, so any -// collection (mapping, array, ...) that provides those instances supports the +// collection (mapping, array, ...) that provides those impls supports the // `arr[i]` syntax. -forall col idx ref . (col, idx):LValueIdxAccess(ref) => -function lidx(c: col, i: idx) -> ref { +function lidx(c: col, i: idx) returns (ref) where (col, idx): LValueIdxAccess { return LValueIdxAccess.lookup((c, i)); } -forall col idx val . (col, idx):RValueIdxAccess(val) => -function ridx(c: col, i: idx) -> val { +function ridx(c: col, i: idx) returns (val) where (col, idx): RValueIdxAccess { return RValueIdxAccess.lookup((c, i)); } // --- Memory Encoding --- -forall t . class t:MemorySize { +trait MemorySize { // The size needed for the value. - function len(v: t) -> word; + function len(v: t) returns (word) ; } // NOTE: this is not implemented for value types. -forall t . class t:MemoryPointer { +trait MemoryPointer { // In-memory location of the given value. - function ptr(v: t) -> word; + function ptr(v: t) returns (word) ; } -forall t . class t:MemoryEncode { +trait MemoryEncode { // Serialize the entire contents at a provided memory area. - function encodeInto(v: t, target: word) -> (); + function encodeInto(v: t, target: word) ; } // TODO: support variadic arguments // Allocates new memory and concatenates the inputs into it. -forall a b . a:MemorySize, a:MemoryEncode, b:MemorySize, b:MemoryEncode => function concat(x: a, y: b) -> memory(bytes) { +function concat(x: a, y: b) returns (memory) where a: MemorySize, a: MemoryEncode, b: MemorySize, b: MemoryEncode { let x_len = MemorySize.len(x); let y_len = MemorySize.len(y); let res: word = allocate_memory(32 + x_len + y_len); @@ -2700,7 +2696,7 @@ forall a b . a:MemorySize, a:MemoryEncode, b:MemorySize, b:MemoryEncode => funct } // This is a specialized 1-input version of concat. -forall a . a:MemorySize, a:MemoryEncode => function to_bytes(x: a) -> memory(bytes) { +function to_bytes(x: a) returns (memory) where a: MemorySize, a: MemoryEncode { let len = MemorySize.len(x); let res = allocate_memory(32 + len); mstore(res, len); @@ -2708,32 +2704,32 @@ forall a . a:MemorySize, a:MemoryEncode => function to_bytes(x: a) -> memory(byt return memory(res); } -instance bytes32:MemorySize { - function len(v: bytes32) -> word { +impl MemorySize { + function len(v: bytes32) returns (word) { return 32; } } -instance bytes32:MemoryEncode { - function encodeInto(v: bytes32, target: word) -> () { +impl MemoryEncode { + function encodeInto(v: bytes32, target: word) { mstore(target, Typedef.rep(v)); } } -instance memory(bytes):MemorySize { - function len(v: memory(bytes)) -> word { +impl MemorySize> { + function len(v: memory) returns (word) { return mload(Typedef.rep(v)); } } -instance memory(bytes):MemoryPointer { - function ptr(v: memory(bytes)) -> word { +impl MemoryPointer> { + function ptr(v: memory) returns (word) { return Typedef.rep(v) + 32; } } -instance memory(bytes):MemoryEncode { - function encodeInto(v: memory(bytes), target: word) -> () { +impl MemoryEncode> { + function encodeInto(v: memory, target: word) { let v_ = Typedef.rep(v); mcopy(target, v_ + 32, mload(v_)); } @@ -2742,22 +2738,26 @@ instance memory(bytes):MemoryEncode { // Placeholder for an empty memory area. // The value is the size of the area in bytes. The area will be zeroed upon serialization. // NOTE: not implementing Typedef by design. -data empty = empty(word); +enum empty { empty(word) } -instance empty:MemorySize { - function len(v: empty) -> word { - match v { - | empty(size) => return size; - } +impl MemorySize { + function len(v: empty) returns (word) { + match (v) { +case empty(size) { +return size; +} +} } } -instance empty:MemoryEncode { - function encodeInto(v: empty, target: word) -> () { +impl MemoryEncode { + function encodeInto(v: empty, target: word) { let size; - match v { - | empty(size_) => size = size_; - } + match (v) { +case empty(size_) { +size = size_; +} +} zeroize_memory(target, size); } } @@ -2766,42 +2766,46 @@ instance empty:MemoryEncode { // This is a very cheap abstraction over a memory area of [ptr, ptr+len) // No type information is preserved. -data memory_ref = memory_ref(word, word); +enum memory_ref { memory_ref(word, word) } -instance memory_ref:MemorySize { - function len(v: memory_ref) -> word { - match v { - | memory_ref(ptr, len) => return len; - } +impl MemorySize { + function len(v: memory_ref) returns (word) { + match (v) { +case memory_ref(ptr, len) { +return len; +} +} } } -instance memory_ref:MemoryPointer { - function ptr(v: memory_ref) -> word { - match v { - | memory_ref(ptr, len) => return ptr; - } +impl MemoryPointer { + function ptr(v: memory_ref) returns (word) { + match (v) { +case memory_ref(ptr, len) { +return ptr; +} +} } } -instance memory_ref:MemoryEncode { - function encodeInto(v: memory_ref, target: word) -> () { - match v { - | memory_ref(ptr, len) => mcopy(target, ptr, len); - } +impl MemoryEncode { + function encodeInto(v: memory_ref, target: word) { + match (v) { +case memory_ref(ptr, len) { +mcopy(target, ptr, len); +} +} } } -forall a . a:MemorySize, a:MemoryPointer => -function slice_(input: a, start: word) -> memory_ref { +function slice_(input: a, start: word) returns (memory_ref) where a: MemorySize, a: MemoryPointer { let len = MemorySize.len(input); // TODO: should this allow (it does now) a zero-length slice? require(len >= start, Error(0xb4120f14)); // OutOfBounds() return memory_ref(MemoryPointer.ptr(input) + start, len - start); } -forall a . a:MemorySize, a:MemoryPointer => -function truncate(input: a, end: word) -> memory_ref { +function truncate(input: a, end: word) returns (memory_ref) where a: MemorySize, a: MemoryPointer { let len = MemorySize.len(input); // TODO: should this allow (it does now) a zero-length slice? require(len >= end, Error(0xb4120f14)); // OutOfBounds() @@ -2811,13 +2815,13 @@ function truncate(input: a, end: word) -> memory_ref { // --- Hashing --- // NOTE: keccak256 name conflicts with assembly namespace -forall a . a:MemorySize, a:MemoryPointer => function keccak256_(input: a) -> bytes32 { +function keccak256_(input: a) returns (bytes32) where a: MemorySize, a: MemoryPointer { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); return bytes32(keccak256(ptr, len)); } -forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 { +function sha256(input: a) returns (bytes32) where a: MemorySize, a: MemoryPointer { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); // We assume the [0, 32] scratch space is reserved. @@ -2826,7 +2830,7 @@ forall a . a:MemorySize, a:MemoryPointer => function sha256(input: a) -> bytes32 return bytes32(mload(0)); } -forall a . a:MemorySize, a:MemoryPointer => function ripemd160(input: a) -> bytes32 { +function ripemd160(input: a) returns (bytes32) where a: MemorySize, a: MemoryPointer { let len : word = MemorySize.len(input); let ptr : word = MemoryPointer.ptr(input); // We assume the [0, 32] scratch space is reserved. @@ -2842,7 +2846,7 @@ forall a . a:MemorySize, a:MemoryPointer => function ripemd160(input: a) -> byte // were updated to ban this, but the precompile wasn't. If a user relies on that // feature they can call the precompile via assembly. // TODO: use uint8 -function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) -> address { +function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) returns (address) { // MalleableSignatureRejected() require( Typedef.rep(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, @@ -2875,11 +2879,11 @@ function ecrecover(hash: bytes32, v: uint256, r: bytes32, s: bytes32) -> address // ERC-7201 namespaced storage slot, computed entirely at compile time from a // string-literal namespace `id`: // keccak256(abi.encode(uint256(keccak256(bytes(id))) - 1)) & ~bytes32(uint256(0xff)) -function erc7201(comptime id: string) -> comptime bytes32 { +function erc7201(comptime id: string) returns (comptime) { return bytes32(keccakWordLit(keccakLit(id) - 1) & ~0xff); } -forall a . a:MemorySize, a:MemoryPointer => function raw_call(target: address, value: uint256, payload: a) -> (bool, memory(bytes)) { +function raw_call(target: address, value: uint256, payload: a) returns (bool, memory) where a: MemorySize, a: MemoryPointer { let ret = call( gas(), Typedef.rep(target), From 29db6f39aa58743139cb3118f63f6ba8d9be006a Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 090/110] Switch the compiler and fixtures to canonical syntax: test utils Co-authored-by: Codex --- crates/test-utils/src/e2e/vector.rs | 2 +- crates/test-utils/src/lib.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/test-utils/src/e2e/vector.rs b/crates/test-utils/src/e2e/vector.rs index 05806323..c4018df9 100644 --- a/crates/test-utils/src/e2e/vector.rs +++ b/crates/test-utils/src/e2e/vector.rs @@ -81,7 +81,7 @@ impl RawE2eConstructor { } } -/// Loads `main.json` next to a `main.solc` fixture when it exists. +/// Loads `main.json` next to a `main.sol` fixture when it exists. pub fn load_raw_e2e_vector(source_path: &Path) -> Result, E2eFailure> { let vector_path = source_path.with_extension("json"); let source = match fs::read_to_string(&vector_path) { diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs index e6cee3b0..f344de89 100644 --- a/crates/test-utils/src/lib.rs +++ b/crates/test-utils/src/lib.rs @@ -264,8 +264,8 @@ where ); } - let entry_path = root.join("main.solc"); - module_key_for_path(LibraryId::Main, root, &entry_path).expect("fixture main.solc key") + let entry_path = root.join("main.sol"); + module_key_for_path(LibraryId::Main, root, &entry_path).expect("fixture main.sol key") } pub fn load_main_source(db: &mut Db, source: &str) -> ModuleKey @@ -403,7 +403,7 @@ pub fn render_diagnostics(db: &dyn hir::Db, diagnostics: &[Diagnostic]) -> Strin pub fn assert_diagnostics_snapshot(fixture_root: &Path, rendered: &str) { let mut settings = insta::Settings::new(); settings.set_snapshot_path(fixture_root); - settings.set_input_file(fixture_root.join("main.solc")); + settings.set_input_file(fixture_root.join("main.sol")); settings.set_prepend_module_to_snapshot(false); settings.bind(|| { insta::assert_snapshot!("diagnostics", rendered); @@ -450,7 +450,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -480,7 +480,7 @@ fn load_library_files( let path = entry.expect("fixture entry").path(); if path.is_dir() { load_library_files(db, library.clone(), root, &path, url_style); - } else if path.extension().and_then(|ext| ext.to_str()) == Some("solc") { + } else if path.extension().and_then(|ext| ext.to_str()) == Some("sol") { let key = module_key_for_path(library.clone(), root, &path).expect("module key"); let file = source_file_for_path(db, &key, &path, url_style); db.insert_module_file(key, file); @@ -518,7 +518,7 @@ fn fixture_url(key: &ModuleKey) -> Url { LibraryId::External(name) => format!("external/{name}"), }; let path = key.logical_path.join("/"); - format!("memory:///{library}/{path}.solc") + format!("memory:///{library}/{path}.sol") .parse() .expect("fixture memory URL") } From 5113d5f93640b06bd80e0c361affa4a8db512553 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 091/110] Switch the compiler and fixtures to canonical syntax: tests Co-authored-by: Codex --- tests/e2e/00answer/main.sol | 6 +- tests/e2e/01id/main.sol | 12 ++-- tests/e2e/021not/main.sol | 36 +++++++----- tests/e2e/022add/main.sol | 8 +-- tests/e2e/024arith/main.sol | 20 +++---- tests/e2e/02nid/main.sol | 12 ++-- tests/e2e/031maybe/main.sol | 24 ++++---- tests/e2e/032simplejoin/main.sol | 66 ++++++++++++++-------- tests/e2e/033join/main.sol | 38 ++++++++----- tests/e2e/034cojoin/main.sol | 62 +++++++++++++-------- tests/e2e/035padding/main.sol | 22 +++++--- tests/e2e/036wildcard/main.sol | 22 +++++--- tests/e2e/037dwarves/main.sol | 38 ++++++++----- tests/e2e/038food0/main.sol | 30 ++++++---- tests/e2e/039food/main.sol | 46 +++++++++------ tests/e2e/041pair/main.sol | 16 +++--- tests/e2e/042triple/main.sol | 16 +++--- tests/e2e/043fstsnd/main.sol | 34 +++++++----- tests/e2e/047rgb/main.sol | 24 +++++--- tests/e2e/048rgb2/main.sol | 26 +++++---- tests/e2e/049rgb3/main.sol | 26 +++++---- tests/e2e/06comp/main.sol | 10 ++-- tests/e2e/09not/main.sol | 36 +++++++----- tests/e2e/10negBool/main.sol | 42 ++++++++------ tests/e2e/11negPair/main.sol | 80 ++++++++++++++++----------- tests/e2e/120basicCounter/main.sol | 6 +- tests/e2e/121counter/main.sol | 6 +- tests/e2e/122counters/main.sol | 6 +- tests/e2e/123stackAndStorage/main.sol | 6 +- tests/e2e/126nanoerc20/main.sol | 45 +++++++-------- tests/e2e/127microerc20/main.sol | 62 ++++++++++++--------- tests/e2e/128minierc20/main.sol | 16 +++--- 32 files changed, 531 insertions(+), 368 deletions(-) diff --git a/tests/e2e/00answer/main.sol b/tests/e2e/00answer/main.sol index 62688c3f..b4d99d37 100644 --- a/tests/e2e/00answer/main.sol +++ b/tests/e2e/00answer/main.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Answer { // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(42); } } diff --git a/tests/e2e/01id/main.sol b/tests/e2e/01id/main.sol index 4701418b..702f4184 100644 --- a/tests/e2e/01id/main.sol +++ b/tests/e2e/01id/main.sol @@ -1,18 +1,18 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Id1 { - data Bool = False | True; + enum Bool { False, True } - function id(x : word) -> word { + function id(x: word) returns (word) { return x ; } - function const(x : word, y : Bool) -> word { return x; } + function const(x: word, y: Bool) returns (word) { return x; } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(const(id(42), Bool.False)); } } diff --git a/tests/e2e/021not/main.sol b/tests/e2e/021not/main.sol index ebb0cc23..7f285805 100644 --- a/tests/e2e/021not/main.sol +++ b/tests/e2e/021not/main.sol @@ -1,25 +1,33 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Not { - data Bool = False | True; + enum Bool { False, True } // #[() -> 1] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(fromBool(bnot(Bool.False))); } - function fromBool(b : Bool) -> word { - match(b) { - | Bool.False => return 0; - | Bool.True => return 1; - } + function fromBool(b: Bool) returns (word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } - function bnot(b : Bool) -> Bool { - match b { - | Bool.False => return Bool.True; - | Bool.True => return Bool.False; - } + function bnot(b: Bool) returns (Bool) { + match (b) { +case Bool.False { +return Bool.True; +} +case Bool.True { +return Bool.False; +} +} } } diff --git a/tests/e2e/022add/main.sol b/tests/e2e/022add/main.sol index 39ea0bcc..75d1490b 100644 --- a/tests/e2e/022add/main.sol +++ b/tests/e2e/022add/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -11,7 +11,7 @@ function add(x : word, y : word) -> word { contract Add1 { // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(add(40, 2)); } } diff --git a/tests/e2e/024arith/main.sol b/tests/e2e/024arith/main.sol index 19d59584..cedac761 100644 --- a/tests/e2e/024arith/main.sol +++ b/tests/e2e/024arith/main.sol @@ -1,6 +1,6 @@ -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -8,7 +8,7 @@ function add(x : word, y : word) -> word { return res; } -function sub(x : word, y : word) -> word { +function sub(x: word, y: word) returns (word) { let res: word; assembly { res := sub(x, y) @@ -16,7 +16,7 @@ function sub(x : word, y : word) -> word { return res; } -function div(x : word, y: word) -> word { +function div(x: word, y: word) returns (word) { let res: word; assembly { res := div(x, y) @@ -24,7 +24,7 @@ function div(x : word, y: word) -> word { return res; } -function sdiv(x : word, y: word) -> word { +function sdiv(x: word, y: word) returns (word) { let res: word; assembly { res := sdiv(x, y) @@ -32,7 +32,7 @@ function sdiv(x : word, y: word) -> word { return res; } -function mod(x : word, y: word) -> word { +function mod(x: word, y: word) returns (word) { let res: word; assembly { res := mod(x, y) @@ -40,7 +40,7 @@ function mod(x : word, y: word) -> word { return res; } -function smod(x : word, y: word) -> word { +function smod(x: word, y: word) returns (word) { let res: word; assembly { res := smod(x, y) @@ -48,7 +48,7 @@ function smod(x : word, y: word) -> word { return res; } -function exp(x : word, y: word) -> word { +function exp(x: word, y: word) returns (word) { let res: word; assembly { res := exp(x, y) @@ -59,9 +59,9 @@ function exp(x : word, y: word) -> word { contract Arith { // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(add(mod(sub(div(exp(2,18),4), 1), 16), 27)); } } -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; diff --git a/tests/e2e/02nid/main.sol b/tests/e2e/02nid/main.sol index 7c131b16..9a430a68 100644 --- a/tests/e2e/02nid/main.sol +++ b/tests/e2e/02nid/main.sol @@ -1,19 +1,19 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Id1 { - function id(x : word) -> word { + function id(x: word) returns (word) { return x ; } - function nid(x : word) -> word { + function nid(x: word) returns (word) { return id(x); } - function const(x : word, y : word) -> word { return x; } + function const(x: word, y: word) returns (word) { return x; } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(const(nid(42), id(1))); } } diff --git a/tests/e2e/031maybe/main.sol b/tests/e2e/031maybe/main.sol index d3b2b098..b50c33d4 100644 --- a/tests/e2e/031maybe/main.sol +++ b/tests/e2e/031maybe/main.sol @@ -1,20 +1,24 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) returns (Option) { return Option.Some(x); } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(0, Option.Some(42))); } } diff --git a/tests/e2e/032simplejoin/main.sol b/tests/e2e/032simplejoin/main.sol index 335981a4..49d27ba8 100644 --- a/tests/e2e/032simplejoin/main.sol +++ b/tests/e2e/032simplejoin/main.sol @@ -1,39 +1,57 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) returns (Option) { return Option.Some(x); } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - function join(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.None => return Option.None; - | Option.Some(Option.None) => return Option.None; - | Option.Some(Option.Some(x)) => return Option.Some(x); - } + function join(mmx: Option>) returns (Option) { + match (mmx) { +case Option.None { +return Option.None; +} +case Option.Some(Option.None) { +return Option.None; +} +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +} } - function join2(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.Some(m) => match m { - | Option.None => return Option.None; - | Option.Some(x) => return Option.Some(x); - } - | _ => return Option.None; - } + function join2(mmx: Option>) returns (Option) { + match (mmx) { +case Option.Some(m) { +match (m) { +case Option.None { +return Option.None; +} +case Option.Some(x) { +return Option.Some(x); +} +} +} +default { +return Option.None; +} +} } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(0, join(Option.Some(Option.Some(42))))); } } diff --git a/tests/e2e/033join/main.sol b/tests/e2e/033join/main.sol index 4983d136..5d592df4 100644 --- a/tests/e2e/033join/main.sol +++ b/tests/e2e/033join/main.sol @@ -1,27 +1,35 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) returns (Option) { return Option.Some(x); } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - function join(mmx : Option(Option(word))) -> Option(word) { - match mmx { - | Option.Some(Option.Some(x)) => return Option.Some(x); - | _ => return Option.None; - } + function join(mmx: Option>) returns (Option) { + match (mmx) { +case Option.Some(Option.Some(x)) { +return Option.Some(x); +} +default { +return Option.None; +} +} } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(0, join(Option.Some(Option.Some(42))))); } } diff --git a/tests/e2e/034cojoin/main.sol b/tests/e2e/034cojoin/main.sol index 0fc367bc..1c9a1dd1 100644 --- a/tests/e2e/034cojoin/main.sol +++ b/tests/e2e/034cojoin/main.sol @@ -1,37 +1,53 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) returns (Option) { return Option.Some(x); } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - function join(mmx : Option(Option(word))) -> Option(word) { + function join(mmx: Option>) returns (Option) { let result = Option.None; - match mmx { - | Option.Some(Option.Some(x)) => result = Option.Some(x); - | Option.None => result = Option.None; - | Option.Some(Option.None) => result = Option.None; - | _ => result = Option.None; - } + match (mmx) { +case Option.Some(Option.Some(x)) { +result = Option.Some(x); +} +case Option.None { +result = Option.None; +} +case Option.Some(Option.None) { +result = Option.None; +} +default { +result = Option.None; +} +} return result; } - function extract(mx : Option(word)) -> word { - match mx { - | Option.Some(x) => return x; - | Option.None => return 0; - } + function extract(mx: Option) returns (word) { + match (mx) { +case Option.Some(x) { +return x; +} +case Option.None { +return 0; +} +} } - function cojoin(x : Option(word)) -> Option(Option(word)) { // Test that sum types can grow + function cojoin(x: Option) returns (Option>) { // Test that sum types can grow let result = Option.None; result = Option.Some(x); return result; @@ -39,7 +55,7 @@ contract Option { // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(0, join(cojoin(Option.Some(42))))); } } diff --git a/tests/e2e/035padding/main.sol b/tests/e2e/035padding/main.sol index 7da8ee9b..c367e757 100644 --- a/tests/e2e/035padding/main.sol +++ b/tests/e2e/035padding/main.sol @@ -1,18 +1,22 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.Some(x) => return x; - | Option.None => return n; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.Some(x) { +return x; +} +case Option.None { +return n; +} +} } // #[() -> 7] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(7, Option.None)); } } diff --git a/tests/e2e/036wildcard/main.sol b/tests/e2e/036wildcard/main.sol index 02896840..ef557144 100644 --- a/tests/e2e/036wildcard/main.sol +++ b/tests/e2e/036wildcard/main.sol @@ -1,18 +1,22 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.Some(x) => return x; - | _ => return n; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.Some(x) { +return x; +} +default { +return n; +} +} } // #[() -> 7] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(7, Option.None)); } } diff --git a/tests/e2e/037dwarves/main.sol b/tests/e2e/037dwarves/main.sol index 17c1ac0e..5fcf76c8 100644 --- a/tests/e2e/037dwarves/main.sol +++ b/tests/e2e/037dwarves/main.sol @@ -1,21 +1,33 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Dwarves { - data Dwarf = Doc | Grumpy | Sleepy | Bashful | Happy | Sneezy | Dopey; + enum Dwarf { Doc, Grumpy, Sleepy, Bashful, Happy, Sneezy, Dopey } - function fromEnum(c : Dwarf) -> word { - match c { - | Dwarf.Doc => return 1; - | Dwarf.Grumpy => return 2; - | Dwarf.Sleepy => return 3; - | Dwarf.Bashful => return 4; - | Dwarf.Happy => return 5; - | _ => return 0; - } + function fromEnum(c: Dwarf) returns (word) { + match (c) { +case Dwarf.Doc { +return 1; +} +case Dwarf.Grumpy { +return 2; +} +case Dwarf.Sleepy { +return 3; +} +case Dwarf.Bashful { +return 4; +} +case Dwarf.Happy { +return 5; +} +default { +return 0; +} +} } // #[() -> 5] - public function run() -> uint256 { return uint256(fromEnum(Dwarf.Happy)); } + function run() public returns (uint256) { return uint256(fromEnum(Dwarf.Happy)); } } diff --git a/tests/e2e/038food0/main.sol b/tests/e2e/038food0/main.sol index 4a6cd7b7..003dd41c 100644 --- a/tests/e2e/038food0/main.sol +++ b/tests/e2e/038food0/main.sol @@ -1,27 +1,33 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data Food = Curry | Beans | Other; -data CFood = Red(Food) | Green(Food) | Nocolor; +enum Food { Curry, Beans, Other } +enum CFood { Red(Food), Green(Food), Nocolor } - function fromEnum(x : CFood) -> word { - match x { - | CFood.Red(Food.Curry) => return 1; - | CFood.Green(Food.Beans) => return 42; - | _ => return 3; - } + function fromEnum(x: CFood) returns (word) { + match (x) { +case CFood.Red(Food.Curry) { +return 1; +} +case CFood.Green(Food.Beans) { +return 42; +} +default { +return 3; +} +} } contract FoodContract { - function id(x : CFood) -> CFood { + function id(x: CFood) returns (CFood) { return(x); } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(fromEnum(id(CFood.Green(Food.Beans)))); } } diff --git a/tests/e2e/039food/main.sol b/tests/e2e/039food/main.sol index 7e97d0f6..ea65ff50 100644 --- a/tests/e2e/039food/main.sol +++ b/tests/e2e/039food/main.sol @@ -1,32 +1,44 @@ -data Food = Curry | Beans | Other; -data CFood = Red(Food) | Green(Food) | Nocolor; +enum Food { Curry, Beans, Other } +enum CFood { Red(Food), Green(Food), Nocolor } - function fromEnum(x : Food) -> word { - match x { - | Food.Curry => return 1; - | Food.Beans => return 42; - | Food.Other => return 3; - } + function fromEnum(x: Food) returns (word) { + match (x) { +case Food.Curry { +return 1; +} +case Food.Beans { +return 42; +} +case Food.Other { +return 3; +} +} } contract FoodContract { - function eat(x : CFood) -> Food { - match x { - | CFood.Red(f) => return f; - | CFood.Green(f) => return f; - | _ => return Food.Other; - } + function eat(x: CFood) returns (Food) { + match (x) { +case CFood.Red(f) { +return f; +} +case CFood.Green(f) { +return f; +} +default { +return Food.Other; +} +} } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(fromEnum(eat(CFood.Green(Food.Beans)))); } } -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; diff --git a/tests/e2e/041pair/main.sol b/tests/e2e/041pair/main.sol index 5028e235..d6d395f4 100644 --- a/tests/e2e/041pair/main.sol +++ b/tests/e2e/041pair/main.sol @@ -1,16 +1,18 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Pair { - function fst(p : (word, word)) -> word { - match p { - | (a,b) => return a; - } + function fst(p: (word, word)) returns (word) { + match (p) { +case (a,b) { +return a; +} +} } // #[() -> 1] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(fst((1,0))); } } diff --git a/tests/e2e/042triple/main.sol b/tests/e2e/042triple/main.sol index cf4e5320..14183981 100644 --- a/tests/e2e/042triple/main.sol +++ b/tests/e2e/042triple/main.sol @@ -1,16 +1,18 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Triple { - function asel(t : (word, word, word)) -> word { - match t { - | (a,b,c) => return c; - } + function asel(t: (word, word, word)) returns (word) { + match (t) { +case (a,b,c) { +return c; +} +} } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(asel((1,21,42))); } } diff --git a/tests/e2e/043fstsnd/main.sol b/tests/e2e/043fstsnd/main.sol index 8777abaf..43cffc29 100644 --- a/tests/e2e/043fstsnd/main.sol +++ b/tests/e2e/043fstsnd/main.sol @@ -1,21 +1,25 @@ -data B = F | T; -data Pair(a,b) = Pair(a,b); +enum B { F, T } +enum Pair { Pair(a, b) } -forall a b . function fst (p : Pair(a, b)) -> a { - match p { - | Pair(x,y) => return x; - } +function fst(p: Pair) returns (a) { + match (p) { +case Pair(x,y) { +return x; +} +} } -forall a b . function snd(p : Pair(a, b)) -> b { - match p { - | Pair(x,y) => return y; - } +function snd(p: Pair) returns (b) { + match (p) { +case Pair(x,y) { +return y; +} +} } -function add(x : word, y : word) -> word { +function add(x: word, y: word) returns (word) { let res: word; assembly { res := add(x, y) @@ -24,13 +28,13 @@ function add(x : word, y : word) -> word { } -function addPair(p : Pair(word, word)) -> word { +function addPair(p: Pair) returns (word) { return add(fst(p), snd(p)); } contract FstSnd { // #[() -> 42] - public function run() -> uint256 { return uint256(addPair(Pair(41,1))); } + function run() public returns (uint256) { return uint256(addPair(Pair(41,1))); } } -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; diff --git a/tests/e2e/047rgb/main.sol b/tests/e2e/047rgb/main.sol index 69fb1737..b774ae9a 100644 --- a/tests/e2e/047rgb/main.sol +++ b/tests/e2e/047rgb/main.sol @@ -1,14 +1,20 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract RGB { - data Color = R | G | B; + enum Color { R, G, B } // #[() -> 42] - public function run() -> uint256 { - match Color.B { - | Color.R => return uint256(4); - | Color.G => return uint256(2); - | Color.B => return uint256(42); - } + function run() public returns (uint256) { + match (Color.B) { +case Color.R { +return uint256(4); +} +case Color.G { +return uint256(2); +} +case Color.B { +return uint256(42); +} +} } } diff --git a/tests/e2e/048rgb2/main.sol b/tests/e2e/048rgb2/main.sol index 8000ee29..47b569ee 100644 --- a/tests/e2e/048rgb2/main.sol +++ b/tests/e2e/048rgb2/main.sol @@ -1,17 +1,23 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract RGB { - data Color = R | G | B; + enum Color { R, G, B } - function fromEnum(c : Color) -> word { - match c { - | Color.R => return 4; - | Color.G => return 2; - | Color.B => return 42; - } + function fromEnum(c: Color) returns (word) { + match (c) { +case Color.R { +return 4; +} +case Color.G { +return 2; +} +case Color.B { +return 42; +} +} } // #[() -> 42] - public function run() -> uint256 { return uint256(fromEnum(Color.B)); } + function run() public returns (uint256) { return uint256(fromEnum(Color.B)); } } diff --git a/tests/e2e/049rgb3/main.sol b/tests/e2e/049rgb3/main.sol index ca54fbed..b5ced83b 100644 --- a/tests/e2e/049rgb3/main.sol +++ b/tests/e2e/049rgb3/main.sol @@ -1,21 +1,27 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data RGB = Red(word) | Green(word) | Blue(word); +enum RGB { Red(word), Green(word), Blue(word) } contract RGB3 { - function choose(c:RGB) -> word { + function choose(c: RGB) returns (word) { let res : word; - match c { - | .Red(x) => assembly { res := add(x,1) } - | .Green(x) => assembly { res := add(x,2) } - | .Blue(x) => assembly { res := add(x,3) } - } + match (c) { +case .Red(x) { +assembly { res := add(x,1) } +} +case .Green(x) { +assembly { res := add(x,2) } +} +case .Blue(x) { +assembly { res := add(x,3) } +} +} return res; } // #[() -> 44] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(choose(RGB.Green(42))); } } diff --git a/tests/e2e/06comp/main.sol b/tests/e2e/06comp/main.sol index ad232a24..8061ad32 100644 --- a/tests/e2e/06comp/main.sol +++ b/tests/e2e/06comp/main.sol @@ -1,13 +1,13 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Compose { - function id(x : word) -> word { return x; } + function id(x: word) returns (word) { return x; } - function idid(x : word) -> word { return id(id(x)); } + function idid(x: word) returns (word) { return id(id(x)); } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(idid(42)); } } diff --git a/tests/e2e/09not/main.sol b/tests/e2e/09not/main.sol index ebb0cc23..7f285805 100644 --- a/tests/e2e/09not/main.sol +++ b/tests/e2e/09not/main.sol @@ -1,25 +1,33 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Not { - data Bool = False | True; + enum Bool { False, True } // #[() -> 1] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(fromBool(bnot(Bool.False))); } - function fromBool(b : Bool) -> word { - match(b) { - | Bool.False => return 0; - | Bool.True => return 1; - } + function fromBool(b: Bool) returns (word) { + match (b) { +case Bool.False { +return 0; +} +case Bool.True { +return 1; +} +} } - function bnot(b : Bool) -> Bool { - match b { - | Bool.False => return Bool.True; - | Bool.True => return Bool.False; - } + function bnot(b: Bool) returns (Bool) { + match (b) { +case Bool.False { +return Bool.True; +} +case Bool.True { +return Bool.False; +} +} } } diff --git a/tests/e2e/10negBool/main.sol b/tests/e2e/10negBool/main.sol index 81aded12..56d4d52f 100644 --- a/tests/e2e/10negBool/main.sol +++ b/tests/e2e/10negBool/main.sol @@ -1,32 +1,40 @@ -forall a . class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } contract NegBool { - function fromB(b : B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } // #[() -> 1] - public function run() -> uint256 { return uint256(fromB(Neg.neg(B.F))); } + function run() public returns (uint256) { return uint256(fromB(Neg.neg(B.F))); } } -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; diff --git a/tests/e2e/11negPair/main.sol b/tests/e2e/11negPair/main.sol index 4f51cf01..49844f17 100644 --- a/tests/e2e/11negPair/main.sol +++ b/tests/e2e/11negPair/main.sol @@ -1,56 +1,72 @@ -forall a . class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; +enum B { F, T } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } -forall a b . function fst (p : (a, b)) -> a { - match p { - | (x,y) => return x; - } +function fst(p: (a, b)) returns (a) { + match (p) { +case (x,y) { +return x; +} +} } -forall a b . function snd(p : (a, b)) -> b { - match p { - | (x,y) => return y; - } +function snd(p: (a, b)) returns (b) { + match (p) { +case (x,y) { +return y; +} +} } -forall a b . a : Neg, b : Neg => instance (a,b):Neg { - function neg(p : (a,b)) -> (a,b) { +impl Neg<(a, b)> where a: Neg, b: Neg { + function neg(p: (a, b)) returns (a, b) { return (Neg.neg (fst(p)), Neg.neg(snd (p))); } } contract NegPair { - function bnot(x : B) -> B { - match x { - | B.T => return B.F; - | B.F => return B.T; - } + function bnot(x: B) returns (B) { + match (x) { +case B.T { +return B.F; +} +case B.F { +return B.T; +} +} } - function fromB(b : B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } // #[() -> 1] - public function run() -> uint256 { return uint256(fromB(fst(Neg.neg((B.F,B.T))))); } + function run() public returns (uint256) { return uint256(fromB(fst(Neg.neg((B.F,B.T))))); } } -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; diff --git a/tests/e2e/120basicCounter/main.sol b/tests/e2e/120basicCounter/main.sol index 73602863..193ac590 100644 --- a/tests/e2e/120basicCounter/main.sol +++ b/tests/e2e/120basicCounter/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Counter { counter : word; // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { counter = Num.add(counter, 42); return uint256(counter); } diff --git a/tests/e2e/121counter/main.sol b/tests/e2e/121counter/main.sol index c2dfd0f2..379deffa 100644 --- a/tests/e2e/121counter/main.sol +++ b/tests/e2e/121counter/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // test single contract field import std; @@ -11,7 +11,7 @@ contract Counter { counter : word; // #[() -> 1] - public function run() -> uint256 { + function run() public returns (uint256) { counter = std.addWord(counter, 1); return uint256(counter); } diff --git a/tests/e2e/122counters/main.sol b/tests/e2e/122counters/main.sol index a733f727..88def3ee 100644 --- a/tests/e2e/122counters/main.sol +++ b/tests/e2e/122counters/main.sol @@ -1,6 +1,6 @@ // test multiple contract fields -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // import StorageLib; @@ -9,7 +9,7 @@ contract Counter { counter2 : uint256; counter3 : word; // #[() -> 3] - public function run() -> uint256 { + function run() public returns (uint256) { counter1 += 1; counter3 += 2; return uint256(counter1 + counter3); diff --git a/tests/e2e/123stackAndStorage/main.sol b/tests/e2e/123stackAndStorage/main.sol index e38189e9..74a7f66a 100644 --- a/tests/e2e/123stackAndStorage/main.sol +++ b/tests/e2e/123stackAndStorage/main.sol @@ -1,6 +1,6 @@ // test multiple contract fields -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Counter { counter1 : word; @@ -8,7 +8,7 @@ contract Counter { counter3 : word; // #[() -> 3] - public function run() -> uint256 { + function run() public returns (uint256) { let x: word; x = counter1 + 1; counter1 = x; diff --git a/tests/e2e/126nanoerc20/main.sol b/tests/e2e/126nanoerc20/main.sol index 9dd15403..d2e08164 100644 --- a/tests/e2e/126nanoerc20/main.sol +++ b/tests/e2e/126nanoerc20/main.sol @@ -1,11 +1,11 @@ -import std.{*}; -import std.dispatch.{*}; -import std.{address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, not}; +import * from std; +import * from std.dispatch; +import {address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, not} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -13,24 +13,25 @@ function caller() -> address { return address(res); } -function myrevert( msg: (word, word) ) -> () { - match msg { - | (str, len) => - let str1 = str; let len1 = len; +function myrevert(msg: (word, word)) { + match (msg) { +case (str, len) { +let str1 = str; let len1 = len; assembly { mstore(0, str1) revert(0, len1) } - } +} +} } -function myrequire(cond: bool, msg: (word, word) ) -> () { +function myrequire(cond: bool, msg: (word, word)) { if( not(cond) ) { myrevert(msg); } } -function require1(cond: bool) -> () { +function require1(cond: bool) { myrequire (cond, (0x72657175697265313a204641494c, 14) /* "require1: FAIL" */ ); } -function nop() -> () { return ();} +function nop() { return ();} contract Uint { reserved : word; @@ -38,15 +39,15 @@ contract Uint { owner : address; decimals : uint256; totalSupply : uint256; - balances : mapping(address,uint256); + balances : mapping(address => uint256); - function mint(amount:uint256) -> () { + function mint(amount: uint256) { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } // function transferFrom(address src, address dst, uint256 amt) public returns (bool) - function transferFrom(src:address, dst:address, amt:uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) returns (bool) { require1(ge(balances[src], amt)); /* @@ -59,27 +60,27 @@ contract Uint { } - function withdraw(src:address, amt:uint256) -> () { - balances[src] = Num.sub(balances[src], amt):uint256; + function withdraw(src: address, amt: uint256) { + balances[src] = Num.sub(balances[src], amt); } - function deposit(dst:address, amt:uint256) -> () { - balances[dst] = Num.add(balances[dst], amt):uint256; + function deposit(dst: address, amt: uint256) { + balances[dst] = Num.add(balances[dst], amt); } - function init() -> () { + function init() { owner = address(0x123456789abcdef); msg_sender = caller(); decimals = uint256(18); } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { init(); mint(uint256(1000)); let src : address = owner; transferFrom(owner, msg_sender, uint256(42)); - return balances[msg_sender] : uint256; + return balances[msg_sender] ; } } diff --git a/tests/e2e/127microerc20/main.sol b/tests/e2e/127microerc20/main.sol index 1115b5c4..4d6e0c45 100644 --- a/tests/e2e/127microerc20/main.sol +++ b/tests/e2e/127microerc20/main.sol @@ -1,11 +1,11 @@ -import std.{*}; -import std.dispatch.{*}; -import std.{address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not}; +import * from std; +import * from std.dispatch; +import {address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -13,7 +13,7 @@ function caller() -> address { return address(res); } -function require1fail() -> () { +function require1fail() { let res: word; assembly { mstore(0x0, 0x72657175697265313a204641494c) // "require1: FAIL" @@ -22,14 +22,18 @@ function require1fail() -> () { return (); // for the typechecker } -function require1(cond: bool) -> () { - match cond { - | false => return require1fail(); - | true => return (); - } +function require1(cond: bool) { + match (cond) { +case false { +return require1fail(); +} +case true { +return (); +} +} } -function nop() -> () { return ();} +function nop() { return ();} contract Mini { reserved : word; @@ -37,10 +41,10 @@ contract Mini { owner : address; decimals : uint256; totalSupply : uint256; - balances : mapping(address,uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); - function mint(amount:uint256) -> () { + function mint(amount: uint256) { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } @@ -61,16 +65,24 @@ contract Mini { */ // function transferFrom(src:address, dst:address, amt:uint256) -> bool { - function transferFrom(src : address, dst : address, amt : uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) returns (bool) { require1(ge(balances[src], amt)); match (Eq.eq(src, msg_sender)) { - | true => match ne(allowance[src][msg_sender], Num.maxVal():uint256) { - | true => require1(false); - | false => (); - } - | false => (); - } +case true { +match (ne(allowance[src][msg_sender], Num.maxVal())) { +case true { +require1(false); +} +case false { +(); +} +} +} +case false { +(); +} +} /* if ((src != msg_sender) && (allowance [src][msg_sender] != (Num.maxVal():uint256)) ) { @@ -78,7 +90,7 @@ contract Mini { } */ balances[src] = Num.sub(balances[src], amt); - balances[dst] = Num.add(balances[dst], amt):uint256; + balances[dst] = Num.add(balances[dst], amt); return true; } @@ -91,19 +103,19 @@ contract Mini { */ - function init() -> () { + function init() { owner = address(0x123456789abcdef); msg_sender = caller(); decimals = uint256(18); } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { init(); mint(uint256(1000)); allowance[owner][msg_sender] = uint256(10000); transferFrom(owner, msg_sender, uint256(42)); - return balances[msg_sender] : uint256; + return balances[msg_sender] ; } } diff --git a/tests/e2e/128minierc20/main.sol b/tests/e2e/128minierc20/main.sol index 35d3260c..7a2883b0 100644 --- a/tests/e2e/128minierc20/main.sol +++ b/tests/e2e/128minierc20/main.sol @@ -1,11 +1,11 @@ -import std.{*}; -import std.dispatch.{*}; -import std.{address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not}; +import * from std; +import * from std.dispatch; +import {address, uint256, mapping, Num, Add, Sub, Bounded, Eq, Ord, Typedef, ge, ne, not} from std; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -13,11 +13,11 @@ function caller() -> address { return address(res); } -function myrevert(msg: word) -> () { +function myrevert(msg: word) { assembly { mstore(0, msg) revert(0, 32) } } -function myrequire(cond: bool, msg: word ) -> () { +function myrequire(cond: bool, msg: word) { if( !cond ) { myrevert(msg); } } @@ -26,8 +26,8 @@ contract MiniERC20 { owner : address; decimals : uint256; totalSupply : uint256; - balances : mapping(address,uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); function mint(amount:uint256) -> () { balances[owner] = Num.add(balances[owner], amount); From 508cef4436002fe18c3ab0950420d56070ee71bf Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 092/110] Switch the compiler and fixtures to canonical syntax: tests Co-authored-by: Codex --- tests/e2e/128minierc20/main.sol | 12 +-- tests/e2e/903badassign/main.sol | 46 ++++++---- tests/e2e/939badfood/main.sol | 32 ++++--- tests/e2e/README.md | 33 +++---- tests/e2e/SimpleField/main.sol | 8 +- tests/e2e/abi-address-array/main.sol | 12 +-- tests/e2e/abi-array-sum/main.sol | 44 +++++---- tests/e2e/abi-batch-adt/main.sol | 72 +++++++++------ tests/e2e/abi-boundaries/main.sol | 12 +-- tests/e2e/abi-bytes-array/main.sol | 12 +-- tests/e2e/abi-dyn-sum-return/main.sol | 30 +++---- tests/e2e/abi-dyn-sum/main.sol | 40 +++++---- tests/e2e/abi-encode-adt/main.sol | 28 +++--- tests/e2e/abi-encode-types/main.sol | 22 ++--- tests/e2e/abi-sum-roundtrip/main.sol | 20 ++--- tests/e2e/arithmetic/main.sol | 8 +- tests/e2e/array-copy/main.sol | 24 ++--- tests/e2e/array-literals/main.sol | 34 +++---- tests/e2e/array-nested/main.sol | 30 +++---- tests/e2e/array-ops/main.sol | 16 ++-- tests/e2e/array-string/main.sol | 22 ++--- tests/e2e/arraylit/main.sol | 34 +++---- tests/e2e/asm-break-continue-leave/main.sol | 8 +- tests/e2e/assembly/main.sol | 6 +- tests/e2e/audit-constructor-suffix/main.sol | 22 +++-- tests/e2e/audit-nested-pair-tail/main.sol | 24 ++--- tests/e2e/basic/main.sol | 90 ++++++++++--------- tests/e2e/composite-values/main.sol | 10 +-- .../compound-assignment-class-method/main.sol | 20 +++-- tests/e2e/concat/main.sol | 22 ++--- tests/e2e/deposit/main.sol | 28 +++--- tests/e2e/derive-class/main.sol | 76 +++++++++------- 32 files changed, 489 insertions(+), 408 deletions(-) diff --git a/tests/e2e/128minierc20/main.sol b/tests/e2e/128minierc20/main.sol index 7a2883b0..20b8b006 100644 --- a/tests/e2e/128minierc20/main.sol +++ b/tests/e2e/128minierc20/main.sol @@ -29,7 +29,7 @@ contract MiniERC20 { balances : mapping(address => uint256); allowance : mapping(address => mapping(address => uint256)); - function mint(amount:uint256) -> () { + function mint(amount: uint256) { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } @@ -49,13 +49,13 @@ contract MiniERC20 { } */ - function transferFrom(src:address, dst:address, amt:uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) returns (bool) { let msg_sender = caller(); myrequire( balances[src] >= amt /* "token/insufficient-balance" */ , 0x746f6b656e2f696e73756666696369656e742d62616c616e6365 ); - if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal():uint256)) { + if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal())) { myrequire( allowance[src][msg_sender] >= amt /* "token/insufficient-allowance" */ , 0x746f6b656e2f696e73756666696369656e742d616c6c6f77616e6365 ); @@ -74,7 +74,7 @@ contract MiniERC20 { } */ - function approve(usr: address, amt: uint256) -> bool { + function approve(usr: address, amt: uint256) returns (bool) { let msg_sender = caller(); allowance[msg_sender][usr] = amt; // emit Approval(msg.sender, usr, amt); @@ -82,13 +82,13 @@ contract MiniERC20 { } - function init() -> () { + function init() { owner = address(0x123456789abcdef); decimals = uint256(18); // Num.fromWord(18) fails, which may be a problem } // #[() -> 958] - public function run() -> uint256 { + function run() public returns (uint256) { let msg_sender = caller(); init(); mint(uint256(1000)); diff --git a/tests/e2e/903badassign/main.sol b/tests/e2e/903badassign/main.sol index 508eb794..b91857d6 100644 --- a/tests/e2e/903badassign/main.sol +++ b/tests/e2e/903badassign/main.sol @@ -1,31 +1,43 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Option { - data Option(a) = None | Some(a); + enum Option { None, Some(a) } - function just(x : word) -> Option(word) { return Option.Some(x); } + function just(x: word) returns (Option) { return Option.Some(x); } - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n: word, o: Option) returns (word) { + match (o) { +case Option.None { +return n; +} +case Option.Some(x) { +return x; +} +} } - function join(mmx : Option(Option(word))) -> Option(word) { + function join(mmx: Option>) returns (Option) { let result = Option.None; - match mmx { - | Option.Some(Option.Some(x)) => result = Option.Some(x); - | Option.None => result = Option.None; - | Option.Some(Option.None) => result = Option.None; - | _ => result = Option.None; - } + match (mmx) { +case Option.Some(Option.Some(x)) { +result = Option.Some(x); +} +case Option.None { +result = Option.None; +} +case Option.Some(Option.None) { +result = Option.None; +} +default { +result = Option.None; +} +} return result; } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(maybe(0, join(Option.Some(Option.Some(42))))); } } diff --git a/tests/e2e/939badfood/main.sol b/tests/e2e/939badfood/main.sol index f3001ef8..0a5ca5b3 100644 --- a/tests/e2e/939badfood/main.sol +++ b/tests/e2e/939badfood/main.sol @@ -1,25 +1,31 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -forall a . class a: Enum { - function fromEnum(x : a) -> word; +trait Enum { + function fromEnum(x: a) returns (word) ; } -data Food = Curry | Beans | Other; +enum Food { Curry, Beans, Other } -instance Food : Enum { - function fromEnum(x : Food) -> word { - match x { - | Food.Curry => return 1; - | Food.Beans => return 2; - | Food.Other => return 3; - } +impl Enum { + function fromEnum(x: Food) returns (word) { + match (x) { +case Food.Curry { +return 1; +} +case Food.Beans { +return 2; +} +case Food.Other { +return 3; +} +} } } contract FoodContract { // #[() -> 2] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(Enum.fromEnum(Food.Beans)); } } diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 74cb6749..5ffd9ffc 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1,14 +1,14 @@ # Backend E2E fixtures -Both the Yul and Sonatina backends generate a test for every `**/main.solc` -fixture in this directory. Selector-dispatched fixtures explicitly import both -`std.{*}` and `std.dispatch.{*}`. Expectations live next to the contract +Both the Yul and Sonatina backends generate a test for every `**/main.sol` +fixture in this directory. Selector-dispatched fixtures explicitly open both +`std` and `std.dispatch` with `import * from ...`. Expectations live next to the contract function they exercise: ```solcore // #[(0, 1) -> 1] // #[(1, 1) -> 2] -public function add(x: uint256, y: uint256) -> uint256 { +function add(x: uint256, y: uint256) public returns (uint256) { return Add.add(x, y); } ``` @@ -20,7 +20,7 @@ argument or result with the wrong type or arity is rejected while resolving the fixture, before any EVM call is made. The execution fixtures deliberately use only selector ABI types supported by the shared reference std. In particular, they do not expose primitive `word`. Direct ADTs and the -`calldata(array(T))` ADT surface use raw JSON vectors instead: their selectors +`calldata>` ADT surface use raw JSON vectors instead: their selectors are derived from `T`'s structural Generic representation, and algebraic/dynamic-array values are outside the inline directive value grammar. @@ -32,10 +32,10 @@ normal call directive on a later public method to assert the persisted state: ```solcore // #[send(41)] -public function set(value: uint256) { stored = value; } +function set(value: uint256) public { stored = value; } // #[() -> 41] -public function readAfterSend() -> uint256 { return stored; } +function readAfterSend() public returns (uint256) { return stored; } ``` The outer parentheses delimit the argument or result list; another pair is @@ -44,7 +44,7 @@ double parentheses: ```solcore // #[((7, 1)) -> (7, 1)] -public function echo(point: (uint256, uint256)) -> (uint256, uint256) { +function echo(point: (uint256, uint256)) public returns (uint256, uint256) { return point; } ``` @@ -54,11 +54,11 @@ right-nested tuple representation also flattens a nested tuple used as one ABI parameter: the single argument `((uint256, uint256), uint256)` is written as `((7, 1, 9))` in a directive. By contrast, two parameters consisting of a pair and a scalar are written as `((7, 1), 9)`. The complete shared example is in -`composite-values/main.solc`. Normal comments are ignored, while a malformed +`composite-values/main.sol`. Normal comments are ignored, while a malformed comment beginning with `#[` is an error. For ABI shapes that the compiler metadata cannot describe yet, a fixture may -instead place an upstream-compatible `main.json` next to `main.solc`. The JSON +instead place an upstream-compatible `main.json` next to `main.sol`. The JSON supplies complete calldata, call value, expected raw returndata or revert payload, the contract name, and optionally the upstream EVM-version metadata. Within each compiled backend/codegen variant, every entry is executed once as @@ -70,10 +70,11 @@ on a fresh, dedicated Osaka Anvil instance. This keeps the byte-exact upstream JSON intact while using the one runtime supported consistently by both backend pipelines. -The 2f372bde snapshot contains 51 executable source/vector pairs, all vendored -byte-for-byte here. Its remaining `template.json` is a source-less placeholder -used by the upstream generator, not an executable fixture. Every original -`evmVersion` field, or its omission, remains preserved byte-for-byte. +The 2f372bde snapshot contains 51 executable source/vector pairs. Their Core +sources are syntax-migrated semantic ports; the adjacent JSON vectors retain +the original calldata, expected output, and `evmVersion` metadata. Its +remaining `template.json` is a source-less placeholder used by the upstream +generator, not an executable fixture. This is also the migration format for Solcore's dispatch fixtures with dynamic arrays or ADTs. For a non-recursive, compiler-derived nullary ADT `T`, the ABI @@ -84,12 +85,12 @@ uses the final Generic `SigString` (for example, `rt(sum(uint256,bytes))` or for a concrete parameterized ADT, but its `ContractDispatch.abiTypeOf` only handles `TyCon n []` and fails ABI JSON emission for that case. Rust intentionally extends the metadata surface with source spellings such as -`Point(uint256)`. +`Point`. This extension is supported only when every type argument, including an unused phantom argument, has the required ABI evidence. Finite nested instantiations are distinguished from definition-recursive representations. Recursive, manually represented, and same-named non-std array/location types are rejected -before backend execution, as is a `calldata(array(t))` handle nested anywhere +before backend execution, as is a `calldata>` handle nested anywhere inside an encoded ADT result. Each case is lowered by the selected backend, compiled to EVM creation diff --git a/tests/e2e/SimpleField/main.sol b/tests/e2e/SimpleField/main.sol index 448d3e49..227ce64c 100644 --- a/tests/e2e/SimpleField/main.sol +++ b/tests/e2e/SimpleField/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -7,12 +7,12 @@ pragma no-bounded-variable-condition ; contract Simple { myval : word ; - function getVal () -> word { + function getVal() returns (word) { return myval ; } // #[() -> 0] - public function run () -> uint256 { + function run() public returns (uint256) { return uint256(getVal()); } } diff --git a/tests/e2e/abi-address-array/main.sol b/tests/e2e/abi-address-array/main.sol index f7449701..fd7b92aa 100644 --- a/tests/e2e/abi-address-array/main.sol +++ b/tests/e2e/abi-address-array/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // calldata(array(address)) — a dynamic array of a STATIC value type. Unlike // bytes[] (dynamic elements, offset table), address is static, so elements sit @@ -12,12 +12,12 @@ contract AddressArr { constructor() {} // The i-th address. - public function at(items : calldata(array(address)), i : uint256) -> address { + function at(items: calldata>, i: uint256) public returns (address) { return items[i]; } // Number of elements. - public function count(items : calldata(array(address))) -> uint256 { + function count(items: calldata>) public returns (uint256) { return items.length(); } } diff --git a/tests/e2e/abi-array-sum/main.sol b/tests/e2e/abi-array-sum/main.sol index c6a790f6..49cdd1a8 100644 --- a/tests/e2e/abi-array-sum/main.sol +++ b/tests/e2e/abi-array-sum/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // ABI-decoding a dynamic array whose element is a sum-typed ADT. // @@ -10,18 +10,18 @@ import std.ABIGeneric.{*}; // wire element is therefore two words — a tag word then the payload — which the // word-per-slot memory(DynArray(...)) representation cannot hold. The array is // instead decoded lazily from calldata: the parameter becomes a -// `calldata(array(Operation))` handle to the length word, and elements are +// `calldata>` handle to the length word, and elements are // decoded on demand. Indexing uses the ordinary `ops[i]` sugar (calldata-array -// RValueIdxAccess) and `ops.length()` uses the Length-class UFCS — the same +// RValueIdxAccess) and `ops.length()` uses the Length-trait UFCS — the same // surface syntax as storage arrays. `ops` is a parameter, so this relies on // value-receiver UFCS (NameResolution), not just the field-receiver form. -data Operation = Approve(uint256) | Reject(uint256); +enum Operation { Approve(uint256), Reject(uint256) } contract Batch { constructor() {} // Number of operations in the array. - public function count(ops : calldata(array(Operation))) -> uint256 { + function count(ops: calldata>) public returns (uint256) { return ops.length(); } @@ -29,20 +29,28 @@ contract Batch { // 32 for Reject. Deliberately not 0/1 — those coincide with the on-wire sum // tag (inl=0, inr=1), so non-trivial values prove the match actually // discriminates the constructor rather than echoing the raw tag word. - public function tagOf(ops : calldata(array(Operation)), i : uint256) -> uint256 { + function tagOf(ops: calldata>, i: uint256) public returns (uint256) { let op : Operation = ops[i]; - match op { - | Operation.Approve(_) => return uint256(16); - | Operation.Reject(_) => return uint256(32); - } + match (op) { +case Operation.Approve(_) { +return uint256(16); +} +case Operation.Reject(_) { +return uint256(32); +} +} } // Payload (the uint256) of element i, regardless of constructor. - public function amountOf(ops : calldata(array(Operation)), i : uint256) -> uint256 { + function amountOf(ops: calldata>, i: uint256) public returns (uint256) { let op : Operation = ops[i]; - match op { - | Operation.Approve(v) => return v; - | Operation.Reject(v) => return v; - } + match (op) { +case Operation.Approve(v) { +return v; +} +case Operation.Reject(v) { +return v; +} +} } } diff --git a/tests/e2e/abi-batch-adt/main.sol b/tests/e2e/abi-batch-adt/main.sol index 74390c27..d704cb67 100644 --- a/tests/e2e/abi-batch-adt/main.sol +++ b/tests/e2e/abi-batch-adt/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Complex nested-ADT ABI decode over a calldata dynamic array. The element is a // three-level algebraic type built from sums *and* products: @@ -27,24 +27,32 @@ import std.ABIGeneric.{*}; // real calldata) needs the exact solcore-generated selector for the nested-ADT // signature, which has to be captured from a local sol-core run. -data Operation = AddSigner(address) | RemoveSigner(address); -data Signature = ECDSA(bytes32, bytes32) | Contract(address); -data Batch = Queue(Operation, Signature) | Execute(uint256, memory(bytes)); +enum Operation { AddSigner(address), RemoveSigner(address) } +enum Signature { ECDSA(bytes32, bytes32), Contract(address) } +enum Batch { Queue(Operation, Signature), Execute(uint256, memory) } // Address added by an AddSigner op (address(0) for a RemoveSigner). -function addedSigner(op : Operation) -> address { - match op { - | Operation.AddSigner(a) => return a; - | Operation.RemoveSigner(_) => return address(0); - } +function addedSigner(op: Operation) returns (address) { + match (op) { +case Operation.AddSigner(a) { +return a; +} +case Operation.RemoveSigner(_) { +return address(0); +} +} } // Verifying contract address of a Contract signature (address(0) for ECDSA). -function contractVerifier(sig : Signature) -> address { - match sig { - | Signature.Contract(a) => return a; - | Signature.ECDSA(_, _) => return address(0); - } +function contractVerifier(sig: Signature) returns (address) { + match (sig) { +case Signature.Contract(a) { +return a; +} +case Signature.ECDSA(_, _) { +return address(0); +} +} } contract BatchDecoder { @@ -52,22 +60,30 @@ contract BatchDecoder { // From a Queue(AddSigner(a), Contract(c)) element, return (a, c): the signer // being added and the contract that verifies the queued action. - public function queueSigner(items : calldata(array(Batch)), i : uint256) -> (address, address) { + function queueSigner(items: calldata>, i: uint256) public returns (address, address) { let b : Batch = items[i]; - match b { - | Batch.Queue(op, sig) => return (addedSigner(op), contractVerifier(sig)); - | Batch.Execute(_, _) => return (address(0), address(0)); - } + match (b) { +case Batch.Queue(op, sig) { +return (addedSigner(op), contractVerifier(sig)); +} +case Batch.Execute(_, _) { +return (address(0), address(0)); +} +} } // The payload bytes carried by an Execute element. - public function execPayload(items : calldata(array(Batch)), i : uint256) -> memory(bytes) { + function execPayload(items: calldata>, i: uint256) public returns (memory) { let b : Batch = items[i]; - let out : memory(bytes); - match b { - | Batch.Execute(_, payload) => out = payload; - | Batch.Queue(_, _) => revertEmpty(); - } + let out : memory; + match (b) { +case Batch.Execute(_, payload) { +out = payload; +} +case Batch.Queue(_, _) { +revertEmpty(); +} +} return out; } } diff --git a/tests/e2e/abi-boundaries/main.sol b/tests/e2e/abi-boundaries/main.sol index 17ea2b95..42562c8c 100644 --- a/tests/e2e/abi-boundaries/main.sol +++ b/tests/e2e/abi-boundaries/main.sol @@ -1,26 +1,26 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract AbiBoundaries { // #[(0) -> 0] // #[(0x8000000000000000000000000000000000000000000000000000000000000000) -> 0x8000000000000000000000000000000000000000000000000000000000000000] // #[(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff] - public function echoUint(value: uint256) -> uint256 { + function echoUint(value: uint256) public returns (uint256) { return value; } // #[(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 1) -> 0] - public function wrappingAdd(lhs: uint256, rhs: uint256) -> uint256 { + function wrappingAdd(lhs: uint256, rhs: uint256) public returns (uint256) { return lhs + rhs; } // #[(0xffffffffffffffffffffffffffffffffffffffff) -> 0xffffffffffffffffffffffffffffffffffffffff] - public function echoAddress(value: address) -> address { + function echoAddress(value: address) public returns (address) { return value; } // #[(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff] - public function echoBytes32(value: bytes32) -> bytes32 { + function echoBytes32(value: bytes32) public returns (bytes32) { return value; } } diff --git a/tests/e2e/abi-bytes-array/main.sol b/tests/e2e/abi-bytes-array/main.sol index 694c8f75..e84854d1 100644 --- a/tests/e2e/abi-bytes-array/main.sol +++ b/tests/e2e/abi-bytes-array/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // calldata(array(bytes)) — a dynamic array whose element is itself dynamic, the // canonical Solidity `bytes[]`. After the length word the region is a table of @@ -14,12 +14,12 @@ contract BytesArray { constructor() {} // The i-th bytes element. - public function at(items : calldata(array(memory(bytes))), i : uint256) -> memory(bytes) { + function at(items: calldata>>, i: uint256) public returns (memory) { return items[i]; } // Number of elements. - public function count(items : calldata(array(memory(bytes)))) -> uint256 { + function count(items: calldata>>) public returns (uint256) { return items.length(); } } diff --git a/tests/e2e/abi-dyn-sum-return/main.sol b/tests/e2e/abi-dyn-sum-return/main.sol index 1e7c9531..09c72fcc 100644 --- a/tests/e2e/abi-dyn-sum-return/main.sol +++ b/tests/e2e/abi-dyn-sum-return/main.sol @@ -1,12 +1,12 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Return a *dynamic sum by value* from a dispatched function — the case the // generic ABI encoder used to get wrong (it wrote only the top-level tag word, // collapsing the whole value to a single 0x00…0 head). The companion -// `abi_dyn_sum.solc` deliberately avoids this by returning `memory(bytes)` / +// `abi_dyn_sum.sol` deliberately avoids this by returning `memory(bytes)` / // individual words; here we exercise the fixed `sum(f,g):ABIEncode` head-offset // path head-on. // @@ -19,9 +19,9 @@ import std.ABIGeneric.{*}; // word, so a deeply nested variant encodes as nested offsets, not flat tags. // A static sum stays inline as [tag][branch] with no leading offset — its wire // form is unchanged by the fix. -data D2 = L(uint256) | R(memory(bytes)); -data D3 = X(uint256) | Y(uint256) | Z(memory(bytes)); -data S2 = P(uint256) | Q(uint256); +enum D2 { L(uint256), R(memory) } +enum D3 { X(uint256), Y(uint256), Z(memory) } +enum S2 { P(uint256), Q(uint256) } contract DynSumRet { constructor() {} @@ -29,39 +29,39 @@ contract DynSumRet { // ── shallow dynamic sum ──────────────────────────────────────────────── // inl branch (static uint256 payload) of a dynamic sum: still takes the // dynamic encode path (offset word + inline [tag][value] in the tail). - public function makeL(n : uint256) -> D2 { + function makeL(n: uint256) public returns (D2) { return D2.L(n); } // inr branch carrying a dynamic bytes payload: [off][1][off][len][data]. - public function makeR(b : memory(bytes)) -> D2 { + function makeR(b: memory) public returns (D2) { return D2.R(b); } // ── deeply right-nested dynamic sum ──────────────────────────────────── // outer inl: [off][0][value] - public function makeX(n : uint256) -> D3 { + function makeX(n: uint256) public returns (D3) { return D3.X(n); } // inr(inl …): two dynamic-sum levels, so two nested offsets: [off][1][off][0][value] - public function makeY(n : uint256) -> D3 { + function makeY(n: uint256) public returns (D3) { return D3.Y(n); } // inr(inr bytes): nested offsets down to the bytes leaf: // [off][1][off][1][off][len][data] - public function makeZ(b : memory(bytes)) -> D3 { + function makeZ(b: memory) public returns (D3) { return D3.Z(b); } // ── static sum control ───────────────────────────────────────────────── // Byte-identical to the pre-fix output: inline [tag][value], no offset word. - public function makeP(n : uint256) -> S2 { + function makeP(n: uint256) public returns (S2) { return S2.P(n); } - public function makeQ(n : uint256) -> S2 { + function makeQ(n: uint256) public returns (S2) { return S2.Q(n); } } diff --git a/tests/e2e/abi-dyn-sum/main.sol b/tests/e2e/abi-dyn-sum/main.sol index d1c0f66b..3c2c7fce 100644 --- a/tests/e2e/abi-dyn-sum/main.sol +++ b/tests/e2e/abi-dyn-sum/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Minimal dynamic sum in a calldata array — like abi_batch_adt but with NO // nested ADTs: the constructors carry primitive / bytes fields directly. This @@ -10,28 +10,36 @@ import std.ABIGeneric.{*}; // which abi_batch_adt also has and this test does not). // // DynSum : sum(uint256, bytes) -- dynamic (Blob carries memory(bytes)) -data DynSum = Small(uint256) | Blob(memory(bytes)); +enum DynSum { Small(uint256), Blob(memory) } contract DynSumArr { constructor() {} // The uint256 in a Small element (0 for a Blob). - public function smallOf(items : calldata(array(DynSum)), i : uint256) -> uint256 { + function smallOf(items: calldata>, i: uint256) public returns (uint256) { let d : DynSum = items[i]; - match d { - | DynSum.Small(x) => return x; - | DynSum.Blob(_) => return uint256(0); - } + match (d) { +case DynSum.Small(x) { +return x; +} +case DynSum.Blob(_) { +return uint256(0); +} +} } // The bytes payload of a Blob element. - public function blobOf(items : calldata(array(DynSum)), i : uint256) -> memory(bytes) { + function blobOf(items: calldata>, i: uint256) public returns (memory) { let d : DynSum = items[i]; - let out : memory(bytes); - match d { - | DynSum.Blob(b) => out = b; - | DynSum.Small(_) => revertEmpty(); - } + let out : memory; + match (d) { +case DynSum.Blob(b) { +out = b; +} +case DynSum.Small(_) { +revertEmpty(); +} +} return out; } } diff --git a/tests/e2e/abi-encode-adt/main.sol b/tests/e2e/abi-encode-adt/main.sol index 51621d85..eed61df3 100644 --- a/tests/e2e/abi-encode-adt/main.sol +++ b/tests/e2e/abi-encode-adt/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -9,7 +9,7 @@ pragma no-bounded-variable-condition ; // Direct tests for `abi_encode` over user-defined algebraic data types (ADTs). // // An ADT reaches `abi_encode` through its auto-derived `Generic` representation -// and the ABIGeneric bridges (std/ABIGeneric.solc): a product constructor +// and the ABIGeneric bridges (std/ABIGeneric.sol): a product constructor // represents as the primitive tuple of its fields, and a sum represents as the // binary `sum(f, g)` type (inl = first constructor, inr = second). Each method // encodes an ADT value and returns the `memory(bytes)` result, which the @@ -33,41 +33,41 @@ pragma no-bounded-variable-condition ; // tail — even the static (Empty) branch keeps that offset wrapper. // static product -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } // static sum -data Choice = First(uint256) | Second(uint256); +enum Choice { First(uint256), Second(uint256) } // dynamic sum (the Text branch carries a dynamic string) -data StrBox = Empty(uint256) | Text(memory(string)); +enum StrBox { Empty(uint256), Text(memory) } contract AbiEncodeAdt { constructor() {} // Static product: encodes as the tuple (a, b) — two inline head words. - public function encPoint(a : uint256, b : uint256) -> memory(bytes) { + function encPoint(a: uint256, b: uint256) public returns (memory) { return abi_encode(Point(a, b)); } // Static sum, left constructor: [tag = 0][x]. - public function encFirst(x : uint256) -> memory(bytes) { + function encFirst(x: uint256) public returns (memory) { return abi_encode(Choice.First(x)); } // Static sum, right constructor: [tag = 1][x]. - public function encSecond(x : uint256) -> memory(bytes) { + function encSecond(x: uint256) public returns (memory) { return abi_encode(Choice.Second(x)); } // Dynamic sum, static branch: still offset-wrapped — [0x20] -> [tag = 0][n]. - public function encEmpty(n : uint256) -> memory(bytes) { + function encEmpty(n: uint256) public returns (memory) { return abi_encode(StrBox.Empty(n)); } // Dynamic sum, dynamic branch: [0x20] -> [tag = 1][branch offset][len][data]. - public function encText() -> memory(bytes) { + function encText() public returns (memory) { let raw : string = "abc"; - let s : memory(string) = Str.fromString(raw); + let s : memory = Str.fromString(raw); return abi_encode(StrBox.Text(s)); } } diff --git a/tests/e2e/abi-encode-types/main.sol b/tests/e2e/abi-encode-types/main.sol index 0628338e..df93783e 100644 --- a/tests/e2e/abi-encode-types/main.sol +++ b/tests/e2e/abi-encode-types/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; -// Direct tests for the top-level `abi_encode` function (std.solc) across both +// Direct tests for the top-level `abi_encode` function (std.sol) across both // static and dynamic types. // // Each method encodes a value with `abi_encode` and returns the resulting @@ -26,37 +26,37 @@ contract AbiEncodeTypes { // --- static --- // uint256 is written directly into the head as one word. - public function encUint(x : uint256) -> memory(bytes) { + function encUint(x: uint256) public returns (memory) { return abi_encode(x); } // bool encodes as a single 0/1 word. - public function encBool(x : bool) -> memory(bytes) { + function encBool(x: bool) public returns (memory) { return abi_encode(x); } // address is left-padded into a single word. - public function encAddr(x : address) -> memory(bytes) { + function encAddr(x: address) public returns (memory) { return abi_encode(x); } // A fully static tuple has both words in the head, with no offset. - public function encPair(a : uint256, b : uint256) -> memory(bytes) { + function encPair(a: uint256, b: uint256) public returns (memory) { return abi_encode((a, b)); } // --- dynamic --- // A string gets a head offset word pointing at a `[len][data]` tail. - public function encStr() -> memory(bytes) { + function encStr() public returns (memory) { let raw : string = "abc"; - let s : memory(string) = Str.fromString(raw); + let s : memory = Str.fromString(raw); return abi_encode(s); } // A dynamic array gets a head offset word pointing at a `[len][elems]` tail. - public function encArr() -> memory(bytes) { - let a : memory(DynArray(uint256)) = [11, 22, 33]; + function encArr() public returns (memory) { + let a : memory> = [11, 22, 33]; return abi_encode(a); } } diff --git a/tests/e2e/abi-sum-roundtrip/main.sol b/tests/e2e/abi-sum-roundtrip/main.sol index dc13caf6..074225be 100644 --- a/tests/e2e/abi-sum-roundtrip/main.sol +++ b/tests/e2e/abi-sum-roundtrip/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; // Roundtrip tests for sum ABI coding: `roundtrip(x) -> x` makes the dispatcher // DECODE the argument from calldata and then ENCODE it straight back into the @@ -16,26 +16,26 @@ import std.ABIGeneric.{*}; // The dynamic direction is what the sum(f,g):ABIEncode fix restores: before it, // encoding a decoded dynamic sum dropped everything but the tag, so the return // bytes could not match the input. -data D2 = L(uint256) | R(memory(bytes)); // dynamic (shallow) -data D3 = X(uint256) | Y(uint256) | Z(memory(bytes)); // dynamic (deeply nested) -data S2 = P(uint256) | Q(uint256); // static +enum D2 { L(uint256), R(memory) } // dynamic (shallow) +enum D3 { X(uint256), Y(uint256), Z(memory) } // dynamic (deeply nested) +enum S2 { P(uint256), Q(uint256) } // static contract SumRoundtrip { constructor() {} // dynamic, shallow: decode a sum(uint256, bytes) then re-encode it. - public function rtD2(x : D2) -> D2 { + function rtD2(x: D2) public returns (D2) { return x; } // dynamic, deeply right-nested: each nested dynamic level round-trips its own // offset word. - public function rtD3(x : D3) -> D3 { + function rtD3(x: D3) public returns (D3) { return x; } // static control: inline layout must round-trip unchanged. - public function rtS2(x : S2) -> S2 { + function rtS2(x: S2) public returns (S2) { return x; } } diff --git a/tests/e2e/arithmetic/main.sol b/tests/e2e/arithmetic/main.sol index 67356531..ec89c2c1 100644 --- a/tests/e2e/arithmetic/main.sol +++ b/tests/e2e/arithmetic/main.sol @@ -1,18 +1,18 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Arithmetic { constructor() {} // #[(0, 1) -> 1] // #[(1, 1) -> 2] - public function add(x: uint256, y: uint256) -> uint256 { + function add(x: uint256, y: uint256) public returns (uint256) { return Add.add(x, y); } // #[(10, 2) -> 8] // #[(2, 0) -> 2] - public function sub(x: uint256, y: uint256) -> uint256 { + function sub(x: uint256, y: uint256) public returns (uint256) { return Sub.sub(x, y); } } diff --git a/tests/e2e/array-copy/main.sol b/tests/e2e/array-copy/main.sol index 6d359c79..9b275758 100644 --- a/tests/e2e/array-copy/main.sol +++ b/tests/e2e/array-copy/main.sol @@ -1,46 +1,46 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Whole-array assignment `a = b` follows Solidity: it is a deep copy, not an // alias; assigning an array to itself is a no-op; and a copy that shrinks the // destination clears the slots it abandons, so regrowing yields zeros. contract ArrayCopy { - a : array(uint256); - b : array(uint256); + a : array; + b : array; constructor() {} - public function pushA(v : uint256) -> () { + function pushA(v: uint256) public { ArrayPush.push(a, v); } - public function pushB(v : uint256) -> () { + function pushB(v: uint256) public { ArrayPush.push(b, v); } // a = b - public function copyBintoA() -> () { + function copyBintoA() public { a = b; } // a = a (must be a no-op, not a self-clobbering copy) - public function copyAintoA() -> () { + function copyAintoA() public { a = a; } - public function setB(i : uint256, v : uint256) -> () { + function setB(i: uint256, v: uint256) public { b[i] = v; } - public function growA(n : uint256) -> () { + function growA(n: uint256) public { Array.setLength(a, n); } - public function lenA() -> uint256 { + function lenA() public returns (uint256) { return Length.length(a); } - public function getA(i : uint256) -> uint256 { + function getA(i: uint256) public returns (uint256) { return a[i]; } } diff --git a/tests/e2e/array-literals/main.sol b/tests/e2e/array-literals/main.sol index db34347f..86c450e3 100644 --- a/tests/e2e/array-literals/main.sol +++ b/tests/e2e/array-literals/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Array literals, end to end. // @@ -7,7 +7,7 @@ import std.dispatch.{*}; // Solidity's memory -> storage copy: it resizes the field and clears the // abandoned tail, so shrinking must not leave old elements reachable. contract ArrayLit { - xs : array(uint256); + xs : array; constructor() {} @@ -15,13 +15,13 @@ contract ArrayLit { // Reads back an element of a memory literal. Element 0 must be the first // element, not the length word stored ahead of it. - public function memAt(i : uint256) -> uint256 { - let m : memory(DynArray(uint256)) = [11, 22, 33]; + function memAt(i: uint256) public returns (uint256) { + let m : memory> = [11, 22, 33]; return m[i]; } - public function memSum() -> uint256 { - let m : memory(DynArray(uint256)) = [1, 2, 3, 4]; + function memSum() public returns (uint256) { + let m : memory> = [1, 2, 3, 4]; let acc : uint256 = uint256(0); let i : uint256; for (i = uint256(0); i < uint256(4); i = i + uint256(1)) { @@ -31,41 +31,41 @@ contract ArrayLit { } // Nested literal: the element type is itself a memory array. - public function nested() -> uint256 { - let g : memory(DynArray(memory(DynArray(uint256)))) = [[1, 2], [3, 4]]; - let row : memory(DynArray(uint256)) = g[uint256(1)]; + function nested() public returns (uint256) { + let g : memory>>> = [[1, 2], [3, 4]]; + let row : memory> = g[uint256(1)]; return row[uint256(0)]; } // --- storage literals --- - public function setThree() -> () { + function setThree() public { xs = [10, 20, 30]; } - public function setFive() -> () { + function setFive() public { xs = [1, 2, 3, 4, 5]; } - public function setTwo() -> () { + function setTwo() public { xs = [7, 8]; } - public function clear() -> () { + function clear() public { xs = []; } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(xs); } - public function get(i : uint256) -> uint256 { + function get(i: uint256) public returns (uint256) { return xs[i]; } // Grow the array back without writing elements. Anything the shrink abandoned // must read as zero, not as the old value. - public function grow(n : uint256) -> () { + function grow(n: uint256) public { Array.setLength(xs, n); } } diff --git a/tests/e2e/array-nested/main.sol b/tests/e2e/array-nested/main.sol index 81662976..3fe2d26b 100644 --- a/tests/e2e/array-nested/main.sol +++ b/tests/e2e/array-nested/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Nested storage arrays and aliasing, on the EVM. // @@ -10,48 +10,48 @@ import std.dispatch.{*}; // Binding an array field to a local is an alias (Solidity's `T[] storage p`), not // a copy: mutating through the local must be visible through the field. contract NestedArray { - grid : array(array(uint256)); - flat : array(uint256); + grid : array>; + flat : array; constructor() {} - public function growOuter(n : uint256) -> () { + function growOuter(n: uint256) public { Array.setLength(grid, n); } // grid[i].push(v) -- the inner handle comes straight out of the index - public function pushInner(i : uint256, v : uint256) -> () { + function pushInner(i: uint256, v: uint256) public { ArrayPush.push(grid[i], v); } - public function innerLen(i : uint256) -> uint256 { + function innerLen(i: uint256) public returns (uint256) { return Length.length(grid[i]); } - public function get2(i : uint256, j : uint256) -> uint256 { + function get2(i: uint256, j: uint256) public returns (uint256) { return grid[i][j]; } - public function set2(i : uint256, j : uint256, v : uint256) -> () { + function set2(i: uint256, j: uint256, v: uint256) public { grid[i][j] = v; } // Mutate `flat` through a local alias; the field must observe it. - public function aliasPush(v : uint256) -> () { - let p : storage(array(uint256)) = flat; + function aliasPush(v: uint256) public { + let p : storage> = flat; ArrayPush.push(p, v); } - public function aliasSet(i : uint256, v : uint256) -> () { - let p : storage(array(uint256)) = flat; + function aliasSet(i: uint256, v: uint256) public { + let p : storage> = flat; p[i] = v; } - public function flatLen() -> uint256 { + function flatLen() public returns (uint256) { return Length.length(flat); } - public function getFlat(i : uint256) -> uint256 { + function getFlat(i: uint256) public returns (uint256) { return flat[i]; } } diff --git a/tests/e2e/array-ops/main.sol b/tests/e2e/array-ops/main.sol index 5a162dbc..29347bfd 100644 --- a/tests/e2e/array-ops/main.sol +++ b/tests/e2e/array-ops/main.sol @@ -1,33 +1,33 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage-array primitives end to end: push / pop / length / indexed read, // the two revert paths (index out of range, pop on empty), and the guarantee // that abandoned slots are zeroed -- so regrowing an array never resurrects the // values that `pop` or a shrinking `setLength` dropped. contract ArrayOps { - xs : array(uint256); + xs : array; constructor() {} // NOTE: not named `add` -- that collides with the Yul builtin of the same name. - public function pushVal(v : uint256) -> () { + function pushVal(v: uint256) public { ArrayPush.push(xs, v); } - public function popArr() -> () { + function popArr() public { Array.pop(xs); } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(xs); } - public function get(i : uint256) -> uint256 { + function get(i: uint256) public returns (uint256) { return xs[i]; } - public function grow(n : uint256) -> () { + function grow(n: uint256) public { Array.setLength(xs, n); } } diff --git a/tests/e2e/array-string/main.sol b/tests/e2e/array-string/main.sol index 6bdac8f3..d66564db 100644 --- a/tests/e2e/array-string/main.sol +++ b/tests/e2e/array-string/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage arrays of a *dynamic* element type. `push` stores a `memory(string)` // through `storage(string):CanStore(memory(string))`, `arr[i]` reads one back, @@ -8,37 +8,37 @@ import std.dispatch.{*}; // Both the short (<32 bytes, inline) and long (>=32 bytes, keccak tail) string // encodings are exercised. contract ArrayString { - names : array(string); - backup : array(string); + names : array; + backup : array; constructor() {} - public function pushName(s : memory(string)) -> () { + function pushName(s: memory) public { ArrayPush.push(names, s); } - public function setName(i : uint256, s : memory(string)) -> () { + function setName(i: uint256, s: memory) public { names[i] = s; } - public function getName(i : uint256) -> memory(string) { + function getName(i: uint256) public returns (memory) { return names[i]; } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(names); } // backup = names - public function saveBackup() -> () { + function saveBackup() public { backup = names; } - public function getBackup(i : uint256) -> memory(string) { + function getBackup(i: uint256) public returns (memory) { return backup[i]; } - public function lenBackup() -> uint256 { + function lenBackup() public returns (uint256) { return Length.length(backup); } } diff --git a/tests/e2e/arraylit/main.sol b/tests/e2e/arraylit/main.sol index db34347f..86c450e3 100644 --- a/tests/e2e/arraylit/main.sol +++ b/tests/e2e/arraylit/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Array literals, end to end. // @@ -7,7 +7,7 @@ import std.dispatch.{*}; // Solidity's memory -> storage copy: it resizes the field and clears the // abandoned tail, so shrinking must not leave old elements reachable. contract ArrayLit { - xs : array(uint256); + xs : array; constructor() {} @@ -15,13 +15,13 @@ contract ArrayLit { // Reads back an element of a memory literal. Element 0 must be the first // element, not the length word stored ahead of it. - public function memAt(i : uint256) -> uint256 { - let m : memory(DynArray(uint256)) = [11, 22, 33]; + function memAt(i: uint256) public returns (uint256) { + let m : memory> = [11, 22, 33]; return m[i]; } - public function memSum() -> uint256 { - let m : memory(DynArray(uint256)) = [1, 2, 3, 4]; + function memSum() public returns (uint256) { + let m : memory> = [1, 2, 3, 4]; let acc : uint256 = uint256(0); let i : uint256; for (i = uint256(0); i < uint256(4); i = i + uint256(1)) { @@ -31,41 +31,41 @@ contract ArrayLit { } // Nested literal: the element type is itself a memory array. - public function nested() -> uint256 { - let g : memory(DynArray(memory(DynArray(uint256)))) = [[1, 2], [3, 4]]; - let row : memory(DynArray(uint256)) = g[uint256(1)]; + function nested() public returns (uint256) { + let g : memory>>> = [[1, 2], [3, 4]]; + let row : memory> = g[uint256(1)]; return row[uint256(0)]; } // --- storage literals --- - public function setThree() -> () { + function setThree() public { xs = [10, 20, 30]; } - public function setFive() -> () { + function setFive() public { xs = [1, 2, 3, 4, 5]; } - public function setTwo() -> () { + function setTwo() public { xs = [7, 8]; } - public function clear() -> () { + function clear() public { xs = []; } - public function len() -> uint256 { + function len() public returns (uint256) { return Length.length(xs); } - public function get(i : uint256) -> uint256 { + function get(i: uint256) public returns (uint256) { return xs[i]; } // Grow the array back without writing elements. Anything the shrink abandoned // must read as zero, not as the old value. - public function grow(n : uint256) -> () { + function grow(n: uint256) public { Array.setLength(xs, n); } } diff --git a/tests/e2e/asm-break-continue-leave/main.sol b/tests/e2e/asm-break-continue-leave/main.sol index 8b689c2d..6690d4c3 100644 --- a/tests/e2e/asm-break-continue-leave/main.sol +++ b/tests/e2e/asm-break-continue-leave/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // End-to-end (runs on evmone via the testrunner) check that Yul `break`, // `continue` and `leave` in inline assembly don't just parse, but actually @@ -12,7 +12,7 @@ contract C { // 2 + 3 + 4 + 5 = 14 // A miscompiled `continue` would also add 0 and 1 (=> 15); a broken `break` // would keep going and add 6..9 as well. - public function loopSum() -> uint256 { + function loopSum() public returns (uint256) { let result : word; assembly { result := 0 @@ -34,7 +34,7 @@ contract C { // clamp(2) = 102, clamp(9) = 3 => 102 + 3 = 105 // A broken `leave` would fall through and add 100 to the x > 3 branch too // (clamp(9) => 103 => total 205). - public function clampSum() -> uint256 { + function clampSum() public returns (uint256) { let result : word; assembly { function clamp(x) -> y { diff --git a/tests/e2e/assembly/main.sol b/tests/e2e/assembly/main.sol index a39e7cdd..dfa492ca 100644 --- a/tests/e2e/assembly/main.sol +++ b/tests/e2e/assembly/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor() {} @@ -7,7 +7,7 @@ contract C { // Exercises a Yul block that declares an uninitialized `let y`, assigns the // boolean literal `true` to it, and writes it back to the surrounding // `word` local `x`. `true` is the word `1`, so this returns uint256(1). - public function asmBool() -> uint256 { + function asmBool() public returns (uint256) { let x : word; assembly { let y diff --git a/tests/e2e/audit-constructor-suffix/main.sol b/tests/e2e/audit-constructor-suffix/main.sol index 8601bbc1..6a355c50 100644 --- a/tests/e2e/audit-constructor-suffix/main.sol +++ b/tests/e2e/audit-constructor-suffix/main.sol @@ -1,18 +1,22 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract ConstructorSuffix { - data T = A | B_A; + enum T { A, B_A } - function value(x:T) -> word { - match x { - | T.A => return 1; - | T.B_A => return 42; - } + function value(x: T) returns (word) { + match (x) { +case T.A { +return 1; +} +case T.B_A { +return 42; +} +} } // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { return uint256(value(T.B_A)); } } diff --git a/tests/e2e/audit-nested-pair-tail/main.sol b/tests/e2e/audit-nested-pair-tail/main.sol index 913a16a9..2d1c1587 100644 --- a/tests/e2e/audit-nested-pair-tail/main.sol +++ b/tests/e2e/audit-nested-pair-tail/main.sol @@ -1,21 +1,25 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -forall a b . function nestedSnd(p: (a, b)) -> b { - match p { - | (_, tail) => return tail; - } +function nestedSnd(p: (a, b)) returns (b) { + match (p) { +case (_, tail) { +return tail; +} +} } contract NestedPairTail { x: word; // #[() -> 42] - public function run() -> uint256 { + function run() public returns (uint256) { x = 42; let tail = nestedSnd((x, (x, x))); - match tail { - | (head, _) => return uint256(head); - } + match (tail) { +case (head, _) { +return uint256(head); +} +} } } diff --git a/tests/e2e/basic/main.sol b/tests/e2e/basic/main.sol index ac747855..4f4832c4 100644 --- a/tests/e2e/basic/main.sol +++ b/tests/e2e/basic/main.sol @@ -1,180 +1,184 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{address as address_}; +import * from std; +import * from std.dispatch; +import {address as address_} from std.opcodes; -function self() -> address { +function self() returns (address) { return address(address_()); } contract C { constructor() {} - public function nothing() -> () {} + function nothing() public {} // Re-enters this very contract via raw_call(address(this), ...). The payload // is the 4-byte selector of an existing entry point (something(), 0xa7a0d537), // built by left-aligning it in a bytes32 and truncating to 4 bytes. The inner // call succeeds, so raw_call reports ok == true and returns its returndata // (the abi-encoded uint256(1)). - public function callSelf() -> (bool, memory(bytes)) { + function callSelf() public returns (bool, memory) { let sel: bytes32 = bytes32(0xa7a0d53700000000000000000000000000000000000000000000000000000000); let payload = truncate(to_bytes(sel), 4); - match raw_call(self(), uint256(0), payload) { - | (ok, ret) => return (ok, ret); - } + match (raw_call(self(), uint256(0), payload)) { +case (ok, ret) { +return (ok, ret); +} +} } // Same shape, but the selector (0xdeadc0de) matches no entry point, so dispatch // reverts (there is no fallback). raw_call swallows the inner revert and reports // ok == false; this outer call itself still succeeds and returns the revert // returndata (the 4-byte NoFallback error selector). - public function callSelfInvalid() -> (bool, memory(bytes)) { + function callSelfInvalid() public returns (bool, memory) { let sel: bytes32 = bytes32(0xdeadc0de00000000000000000000000000000000000000000000000000000000); let payload = truncate(to_bytes(sel), 4); - match raw_call(self(), uint256(0), payload) { - | (ok, ret) => return (ok, ret); - } + match (raw_call(self(), uint256(0), payload)) { +case (ok, ret) { +return (ok, ret); +} +} } - public function something() -> (uint256) { + function something() public returns (uint256) { return uint256(1); } - public function add2(x : uint256, y : uint256) -> uint256 { + function add2(x: uint256, y: uint256) public returns (uint256) { return Add.add(x,y); } - public function add3(x : uint256, y : uint256, z : uint256) -> uint256 { + function add3(x: uint256, y: uint256, z: uint256) public returns (uint256) { return Add.add(z, Add.add(x,y)); } - public function addmod3(x : uint256, y : uint256, k : uint256) -> uint256 { + function addmod3(x: uint256, y: uint256, k: uint256) public returns (uint256) { return addmod(x, y, k); } - public function mulmod3(x : uint256, y : uint256, k : uint256) -> uint256 { + function mulmod3(x: uint256, y: uint256, k: uint256) public returns (uint256) { return mulmod(x, y, k); } - // Bitwise / modulo via the syntactic sugar only (no explicit class calls): + // Bitwise / modulo via the syntactic sugar only (no explicit trait calls): // `^` -> BitXor.bxor, `|` -> BitOr.bor, `&` -> BitAnd.band, `%` -> Mod.mod. - public function bxor2(x : uint256, y : uint256) -> uint256 { + function bxor2(x: uint256, y: uint256) public returns (uint256) { return x ^ y; } - public function bor2(x : uint256, y : uint256) -> uint256 { + function bor2(x: uint256, y: uint256) public returns (uint256) { return x | y; } - public function band2(x : uint256, y : uint256) -> uint256 { + function band2(x: uint256, y: uint256) public returns (uint256) { return x & y; } // Unary bitwise NOT via the sugar only: `~` -> BitNot.bnot. - public function bnot1(x : uint256) -> uint256 { + function bnot1(x: uint256) public returns (uint256) { return ~x; } - public function mod2(x : uint256, y : uint256) -> uint256 { + function mod2(x: uint256, y: uint256) public returns (uint256) { return x % y; } // `*` -> Mul.mul, `/` -> Div.div (completing the binary-operator sugar // set alongside bxor2 / bor2 / band2 / mod2). - public function mul2(x : uint256, y : uint256) -> uint256 { + function mul2(x: uint256, y: uint256) public returns (uint256) { return x * y; } - public function div2(x : uint256, y : uint256) -> uint256 { + function div2(x: uint256, y: uint256) public returns (uint256) { return x / y; } // Compound assignment statement sugar: each `acc op= y` desugars to // `acc := acc op y`, so these must agree with the binary operators above. - public function pluseq(x : uint256, y : uint256) -> uint256 { + function pluseq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc += y; return acc; } - public function minuseq(x : uint256, y : uint256) -> uint256 { + function minuseq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc -= y; return acc; } - public function timeseq(x : uint256, y : uint256) -> uint256 { + function timeseq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc *= y; return acc; } - public function divideeq(x : uint256, y : uint256) -> uint256 { + function divideeq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc /= y; return acc; } - public function modeq(x : uint256, y : uint256) -> uint256 { + function modeq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc %= y; return acc; } - public function bxoreq(x : uint256, y : uint256) -> uint256 { + function bxoreq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc ^= y; return acc; } - public function bandeq(x : uint256, y : uint256) -> uint256 { + function bandeq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc &= y; return acc; } - public function boreq(x : uint256, y : uint256) -> uint256 { + function boreq(x: uint256, y: uint256) public returns (uint256) { let acc : uint256 = x; acc |= y; return acc; } // In-place unary bitwise NOT: `acc ~=` desugars to `acc := ~acc`. - public function bnoteq(x : uint256) -> uint256 { + function bnoteq(x: uint256) public returns (uint256) { let acc : uint256 = x; acc ~=; return acc; } - public function id_bytes(b: memory(bytes)) -> memory(bytes) { + function id_bytes(b: memory) public returns (memory) { return b; } - public function id_string(b: memory(string)) -> memory(string) { + function id_string(b: memory) public returns (memory) { return b; } - public function id_bytes32(b: bytes32) -> bytes32 { + function id_bytes32(b: bytes32) public returns (bytes32) { return b; } - public function id_bytes4(b: bytes4) -> bytes4 { + function id_bytes4(b: bytes4) public returns (bytes4) { return b; } - public function id_address(a: address) -> address { + function id_address(a: address) public returns (address) { return a; } // Exercises bool:ABIDecode (argument) and bool:ABIEncode (return). - public function id_bool(b: bool) -> bool { + function id_bool(b: bool) public returns (bool) { return b; } - public function id_pair() -> (uint256, uint256) { + function id_pair() public returns (uint256, uint256) { return (uint256(7), uint256(11)); } - function hidden() -> (uint256) { + function hidden() returns (uint256) { return uint256(42); } } diff --git a/tests/e2e/composite-values/main.sol b/tests/e2e/composite-values/main.sol index 0fa3d938..6f1d04b9 100644 --- a/tests/e2e/composite-values/main.sol +++ b/tests/e2e/composite-values/main.sol @@ -1,22 +1,22 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract CompositeValues { constructor() {} // #[((7, 1), 9) -> (7, 1, 9)] - public function pack(point: (uint256, uint256), tag: uint256) -> ((uint256, uint256), uint256) { + function pack(point: (uint256, uint256), tag: uint256) public returns ((uint256, uint256), uint256) { return (point, tag); } // #[((7, 1, 9)) -> (7, 1, 9)] - public function unpack(tagged: ((uint256, uint256), uint256)) -> ((uint256, uint256), uint256) { + function unpack(tagged: ((uint256, uint256), uint256)) public returns ((uint256, uint256), uint256) { return tagged; } // #[((0, 0, 0)) -> (0, 0, 0)] // #[((42, 1, 99)) -> (42, 1, 99)] - public function echo(tagged: ((uint256, uint256), uint256)) -> ((uint256, uint256), uint256) { + function echo(tagged: ((uint256, uint256), uint256)) public returns ((uint256, uint256), uint256) { return tagged; } } diff --git a/tests/e2e/compound-assignment-class-method/main.sol b/tests/e2e/compound-assignment-class-method/main.sol index 1b724c1e..5ebaef84 100644 --- a/tests/e2e/compound-assignment-class-method/main.sol +++ b/tests/e2e/compound-assignment-class-method/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data Choice = Choice(uint256); +enum Choice { Choice(uint256) } -instance Choice:Add { - function add(l: Choice, r: Choice) -> Choice { +impl Add { + function add(l: Choice, r: Choice) returns (Choice) { return r; } } @@ -14,11 +14,13 @@ contract CompoundAssignmentClassMethod { // #[(3, 7) -> 7] // #[(11, 5) -> 5] - public function choose_right(x: uint256, y: uint256) -> uint256 { + function choose_right(x: uint256, y: uint256) public returns (uint256) { let result: Choice = Choice(x); result += Choice(y); - match result { - | Choice(value) => return value; - } + match (result) { +case Choice(value) { +return value; +} +} } } diff --git a/tests/e2e/concat/main.sol b/tests/e2e/concat/main.sol index 4d0b59bf..ce5ac428 100644 --- a/tests/e2e/concat/main.sol +++ b/tests/e2e/concat/main.sol @@ -1,42 +1,42 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { constructor() {} - public function concat_b32_b32(a: bytes32, b: bytes32) -> memory(bytes) { + function concat_b32_b32(a: bytes32, b: bytes32) public returns (memory) { return concat(a, b); } - public function concat_b32_bytes(a: bytes32, b: memory(bytes)) -> memory(bytes) { + function concat_b32_bytes(a: bytes32, b: memory) public returns (memory) { return concat(a, b); } - public function concat_bytes_bytes(a: memory(bytes), b: memory(bytes)) -> memory(bytes) { + function concat_bytes_bytes(a: memory, b: memory) public returns (memory) { return concat(a, b); } - public function to_bytes_b32(a: bytes32) -> memory(bytes) { + function to_bytes_b32(a: bytes32) public returns (memory) { return to_bytes(a); } - public function to_bytes_bytes(a: memory(bytes)) -> memory(bytes) { + function to_bytes_bytes(a: memory) public returns (memory) { return to_bytes(a); } - public function empty_area(n: uint256) -> memory(bytes) { + function empty_area(n: uint256) public returns (memory) { return to_bytes(empty(Typedef.rep(n))); } - public function concat_b32_empty(a: bytes32, n: uint256) -> memory(bytes) { + function concat_b32_empty(a: bytes32, n: uint256) public returns (memory) { return concat(a, empty(Typedef.rep(n))); } - public function concat_nested_b32(a: bytes32, b: bytes32, c: bytes32) -> memory(bytes) { + function concat_nested_b32(a: bytes32, b: bytes32, c: bytes32) public returns (memory) { return concat(a, concat(b, c)); } - public function concat_nested_empty(a: bytes32, n: uint256, c: bytes32) -> memory(bytes) { + function concat_nested_empty(a: bytes32, n: uint256, c: bytes32) public returns (memory) { return concat(a, concat(empty(Typedef.rep(n)), c)); } } diff --git a/tests/e2e/deposit/main.sol b/tests/e2e/deposit/main.sol index 9656d84d..7df57487 100644 --- a/tests/e2e/deposit/main.sol +++ b/tests/e2e/deposit/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{callvalue}; +import * from std; +import * from std.dispatch; +import {callvalue} from std.opcodes; // TODO: Should use uint64. // Assumes 64-bit input. -function to_little_endian_64(v: uint256) -> memory(bytes) { +function to_little_endian_64(v: uint256) returns (memory) { let res: word = allocate_memory(32 + 8); let value: word = Typedef.rep(v); assembly { @@ -23,11 +23,11 @@ function to_little_endian_64(v: uint256) -> memory(bytes) { // No constants are supported yet, using this as a workaround. // Defining variables outside of contract/function is not supported. -function DEPOSIT_CONTRACT_TREE_DEPTH() -> uint256 { +function DEPOSIT_CONTRACT_TREE_DEPTH() returns (uint256) { return 32; } -function MAX_DEPOSIT_COUNT() -> uint256 { +function MAX_DEPOSIT_COUNT() returns (uint256) { // uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1; // TODO: Could use Bounded(uint32).maxVal() return 0xFFFFFFFF; @@ -36,8 +36,8 @@ function MAX_DEPOSIT_COUNT() -> uint256 { contract DepositContract { deposit_count : uint256; // TODO: use fixed-size arrays of DEPOSIT_CONTRACT_TREE_DEPTH() length - branch : array(bytes32); - zero_hashes : array(bytes32); + branch : array; + zero_hashes : array; constructor() { // Dynamic storage arrays start empty and indexed access is bounds-checked, @@ -55,11 +55,11 @@ contract DepositContract { } // TODO: this is for testing only - public function get_zero_hash(index: uint256) -> bytes32 { + function get_zero_hash(index: uint256) public returns (bytes32) { return zero_hashes[index]; } - public function get_deposit_root() -> bytes32 { + function get_deposit_root() public returns (bytes32) { let node: bytes32; let size = deposit_count; for (let height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH(); height += 1) { @@ -79,13 +79,13 @@ contract DepositContract { )); } - public function get_deposit_count() -> memory(bytes) { + function get_deposit_count() public returns (memory) { return to_little_endian_64(deposit_count); } // TODO: once string literals are properly supported, change errors to messages // matching the deposit contract, full 100% identical behaviour. - public payable function deposit(pubkey: memory(bytes), withdrawal_credentials: memory(bytes), signature: memory(bytes), deposit_data_root: bytes32) -> () { + function deposit(pubkey: memory, withdrawal_credentials: memory, signature: memory, deposit_data_root: bytes32) public payable { // Extended ABI length checks since dynamic types are used. require(MemorySize.len(pubkey) == 48, Error(0x9ca717ed)); // InvalidPubkeyLength() require(MemorySize.len(withdrawal_credentials) == 32, Error(0x3debbf1e)); // InvalidWithdrawalCredentialsLength() @@ -101,7 +101,7 @@ contract DepositContract { // <= type(uint64).max require(deposit_amount <= 0xffffffffffffffff, Error(0x2aa66734)); // DepositValueTooHigh() - let amount: memory(bytes) = to_little_endian_64(uint256(deposit_amount)); + let amount: memory = to_little_endian_64(uint256(deposit_amount)); // TODO: emit DepositEvent /* event DepositEvent( @@ -159,7 +159,7 @@ contract DepositContract { assert(false); } - public function supportsInterface(interfaceId: bytes4) -> bool { + function supportsInterface(interfaceId: bytes4) public returns (bool) { unimplemented(); return false; } diff --git a/tests/e2e/derive-class/main.sol b/tests/e2e/derive-class/main.sol index 322fb699..6351c656 100644 --- a/tests/e2e/derive-class/main.sol +++ b/tests/e2e/derive-class/main.sol @@ -1,60 +1,76 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; -forall a . class a:CloneLike { - function clone(x : a) -> a; +trait CloneLike { + function clone(x: a) returns (a) ; } -instance uint256:CloneLike { - function clone(x : uint256) -> uint256 { return x; } +impl CloneLike { + function clone(x: uint256) returns (uint256) { return x; } } contract DeriveClass { #[derive(Eq, Ord)] - data Color = Red | Green | Blue; + enum Color { Red, Green, Blue } #[derive(Eq, Ord)] - data Point = Point(uint256, uint256); + enum Point { Point(uint256, uint256) } #[derive(CloneLike)] - data Box = Box(uint256); + enum Box { Box(uint256) } constructor() {} // #[() -> 1] - public function eqRedRed() -> uint256 { - match Eq.eq(Color.Red, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedRed() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // #[() -> 0] - public function eqRedBlue() -> uint256 { - match Eq.eq(Color.Red, Color.Blue) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedBlue() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Blue)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // #[() -> 1] - public function gtGreenRed() -> uint256 { - match Ord.gt(Color.Green, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtGreenRed() public returns (uint256) { + match (Ord.gt(Color.Green, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // #[() -> 0] - public function gtRedGreen() -> uint256 { - match Ord.gt(Color.Red, Color.Green) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtRedGreen() public returns (uint256) { + match (Ord.gt(Color.Red, Color.Green)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // #[() -> 1] From 3443aead2c87e0c35262fd4fd27f97e4dc123bef Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 093/110] Switch the compiler and fixtures to canonical syntax: tests Co-authored-by: Codex --- tests/e2e/derive-class/main.sol | 38 +++++--- tests/e2e/derive-contract-local/main.sol | 94 ++++++++++++-------- tests/e2e/derive-ord/main.sol | 94 ++++++++++++-------- tests/e2e/ecrecover/main.sol | 10 +-- tests/e2e/eip712/main.sol | 24 ++--- tests/e2e/erc7201-comptime/main.sol | 12 +-- tests/e2e/fallback/main.sol | 8 +- tests/e2e/forloops/main.sol | 22 ++--- tests/e2e/generic-product/main.sol | 46 ++++++---- tests/e2e/generic-sum/main.sol | 74 ++++++++------- tests/e2e/hashes/main.sol | 22 ++--- tests/e2e/ltimp/ltproxy.sol | 4 +- tests/e2e/ltimp/main.sol | 8 +- tests/e2e/memory/main.sol | 10 +-- tests/e2e/mini-erc20/main.sol | 38 ++++---- tests/e2e/neg/main.sol | 92 ++++++++++--------- tests/e2e/nonpayable-ctor/main.sol | 6 +- tests/e2e/ownable/main.sol | 10 +-- tests/e2e/p256verify/main.sol | 10 +-- tests/e2e/payable-ctor/main.sol | 8 +- tests/e2e/payable/main.sol | 10 +-- tests/e2e/persistent-storage/main.sol | 10 +-- tests/e2e/raw-vector/main.sol | 12 +-- tests/e2e/revert-raw/main.sol | 10 +-- tests/e2e/revert/main.sol | 6 +- tests/e2e/slices/main.sol | 26 +++--- tests/e2e/specialise-sum-of-product/main.sol | 73 +++++++++------ tests/e2e/std-word-correctness/main.sol | 10 +-- tests/e2e/storage-adt-abi/main.sol | 50 ++++++----- tests/e2e/storage-adt-bool/main.sol | 50 ++++++----- 30 files changed, 500 insertions(+), 387 deletions(-) diff --git a/tests/e2e/derive-class/main.sol b/tests/e2e/derive-class/main.sol index 6351c656..ffe94f85 100644 --- a/tests/e2e/derive-class/main.sol +++ b/tests/e2e/derive-class/main.sol @@ -74,26 +74,36 @@ return uint256(0); } // #[() -> 1] - public function eqPointSame() -> uint256 { - match Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2))) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqPointSame() public returns (uint256) { + match (Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // #[() -> 1] - public function gtPointLex() -> uint256 { - match Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50))) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtPointLex() public returns (uint256) { + match (Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // #[(42) -> 42] // #[(3735928559) -> 3735928559] - public function clonePayload(x : uint256) -> uint256 { - match CloneLike.clone(Box(x)) { - | Box(value) => return value; - } + function clonePayload(x: uint256) public returns (uint256) { + match (CloneLike.clone(Box(x))) { +case Box(value) { +return value; +} +} } } diff --git a/tests/e2e/derive-contract-local/main.sol b/tests/e2e/derive-contract-local/main.sol index c48fb312..6af4fa78 100644 --- a/tests/e2e/derive-contract-local/main.sol +++ b/tests/e2e/derive-contract-local/main.sol @@ -4,65 +4,89 @@ // - Color (a contract-local enum) exercises the () and sum(f, g) instances; // - Point (a contract-local product) exercises the pair (f, g) instance. -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; contract DeriveContractLocal { #[derive(Eq, Ord)] - data Color = Red | Green | Blue; + enum Color { Red, Green, Blue } #[derive(Eq, Ord)] - data Point = Point(uint256, uint256); + enum Point { Point(uint256, uint256) } constructor() {} // enum equality (reaches the () and sum universe instances) - public function eqRedRed() -> uint256 { - match Eq.eq(Color.Red, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedRed() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function eqRedBlue() -> uint256 { - match Eq.eq(Color.Red, Color.Blue) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedBlue() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Blue)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // enum ordering follows declaration order: Red < Green < Blue - public function gtGreenRed() -> uint256 { - match Ord.gt(Color.Green, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtGreenRed() public returns (uint256) { + match (Ord.gt(Color.Green, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function gtRedGreen() -> uint256 { - match Ord.gt(Color.Red, Color.Green) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtRedGreen() public returns (uint256) { + match (Ord.gt(Color.Red, Color.Green)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product equality (reaches the pair universe instance) - public function eqPointSame() -> uint256 { - match Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2))) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqPointSame() public returns (uint256) { + match (Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product ordering is lexicographic: the second field breaks the tie - public function gtPointLex() -> uint256 { - match Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50))) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtPointLex() public returns (uint256) { + match (Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } } diff --git a/tests/e2e/derive-ord/main.sol b/tests/e2e/derive-ord/main.sol index 6535e55e..dd801111 100644 --- a/tests/e2e/derive-ord/main.sol +++ b/tests/e2e/derive-ord/main.sol @@ -4,65 +4,89 @@ // - Color (an enum) exercises the unit () and sum(f, g) instances; // - Point (a product) exercises the pair (f, g) instance. -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; pragma no-patterson-condition; pragma no-bounded-variable-condition; #[derive(Eq, Ord)] -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } #[derive(Eq, Ord)] -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } contract DeriveOrd { constructor() {} // enum equality (reaches the () and sum universe instances) - public function eqRedRed() -> uint256 { - match Eq.eq(Color.Red, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedRed() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function eqRedBlue() -> uint256 { - match Eq.eq(Color.Red, Color.Blue) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqRedBlue() public returns (uint256) { + match (Eq.eq(Color.Red, Color.Blue)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // enum ordering follows declaration order: Red < Green < Blue - public function gtGreenRed() -> uint256 { - match Ord.gt(Color.Green, Color.Red) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtGreenRed() public returns (uint256) { + match (Ord.gt(Color.Green, Color.Red)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } - public function gtRedGreen() -> uint256 { - match Ord.gt(Color.Red, Color.Green) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtRedGreen() public returns (uint256) { + match (Ord.gt(Color.Red, Color.Green)) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product equality (reaches the pair universe instance) - public function eqPointSame() -> uint256 { - match Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2))) { - | true => return uint256(1); - | false => return uint256(0); - } + function eqPointSame() public returns (uint256) { + match (Eq.eq(Point(uint256(1), uint256(2)), Point(uint256(1), uint256(2)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } // product ordering is lexicographic: the second field breaks the tie - public function gtPointLex() -> uint256 { - match Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50))) { - | true => return uint256(1); - | false => return uint256(0); - } + function gtPointLex() public returns (uint256) { + match (Ord.gt(Point(uint256(1), uint256(100)), Point(uint256(1), uint256(50)))) { +case true { +return uint256(1); +} +case false { +return uint256(0); +} +} } } diff --git a/tests/e2e/ecrecover/main.sol b/tests/e2e/ecrecover/main.sol index e66122a1..412fec69 100644 --- a/tests/e2e/ecrecover/main.sol +++ b/tests/e2e/ecrecover/main.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract EcrecoverTest { - public function recover() -> address { + function recover() public returns (address) { let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(27); let r: bytes32 = bytes32(0xb3ba6dd3757d18f28736e84b1296af85362b7bdf4548710733c6325abf95311d); @@ -14,7 +14,7 @@ contract EcrecoverTest { // but recovers nothing, so it returns empty output and `res` stays 0. This // exercises the `ECRecoverFailed()` (0x4fbfae63) revert path. `v` and `s` // are kept well-formed so neither the malleability nor call-failed guards fire. - public function recoverFail() -> address { + function recoverFail() public returns (address) { let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(27); let r: bytes32 = bytes32(0x0); @@ -29,7 +29,7 @@ contract EcrecoverTest { // 0 and hit the `ECRecoverFailed()` (0x4fbfae63) revert path — without the // clear a stale non-zero word would be returned as a bogus address. `r` and // `s` are the well-formed values from `recover()` so only `v` is at fault. - public function recoverFailBadV() -> address { + function recoverFailBadV() public returns (address) { let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(1); let r: bytes32 = bytes32(0xb3ba6dd3757d18f28736e84b1296af85362b7bdf4548710733c6325abf95311d); diff --git a/tests/e2e/eip712/main.sol b/tests/e2e/eip712/main.sol index a292b5b9..0408655b 100644 --- a/tests/e2e/eip712/main.sol +++ b/tests/e2e/eip712/main.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; -import std.eip712.{*}; +import * from std; +import * from std.dispatch; +import * from std.eip712; // Canonical EIP-712 example from the specification // (https://eips.ethereum.org/EIPS/eip-712): a `Mail` sent from one `Person` to @@ -22,7 +22,7 @@ import std.eip712.{*}; // with `keccak256_`, exactly as in the slices example. // hashStruct(Person) = keccak256(PERSON_TYPEHASH ‖ keccak256(name) ‖ wallet) -function hashPerson(nameHash: bytes32, wallet: address) -> bytes32 { +function hashPerson(nameHash: bytes32, wallet: address) returns (bytes32) { let typeHash = bytes32(keccakLit("Person(string name,address wallet)")); return keccak256_( concat(typeHash, concat(nameHash, bytes32(Typedef.rep(wallet)))) @@ -32,7 +32,7 @@ function hashPerson(nameHash: bytes32, wallet: address) -> bytes32 { // hashStruct(Mail) = keccak256(MAIL_TYPEHASH ‖ hashStruct(from) ‖ hashStruct(to) ‖ keccak256(contents)) // The Mail type hash embeds the referenced Person type per the EIP-712 rule for // nested structs (referenced types are appended, sorted by name). -function hashMail(fromHash: bytes32, toHash: bytes32, contentsHash: bytes32) -> bytes32 { +function hashMail(fromHash: bytes32, toHash: bytes32, contentsHash: bytes32) returns (bytes32) { let typeHash = bytes32( keccakLit("Mail(Person from,Person to,string contents)Person(string name,address wallet)") ); @@ -43,7 +43,7 @@ function hashMail(fromHash: bytes32, toHash: bytes32, contentsHash: bytes32) -> // Domain separator for name "Ether Mail", version "1", chainId 1 and the fixed // verifying contract from the spec. Uses the std EIP712Domain helper. -function mailDomainSeparator() -> bytes32 { +function mailDomainSeparator() returns (bytes32) { return eip712DomainSeparator( bytes32(keccakLit("Ether Mail")), bytes32(keccakLit("1")), @@ -53,7 +53,7 @@ function mailDomainSeparator() -> bytes32 { } // hashStruct of the fixed Mail message. -function mailStructHash() -> bytes32 { +function mailStructHash() returns (bytes32) { let fromHash = hashPerson( bytes32(keccakLit("Cow")), address(0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826) @@ -66,7 +66,7 @@ function mailStructHash() -> bytes32 { return hashMail(fromHash, toHash, contentsHash); } -function mailDigest() -> bytes32 { +function mailDigest() returns (bytes32) { return eip712Digest(mailDomainSeparator(), mailStructHash()); } @@ -74,21 +74,21 @@ contract EIP712Mail { constructor() {} // Intermediate hashes, exposed so each EIP-712 layer can be asserted. - public function domainSeparator() -> bytes32 { + function domainSeparator() public returns (bytes32) { return mailDomainSeparator(); } - public function structHash() -> bytes32 { + function structHash() public returns (bytes32) { return mailStructHash(); } - public function digest() -> bytes32 { + function digest() public returns (bytes32) { return mailDigest(); } // Recovers the signer of the fixed Mail message using the published // signature. Returns the "Cow" wallet 0xCD2a3d…D826. - public function verify() -> address { + function verify() public returns (address) { let v: uint256 = uint256(28); let r: bytes32 = bytes32(0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d); let s: bytes32 = bytes32(0x07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b91562); diff --git a/tests/e2e/erc7201-comptime/main.sol b/tests/e2e/erc7201-comptime/main.sol index 931d11f0..39afcc9c 100644 --- a/tests/e2e/erc7201-comptime/main.sol +++ b/tests/e2e/erc7201-comptime/main.sol @@ -1,26 +1,26 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Erc7201Comptime { // keccak256(bytes32(0)) // #[() -> 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563] - public function keccakWord() -> bytes32 { + function keccakWord() public returns (bytes32) { return bytes32(keccakWordLit(0)); } // ERC-7201 namespace constants are folded at compile time. // #[() -> 0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500] - public function example() -> bytes32 { + function example() public returns (bytes32) { return erc7201("example.main"); } // #[() -> 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300] - public function ownable() -> bytes32 { + function ownable() public returns (bytes32) { return erc7201("openzeppelin.storage.Ownable"); } // #[() -> 0x4318a0031e4d2f411be9017543511db04d79cf580aaff6bae7539a4a49eacc00] - public function empty() -> bytes32 { + function empty() public returns (bytes32) { return erc7201(""); } } diff --git a/tests/e2e/fallback/main.sol b/tests/e2e/fallback/main.sol index 9bf22452..32bb5827 100644 --- a/tests/e2e/fallback/main.sol +++ b/tests/e2e/fallback/main.sol @@ -1,14 +1,14 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract WithFallback { constructor() {} - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } - fallback() -> () { + fallback() { revertLit("fallback-was-called"); } } diff --git a/tests/e2e/forloops/main.sol b/tests/e2e/forloops/main.sol index f2086ae4..23605b9d 100644 --- a/tests/e2e/forloops/main.sol +++ b/tests/e2e/forloops/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract C { counter : uint256; @@ -8,17 +8,17 @@ contract C { counter = uint256(0); } - function bump() -> uint256 { + function bump() returns (uint256) { counter = counter + uint256(1); return counter; } - public function getCounter() -> uint256 { + function getCounter() public returns (uint256) { return counter; } // Sum of 0..4 with early `break` at i == 5. - public function break_sum() -> uint256 { + function break_sum() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(0); i < uint256(10); i = i + uint256(1)) { if (i == uint256(5)) { @@ -32,7 +32,7 @@ contract C { // Sum of 5..9 using `continue` to skip the iterations where i < 5. // The post-statement (i = i + 1) must still run on `continue`, otherwise // the loop would never terminate. - public function continue_sum() -> uint256 { + function continue_sum() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(0); i < uint256(10); i = i + uint256(1)) { if (i < uint256(5)) { @@ -44,7 +44,7 @@ contract C { } // Empty initializer: `i` is declared/initialised outside the loop. - public function empty_init() -> uint256 { + function empty_init() public returns (uint256) { let i : uint256 = uint256(3); let s : uint256 = uint256(0); for (; i < uint256(7); i = i + uint256(1)) { @@ -54,7 +54,7 @@ contract C { } // Empty post-body: the increment is done in the loop body. - public function empty_post() -> uint256 { + function empty_post() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(0); i < uint256(4); ) { s = s + i; @@ -66,7 +66,7 @@ contract C { // Side effect in the condition: `bump()` increments storage on every // probe (including the failing one), so observing `counter` afterwards // proves the condition ran the expected number of times. - public function cond_side_effect() -> uint256 { + function cond_side_effect() public returns (uint256) { counter = uint256(0); for (let i : uint256 = uint256(0); bump() < uint256(5); i = i + uint256(1)) {} return counter; @@ -74,7 +74,7 @@ contract C { // Side effect in the post-body: `bump()` runs once per completed // iteration, so `counter` ends equal to the iteration count. - public function post_side_effect() -> uint256 { + function post_side_effect() public returns (uint256) { counter = uint256(0); for (let i : uint256 = uint256(0); i < uint256(3); bump()) { i = i + uint256(1); @@ -83,7 +83,7 @@ contract C { } // Nested `for` -- sum of i*j for i,j in 1..3. - public function double_loop() -> uint256 { + function double_loop() public returns (uint256) { let s : uint256 = uint256(0); for (let i : uint256 = uint256(1); i < uint256(4); i = i + uint256(1)) { for (let j : uint256 = uint256(1); j < uint256(4); j = j + uint256(1)) { diff --git a/tests/e2e/generic-product/main.sol b/tests/e2e/generic-product/main.sol index 5a2ce10f..5a6b0a72 100644 --- a/tests/e2e/generic-product/main.sol +++ b/tests/e2e/generic-product/main.sol @@ -1,21 +1,29 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-generic-instance-for Point; -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } -// Only requirement: Generic instance using the primitive pair type. +// Only requirement: a Generic impl using the primitive pair type. // rep = (uint256, uint256) — primitive Solcore pair -instance Point : Generic((uint256, uint256)) { - function from(p : Point) -> (uint256, uint256) { - match p { | Point(x, y) => return (x, y); } +impl Generic { + function from(p: Point) returns (uint256, uint256) { + match (p) { +case Point(x, y) { +return (x, y); +} +} } - function to(t : (uint256, uint256)) -> Point { - match t { | (x, y) => return Point(x, y); } + function to(t: (uint256, uint256)) returns (Point) { + match (t) { +case (x, y) { +return Point(x, y); +} +} } } @@ -23,7 +31,7 @@ contract GenericProduct { constructor() {} // Calls encode; returns word at offset 0 (the x field). - public function encodeX(a : uint256, b : uint256) -> uint256 { + function encodeX(a: uint256, b: uint256) public returns (uint256) { let p : Point = Point(a, b); let buf = allocate_zeroed_memory(64); encode(p, buf, 0, 64); @@ -31,7 +39,7 @@ contract GenericProduct { } // Calls encode; returns word at offset 32 (the y field). - public function encodeY(a : uint256, b : uint256) -> uint256 { + function encodeY(a: uint256, b: uint256) public returns (uint256) { let p : Point = Point(a, b); let buf = allocate_zeroed_memory(64); encode(p, buf, 0, 64); @@ -39,13 +47,17 @@ contract GenericProduct { } // Writes [a][b] into memory, calls decode, returns the x field. - public function decodeX(a : uint256, b : uint256) -> uint256 { + function decodeX(a: uint256, b: uint256) public returns (uint256) { let buf = allocate_zeroed_memory(64); mstore(buf, Typedef.rep(a)); mstore(buf + 32, Typedef.rep(b)); let rdr : MemoryWordReader = MemoryWordReader(buf); - let dec : ABIDecoder(Point, MemoryWordReader) = ABIDecoder(rdr); + let dec : ABIDecoder = ABIDecoder(rdr); let p : Point = decode(dec, 0); - match p { | Point(x, _) => return x; } + match (p) { +case Point(x, _) { +return x; +} +} } } diff --git a/tests/e2e/generic-sum/main.sol b/tests/e2e/generic-sum/main.sol index 164f7bc7..34d9b128 100644 --- a/tests/e2e/generic-sum/main.sol +++ b/tests/e2e/generic-sum/main.sol @@ -1,27 +1,35 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; +import * from std.Generic; +import * from std.ABIGeneric; pragma no-generic-instance-for Option; -data Option(a) = None | Some(a); +enum Option { None, Some(a) } -// Only requirement: Generic instance using the primitive sum type. +// Only requirement: a Generic impl using the primitive sum type. // rep = sum((), uint256): inl(()) = None, inr(v) = Some(v) -instance Option(uint256) : Generic(sum((), uint256)) { - function from(x : Option(uint256)) -> sum((), uint256) { - match x { - | Option.None => return inl(()); - | Option.Some(v) => return inr(v); - } +impl Generic, sum<(), uint256>> { + function from(x: Option) returns (sum<(), uint256>) { + match (x) { +case Option.None { +return inl(()); +} +case Option.Some(v) { +return inr(v); +} +} } - function to(r : sum((), uint256)) -> Option(uint256) { - match r { - | inl(_) => return Option.None; - | inr(v) => return Option.Some(v); - } + function to(r: sum<(), uint256>) returns (Option) { + match (r) { +case inl(_) { +return Option.None; +} +case inr(v) { +return Option.Some(v); +} +} } } @@ -30,8 +38,8 @@ contract GenericSum { // Calls encode; returns the tag word (first 32 bytes). // None → 0 - public function encodeNone() -> uint256 { - let x : Option(uint256) = Option.None; + function encodeNone() public returns (uint256) { + let x : Option = Option.None; let buf = allocate_zeroed_memory(64); encode(x, buf, 0, 64); return Typedef.abs(mload(buf)); @@ -39,32 +47,36 @@ contract GenericSum { // Calls encode; returns the tag word (first 32 bytes). // Some(n) → 1 - public function encodeSomeTag(n : uint256) -> uint256 { - let x : Option(uint256) = Option.Some(n); + function encodeSomeTag(n: uint256) public returns (uint256) { + let x : Option = Option.Some(n); let buf = allocate_zeroed_memory(64); encode(x, buf, 0, 64); return Typedef.abs(mload(buf)); } // Calls encode; returns the payload word (bytes 32-63). - public function encodePayload(n : uint256) -> uint256 { - let x : Option(uint256) = Option.Some(n); + function encodePayload(n: uint256) public returns (uint256) { + let x : Option = Option.Some(n); let buf = allocate_zeroed_memory(64); encode(x, buf, 0, 64); return Typedef.abs(mload(buf + 32)); } // Writes [tag][value] into memory, calls decode, returns the value or 0. - public function decodeAndGet(tag : uint256, value : uint256) -> uint256 { + function decodeAndGet(tag: uint256, value: uint256) public returns (uint256) { let buf = allocate_zeroed_memory(64); mstore(buf, Typedef.rep(tag)); mstore(buf + 32, Typedef.rep(value)); let rdr : MemoryWordReader = MemoryWordReader(buf); - let dec : ABIDecoder(Option(uint256), MemoryWordReader) = ABIDecoder(rdr); - let opt : Option(uint256) = decode(dec, 0); - match opt { - | Option.None => return uint256(0); - | Option.Some(v) => return v; - } + let dec : ABIDecoder, MemoryWordReader> = ABIDecoder(rdr); + let opt : Option = decode(dec, 0); + match (opt) { +case Option.None { +return uint256(0); +} +case Option.Some(v) { +return v; +} +} } } diff --git a/tests/e2e/hashes/main.sol b/tests/e2e/hashes/main.sol index 53912a49..2b54a846 100644 --- a/tests/e2e/hashes/main.sol +++ b/tests/e2e/hashes/main.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mstore}; +import * from std; +import * from std.dispatch; +import {mstore} from std.opcodes; // Build a memory(bytes) holding the three-byte string "abc". -function abcBytes() -> memory(bytes) { +function abcBytes() returns (memory) { let p = allocate_memory(64); mstore(p, 3); mstore(p + 32, 0x6162630000000000000000000000000000000000000000000000000000000000); @@ -13,35 +13,35 @@ function abcBytes() -> memory(bytes) { contract C { constructor() {} - public function keccak() -> bytes32 { + function keccak() public returns (bytes32) { return keccak256_(abcBytes()); } - public function sha() -> bytes32 { + function sha() public returns (bytes32) { return sha256(abcBytes()); } - public function ripemd() -> bytes32 { + function ripemd() public returns (bytes32) { return ripemd160(abcBytes()); } // keccakWordLit folds keccak256 of a word's 32-byte big-endian form at // compile time; keccakWordLit(0) == keccak256(bytes32(0)). - public function keccakWord() -> bytes32 { + function keccakWord() public returns (bytes32) { return bytes32(keccakWordLit(0)); } // ERC-7201 namespaced storage slots, folded to constants at compile time // from the string-literal namespace (no runtime keccak of the id). - public function erc7201Example() -> bytes32 { + function erc7201Example() public returns (bytes32) { return erc7201("example.main"); } - public function erc7201Ownable() -> bytes32 { + function erc7201Ownable() public returns (bytes32) { return erc7201("openzeppelin.storage.Ownable"); } - public function erc7201Empty() -> bytes32 { + function erc7201Empty() public returns (bytes32) { return erc7201(""); } } diff --git a/tests/e2e/ltimp/ltproxy.sol b/tests/e2e/ltimp/ltproxy.sol index 15e88c87..493118bf 100644 --- a/tests/e2e/ltimp/ltproxy.sol +++ b/tests/e2e/ltimp/ltproxy.sol @@ -1,7 +1,7 @@ -import std.{lt}; +import {lt} from std; export { ltproxy }; -function ltproxy() -> bool { +function ltproxy() returns (bool) { let zero : word = 0; return (zero < 42); } diff --git a/tests/e2e/ltimp/main.sol b/tests/e2e/ltimp/main.sol index 931b831f..a5d1531c 100644 --- a/tests/e2e/ltimp/main.sol +++ b/tests/e2e/ltimp/main.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -import ltproxy.{ltproxy}; +import {ltproxy} from ltproxy; contract LtImp { // #[() -> true] - public function run() -> bool { ltproxy() } + function run() public returns (bool) { ltproxy() } } diff --git a/tests/e2e/memory/main.sol b/tests/e2e/memory/main.sol index eec43817..6f79c9cd 100644 --- a/tests/e2e/memory/main.sol +++ b/tests/e2e/memory/main.sol @@ -1,16 +1,16 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mstore}; +import * from std; +import * from std.dispatch; +import {mstore} from std.opcodes; contract C { - public function dirty_allocate() -> memory(bytes) { + function dirty_allocate() public returns (memory) { mstore(get_free_memory() + 32, 0xdeadc0de); let ptr = allocate_memory(32 + 32); mstore(ptr, 32); return memory(ptr); } - public function clear_allocate() -> memory(bytes) { + function clear_allocate() public returns (memory) { mstore(get_free_memory() + 32, 0xdeadc0de); let ptr = allocate_zeroed_memory(32 + 32); mstore(ptr, 32); diff --git a/tests/e2e/mini-erc20/main.sol b/tests/e2e/mini-erc20/main.sol index a5eb3554..bf23b85e 100644 --- a/tests/e2e/mini-erc20/main.sol +++ b/tests/e2e/mini-erc20/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -15,10 +15,10 @@ contract MiniERC20 { owner : address; decimals : uint256; // should be uint8 when we get to it totalSupply : uint256; - balances : mapping(address,uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); - constructor(name_ : memory(string), symbol_ : memory(string), totalSupply_:uint256) { + constructor(name_ : memory, symbol_ : memory, totalSupply_:uint256) { name = name_; symbol = symbol_; owner = caller(); @@ -26,45 +26,45 @@ contract MiniERC20 { mint(totalSupply_); } - public function name() -> memory(string) { + function name() public returns (memory) { return name; } - public function symbol() -> memory(string) { + function symbol() public returns (memory) { return symbol; } - public function decimals() -> uint256 { + function decimals() public returns (uint256) { return decimals; } - public function allowance(owner_ : address, spender: address) -> uint256 { + function allowance(owner_: address, spender: address) public returns (uint256) { return allowance[owner_][spender]; // don't use "owner" here } - public function balanceOf(account : address) -> uint256 { + function balanceOf(account: address) public returns (uint256) { return balances[account]; } - public function totalSupply() -> uint256 { + function totalSupply() public returns (uint256) { return totalSupply; } // Note that this is not access guarded — the minting always goes to the owner - public function mint(amount:uint256) -> () { + function mint(amount: uint256) public { balances[owner] = Num.add(balances[owner], amount); totalSupply = Num.add(totalSupply, amount); } - public function transfer(dst : address, amt : uint256) -> bool { + function transfer(dst: address, amt: uint256) public returns (bool) { return transferFrom(caller(), dst, amt); } - public function transferFrom(src:address, dst:address, amt:uint256) -> bool { + function transferFrom(src: address, dst: address, amt: uint256) public returns (bool) { let msg_sender = caller(); require(balances[src] >= amt, "transferFrom: insufficient balance"); - if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal():uint256)) { + if (src != msg_sender && allowance[src][msg_sender] != (Num.maxVal())) { require(allowance[src][msg_sender] >= amt, "transferFrom: insufficient allowance"); allowance[src][msg_sender] -= amt; } @@ -74,7 +74,7 @@ contract MiniERC20 { return true; } - public function approve(usr: address, amt: uint256) -> bool { + function approve(usr: address, amt: uint256) public returns (bool) { let msg_sender = caller(); allowance[msg_sender][usr] = amt; // emit Approval(msg.sender, usr, amt); @@ -83,11 +83,11 @@ contract MiniERC20 { // testing - public function getMyBalance() -> uint256 { + function getMyBalance() public returns (uint256) { return balances[caller()]; } - public function test() -> uint256 { + function test() public returns (uint256) { approve(address(0), 10); transferFrom(caller(), address(0), 958); return getMyBalance(); diff --git a/tests/e2e/neg/main.sol b/tests/e2e/neg/main.sol index b04d0a8a..09356af6 100644 --- a/tests/e2e/neg/main.sol +++ b/tests/e2e/neg/main.sol @@ -1,69 +1,73 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -forall a. -class a : Neg { - function neg(x:a) -> a; +trait Neg { + function neg(x: a) returns (a) ; } -data B = F | T; -data Pair(a,b) = Pair(a,b); +enum B { F, T } +enum Pair { Pair(a, b) } -instance B : Neg { - function neg (x : B) -> B { - match x { - | B.F => return B.T; - | B.T => return B.F; - } +impl Neg { + function neg(x: B) returns (B) { + match (x) { +case B.F { +return B.T; +} +case B.T { +return B.F; +} +} } } -forall a b . function pairfst (p : Pair(a,b)) -> a { - match p { - | Pair(x,y) => return x; - } +function pairfst(p: Pair) returns (a) { + match (p) { +case Pair(x,y) { +return x; +} +} } -forall a b . function pairsnd(p : Pair(a,b)) -> b { - match p { - | Pair(x,y) => return y; - } +function pairsnd(p: Pair) returns (b) { + match (p) { +case Pair(x,y) { +return y; +} +} } -forall a b. -a:Neg,b:Neg => instance Pair(a,b):Neg { - function neg(p:Pair(a,b)) -> Pair(a,b) { +impl Neg> where a: Neg, b: Neg { + function neg(p: Pair) returns (Pair) { return Pair(Neg.neg (pairfst(p)), Neg.neg(pairsnd(p))); } } -/* -instance (a:Neg,b:Neg) => Pair(a,b):Neg { - function neg(p) { - match p { - | Pair(a,b) => return Pair(neg(a), neg(b)); - } - } + function bnot(x: B) returns (B) { + match (x) { +case B.T { +return B.F; +} +case B.F { +return B.T; +} } -*/ - - function bnot(x:B) -> B { - match x { - | B.T => return B.F; - | B.F => return B.T; - } } - function fromB(b:B) -> word { - match b { - | B.F => return 0; - | B.T => return 1; - } + function fromB(b: B) returns (word) { + match (b) { +case B.F { +return 0; +} +case B.T { +return 1; +} +} } contract NegPair { constructor() {} - public function negPair() -> uint256 { return uint256(fromB(pairfst(Neg.neg(Pair(B.F,B.T))))); } + function negPair() public returns (uint256) { return uint256(fromB(pairfst(Neg.neg(Pair(B.F,B.T))))); } } diff --git a/tests/e2e/nonpayable-ctor/main.sol b/tests/e2e/nonpayable-ctor/main.sol index c19c104b..4eebca06 100644 --- a/tests/e2e/nonpayable-ctor/main.sol +++ b/tests/e2e/nonpayable-ctor/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // A contract whose constructor is NOT marked `payable`. Deploying it with an // incoming value transfer must revert with the NonPayableReceivedValue error @@ -7,7 +7,7 @@ import std.dispatch.{*}; contract NonPayableCtor { constructor() {} - public function balance() -> uint256 { + function balance() public returns (uint256) { let value; assembly { value := selfbalance() diff --git a/tests/e2e/ownable/main.sol b/tests/e2e/ownable/main.sol index b20be59b..c3c2fb65 100644 --- a/tests/e2e/ownable/main.sol +++ b/tests/e2e/ownable/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // caller() is not in the std library yet, // so every contract must define its own -function caller() -> address { +function caller() returns (address) { let res: word; assembly { res := caller() @@ -20,11 +20,11 @@ contract Ownable { } // named getOwner() instead of owner() to avoid collision with the field name - public function getOwner() -> address { + function getOwner() public returns (address) { return owner; } - public function changeOwner(newOwner : address) -> () { + function changeOwner(newOwner: address) public { require(caller() == owner, Error(0x12b0c500)); // OwnableUnauthorizedAccount() owner = newOwner; } diff --git a/tests/e2e/p256verify/main.sol b/tests/e2e/p256verify/main.sol index e1ddc4f0..af8d978c 100644 --- a/tests/e2e/p256verify/main.sol +++ b/tests/e2e/p256verify/main.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.dispatch.{*}; -import std.eip7951.{p256verify}; +import * from std; +import * from std.dispatch; +import {p256verify} from std.eip7951; // Exercises the P256VERIFY (secp256r1) precompile at address 0x100, introduced // by EIP-7951, through the std `p256verify` helper. It returns true for a valid @@ -8,7 +8,7 @@ import std.eip7951.{p256verify}; contract P256Test { constructor() {} - public function verifyValid() -> bool { + function verifyValid() public returns (bool) { return p256verify( bytes32(0xabcdef00112233445566778899aabbccddeeff00112233445566778899aabbcc), bytes32(0xa29295460e251beea1bdc9b84b2f3fe8e3a3e4d872baa3c55b78c9e448190ea9), @@ -18,7 +18,7 @@ contract P256Test { ); } - public function verifyInvalid() -> bool { + function verifyInvalid() public returns (bool) { return p256verify( bytes32(0xabcdef00112233445566778899aabbccddeeff00112233445566778899aabbcd), bytes32(0xa29295460e251beea1bdc9b84b2f3fe8e3a3e4d872baa3c55b78c9e448190ea9), diff --git a/tests/e2e/payable-ctor/main.sol b/tests/e2e/payable-ctor/main.sol index ce2d3ce1..93c6813a 100644 --- a/tests/e2e/payable-ctor/main.sol +++ b/tests/e2e/payable-ctor/main.sol @@ -1,13 +1,13 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // A contract whose constructor is explicitly marked `payable`. // Deploying it with an incoming value transfer must succeed and the // transferred value is retained by the newly created contract. contract PayableCtor { - payable constructor() {} + constructor() payable {} - public function balance() -> uint256 { + function balance() public returns (uint256) { let value; assembly { value := selfbalance() diff --git a/tests/e2e/payable/main.sol b/tests/e2e/payable/main.sol index 553275b1..a8d15a88 100644 --- a/tests/e2e/payable/main.sol +++ b/tests/e2e/payable/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PayableTest { constructor() {} - public payable function deposit() -> uint256 { + function deposit() public payable returns (uint256) { let value; assembly { value := callvalue() @@ -12,7 +12,7 @@ contract PayableTest { return uint256(value); } - public function balance() -> uint256 { + function balance() public returns (uint256) { let value; assembly { value := selfbalance() @@ -20,7 +20,7 @@ contract PayableTest { return uint256(value); } - payable fallback() -> () { + fallback() payable { let value; assembly { value := callvalue() diff --git a/tests/e2e/persistent-storage/main.sol b/tests/e2e/persistent-storage/main.sol index 204a1508..14461755 100644 --- a/tests/e2e/persistent-storage/main.sol +++ b/tests/e2e/persistent-storage/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract PersistentStorage { stored: uint256; @@ -9,17 +9,17 @@ contract PersistentStorage { } // #[() -> 7] - public function initialValue() -> uint256 { + function initialValue() public returns (uint256) { return stored; } // #[send(41)] - public function setStored(value: uint256) { + function setStored(value: uint256) public { stored = value; } // #[() -> 41] - public function valueAfterSend() -> uint256 { + function valueAfterSend() public returns (uint256) { return stored; } } diff --git a/tests/e2e/raw-vector/main.sol b/tests/e2e/raw-vector/main.sol index 3e3e1982..c13ea6a9 100644 --- a/tests/e2e/raw-vector/main.sol +++ b/tests/e2e/raw-vector/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract RawVector { stored: uint256; @@ -8,11 +8,11 @@ contract RawVector { stored = uint256(7); } - public function initialValue() -> uint256 { + function initialValue() public returns (uint256) { return stored; } - public function callerAddress() -> address { + function callerAddress() public returns (address) { let result: word; assembly { result := caller() @@ -20,11 +20,11 @@ contract RawVector { return address(result); } - public function setStored(value: uint256) { + function setStored(value: uint256) public { stored = value; } - public function valueAfterSend() -> uint256 { + function valueAfterSend() public returns (uint256) { return stored; } } diff --git a/tests/e2e/revert-raw/main.sol b/tests/e2e/revert-raw/main.sol index 88e8229d..e0962961 100644 --- a/tests/e2e/revert-raw/main.sol +++ b/tests/e2e/revert-raw/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -function my_revert() -> word { +function my_revert() returns (word) { revertLit("regression"); return 0; } @@ -9,11 +9,11 @@ function my_revert() -> word { contract Foo { constructor() {} - public function noAnswer() -> uint256 { + function noAnswer() public returns (uint256) { return uint256(my_revert()); } - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } } diff --git a/tests/e2e/revert/main.sol b/tests/e2e/revert/main.sol index 75ba09c5..6082069d 100644 --- a/tests/e2e/revert/main.sol +++ b/tests/e2e/revert/main.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract RevertExpectation { // #[(7) -> revert(0xdeadbeef)] - public function fail(x: uint256) -> uint256 { + function fail(x: uint256) public returns (uint256) { assembly { mstore(0, 0xdeadbeef) revert(28, 4) diff --git a/tests/e2e/slices/main.sol b/tests/e2e/slices/main.sol index a44d6b38..7d6025f4 100644 --- a/tests/e2e/slices/main.sol +++ b/tests/e2e/slices/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Exercises slice_/truncate (memory_slice) composed with concat, to_bytes, // and the hashing precompiles (keccak256_, sha256). memory_slice implements @@ -8,58 +8,58 @@ import std.dispatch.{*}; contract C { // --- slice_/truncate on a memory(bytes), materialized with to_bytes --- - public function slice_bytes(a: memory(bytes), start: uint256) -> memory(bytes) { + function slice_bytes(a: memory, start: uint256) public returns (memory) { return to_bytes(slice_(a, Typedef.rep(start))); } - public function truncate_bytes(a: memory(bytes), end: uint256) -> memory(bytes) { + function truncate_bytes(a: memory, end: uint256) public returns (memory) { return to_bytes(truncate(a, Typedef.rep(end))); } // --- slice_/truncate over the result of a concat --- - public function slice_of_concat(a: bytes32, b: bytes32, start: uint256) -> memory(bytes) { + function slice_of_concat(a: bytes32, b: bytes32, start: uint256) public returns (memory) { return to_bytes(slice_(concat(a, b), Typedef.rep(start))); } - public function truncate_of_concat(a: bytes32, b: bytes32, end: uint256) -> memory(bytes) { + function truncate_of_concat(a: bytes32, b: bytes32, end: uint256) public returns (memory) { return to_bytes(truncate(concat(a, b), Typedef.rep(end))); } // to_bytes(truncate(slice_(concat(a, b), start), end)) -- the headline nesting: // drop `start` bytes, then keep `end` of what remains (re-slicing a memory_slice). - public function window_of_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) -> memory(bytes) { + function window_of_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) public returns (memory) { return to_bytes(truncate(slice_(concat(a, b), Typedef.rep(start)), Typedef.rep(end))); } // --- a slice used as a concat operand --- - public function concat_slice_b32(a: memory(bytes), start: uint256, c: bytes32) -> memory(bytes) { + function concat_slice_b32(a: memory, start: uint256, c: bytes32) public returns (memory) { return concat(slice_(a, Typedef.rep(start)), c); } - public function concat_two_slices(a: memory(bytes), sa: uint256, b: memory(bytes), eb: uint256) -> memory(bytes) { + function concat_two_slices(a: memory, sa: uint256, b: memory, eb: uint256) public returns (memory) { return concat(slice_(a, Typedef.rep(sa)), truncate(b, Typedef.rep(eb))); } // --- re-slicing a memory_slice --- - public function slice_of_slice(a: memory(bytes), s1: uint256, s2: uint256) -> memory(bytes) { + function slice_of_slice(a: memory, s1: uint256, s2: uint256) public returns (memory) { return to_bytes(slice_(slice_(a, Typedef.rep(s1)), Typedef.rep(s2))); } // --- hashing a slice directly (no intermediate copy) --- - public function keccak_slice(a: memory(bytes), start: uint256) -> bytes32 { + function keccak_slice(a: memory, start: uint256) public returns (bytes32) { return keccak256_(slice_(a, Typedef.rep(start))); } - public function sha_truncate(a: memory(bytes), end: uint256) -> bytes32 { + function sha_truncate(a: memory, end: uint256) public returns (bytes32) { return sha256(truncate(a, Typedef.rep(end))); } // keccak256_(truncate(slice_(concat(a, b), start), end)) -- nested chain, hash endpoint. - public function keccak_window_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) -> bytes32 { + function keccak_window_concat(a: bytes32, b: bytes32, start: uint256, end: uint256) public returns (bytes32) { return keccak256_(truncate(slice_(concat(a, b), Typedef.rep(start)), Typedef.rep(end))); } } diff --git a/tests/e2e/specialise-sum-of-product/main.sol b/tests/e2e/specialise-sum-of-product/main.sol index 22d60064..b28de52b 100644 --- a/tests/e2e/specialise-sum-of-product/main.sol +++ b/tests/e2e/specialise-sum-of-product/main.sol @@ -20,50 +20,65 @@ // class and its instances are defined locally and exercised directly, so the // program must now lower end-to-end and return the expected value. -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-patterson-condition; pragma no-bounded-variable-condition; // total(x, y) sums every leaf word of both arguments. -forall a. -class a : Total { - function total(x : a, y : a) -> word; +trait Total { + function total(x: a, y: a) returns (word) ; } -instance word : Total { - function total(x : word, y : word) -> word { +impl Total { + function total(x: word, y: word) returns (word) { return x + y; } } // product: recurse into both components (this is the shape inl carries). -forall f g . f : Total, g : Total => instance (f, g) : Total { - function total(x : (f, g), y : (f, g)) -> word { - match x { - | (xa, xb) => match y { - | (ya, yb) => return Total.total(xa, ya) + Total.total(xb, yb); - } - } +impl Total<(f, g)> where f: Total, g: Total { + function total(x: (f, g), y: (f, g)) returns (word) { + match (x) { +case (xa, xb) { +match (y) { +case (ya, yb) { +return Total.total(xa, ya) + Total.total(xb, yb); +} +} +} +} } } // sum: the buggy shape. The inl branch recurses at f (a product here), the inr // branch recurses at g (a word here); specializing one must not pollute the // other's nested `match y`. -forall f g . f : Total, g : Total => instance sum(f, g) : Total { - function total(x : sum(f, g), y : sum(f, g)) -> word { - match x { - | inl(xa) => match y { - | inl(ya) => return Total.total(xa, ya); - | inr(yb) => return 0; - } - | inr(xb) => match y { - | inl(ya) => return 0; - | inr(yb) => return Total.total(xb, yb); - } - } +impl Total> where f: Total, g: Total { + function total(x: sum, y: sum) returns (word) { + match (x) { +case inl(xa) { +match (y) { +case inl(ya) { +return Total.total(xa, ya); +} +case inr(yb) { +return 0; +} +} +} +case inr(xb) { +match (y) { +case inl(ya) { +return 0; +} +case inr(yb) { +return Total.total(xb, yb); +} +} +} +} } } @@ -73,9 +88,9 @@ contract SpecialiseSumOfProduct { // inl carries a product (word, word); the two sum sides differ in shape // (pair vs word), which is what the specializer mishandled. // total(inl((1,2)), inl((1,2))) = total((1,2),(1,2)) = (1+1)+(2+2) = 6. - public function probe() -> uint256 { - let x : sum((word, word), word) = inl((1, 2)); - let y : sum((word, word), word) = inl((1, 2)); + function probe() public returns (uint256) { + let x : sum<(word, word), word> = inl((1, 2)); + let y : sum<(word, word), word> = inl((1, 2)); return uint256(Total.total(x, y)); } } diff --git a/tests/e2e/std-word-correctness/main.sol b/tests/e2e/std-word-correctness/main.sol index d597e94e..2f658558 100644 --- a/tests/e2e/std-word-correctness/main.sol +++ b/tests/e2e/std-word-correctness/main.sol @@ -1,25 +1,25 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract StdWordCorrectness { // #[(7, 42) -> 7] // #[(42, 7) -> 7] // #[(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0) -> 0] - public function minOf(a: uint256, b: uint256) -> uint256 { + function minOf(a: uint256, b: uint256) public returns (uint256) { return uint256(minWord(Typedef.rep(a), Typedef.rep(b))); } // #[(7, 42) -> 42] // #[(42, 7) -> 42] // #[(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0) -> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff] - public function maxOf(a: uint256, b: uint256) -> uint256 { + function maxOf(a: uint256, b: uint256) public returns (uint256) { return uint256(maxWord(Typedef.rep(a), Typedef.rep(b))); } // An invalid recovery id makes the precompile succeed with no returndata. // Dirty scratch memory must not be mistaken for a recovered address. // #[() -> revert(0x4fbfae63)] - public function recoverInvalidAfterDirtyScratch() -> address { + function recoverInvalidAfterDirtyScratch() public returns (address) { assembly { mstore(0, 0x1234) } let h: bytes32 = bytes32(0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899); let v: uint256 = uint256(1); diff --git a/tests/e2e/storage-adt-abi/main.sol b/tests/e2e/storage-adt-abi/main.sol index 2dcdc0ba..35e8cbcc 100644 --- a/tests/e2e/storage-adt-abi/main.sol +++ b/tests/e2e/storage-adt-abi/main.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.ABIGeneric.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.ABIGeneric; +import * from std.StorageGeneric; // An ADT crossing the ABI boundary AND living in storage at the same time. // @@ -18,42 +18,50 @@ import std.StorageGeneric.{*}; // at +32. So `Some(42)` is 0x...01 followed by 0x...2a, and `None` is 0x...00 // followed by a don't-care word. -data Option(a) = None | Some(a); +enum Option { None, Some(a) } contract C { - stored : Option(uint256); + stored : Option; constructor() { stored = Option.None; - assert(StorageSize.size(Proxy : Proxy(Option(uint256))) == 2); + assert(StorageSize.size(@Option) == 2); } // ADT as a parameter: decoded from calldata, then written to storage. - public function setOpt(o : Option(uint256)) -> () { + function setOpt(o: Option) public { stored = o; } // ADT as a return value: loaded from storage, then encoded into returndata. - public function getOpt() -> Option(uint256) { + function getOpt() public returns (Option) { return stored; } // Round-trip in one call, without touching storage. - public function echo(o : Option(uint256)) -> Option(uint256) { + function echo(o: Option) public returns (Option) { return o; } - public function isSome() -> bool { - match stored { - | Option.None => return false; - | Option.Some(_) => return true; - } + function isSome() public returns (bool) { + match (stored) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } - public function unwrapOr(d : uint256) -> uint256 { - match stored { - | Option.None => return d; - | Option.Some(v) => return v; - } + function unwrapOr(d: uint256) public returns (uint256) { + match (stored) { +case Option.None { +return d; +} +case Option.Some(v) { +return v; +} +} } } diff --git a/tests/e2e/storage-adt-bool/main.sol b/tests/e2e/storage-adt-bool/main.sol index 5d1a80b6..00a8e6b8 100644 --- a/tests/e2e/storage-adt-bool/main.sol +++ b/tests/e2e/storage-adt-bool/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // `bool` in storage, bare and inside an ADT. // @@ -16,10 +16,10 @@ import std.StorageGeneric.{*}; // instance, so it cannot appear in a public parameter position. It can appear // in a return position, which is what the getters below exercise. -data Flags = Flags(bool, bool); -data Toggle = Off | On(bool); +enum Flags { Flags(bool, bool) } +enum Toggle { Off, On(bool) } -function toBool(v : uint256) -> bool { +function toBool(v: uint256) returns (bool) { return v != uint256(0); } @@ -32,42 +32,46 @@ contract C { bare = false; flags = Flags(false, false); toggle = Toggle.Off; - assert(StorageSize.size(Proxy : Proxy(bool)) == 1); + assert(StorageSize.size(@bool) == 1); // product of two bools - assert(StorageSize.size(Proxy : Proxy(Flags)) == 2); + assert(StorageSize.size(@Flags) == 2); // 1 tag + max(size (), size bool) - assert(StorageSize.size(Proxy : Proxy(Toggle)) == 2); + assert(StorageSize.size(@Toggle) == 2); } - public function setBare(v : uint256) -> () { + function setBare(v: uint256) public { bare = toBool(v); } - public function getBare() -> bool { + function getBare() public returns (bool) { return bare; } - public function setFlags(a : uint256, b : uint256) -> () { + function setFlags(a: uint256, b: uint256) public { flags = Flags(toBool(a), toBool(b)); } - public function firstFlag() -> bool { - match flags { - | Flags(a, _) => return a; - } + function firstFlag() public returns (bool) { + match (flags) { +case Flags(a, _) { +return a; +} +} } - public function secondFlag() -> bool { - match flags { - | Flags(_, b) => return b; - } + function secondFlag() public returns (bool) { + match (flags) { +case Flags(_, b) { +return b; +} +} } - public function turnOn(v : uint256) -> () { + function turnOn(v: uint256) public { toggle = Toggle.On(toBool(v)); } - public function turnOff() -> () { + function turnOff() public { toggle = Toggle.Off; } From 1a4747b7ebecaf2a118eb77a6d4a256f1ae4de0d Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 094/110] Switch the compiler and fixtures to canonical syntax: tests Co-authored-by: Codex --- tests/e2e/storage-adt-bool/main.sol | 28 ++++-- tests/e2e/storage-adt-enum/main.sol | 85 +++++++++------- tests/e2e/storage-adt-field/main.sol | 105 ++++++++++++-------- tests/e2e/storage-adt-mapping/main.sol | 95 ++++++++++-------- tests/e2e/storage-adt-recursive-ok/main.sol | 30 +++--- tests/e2e/storage-array/main.sol | 18 ++-- tests/e2e/storage-dynamic-field/main.sol | 46 +++++---- tests/e2e/storage-index-order/main.sol | 12 +-- tests/e2e/storage/main.sol | 8 +- tests/e2e/stringlit/main.sol | 10 +- tests/e2e/sum-wide-product/main.sol | 20 ++-- tests/e2e/ufcs-array/main.sol | 24 ++--- tests/e2e/weth9/main.sol | 36 +++---- tests/e2e/yul-special-identifiers/main.sol | 6 +- 14 files changed, 297 insertions(+), 226 deletions(-) diff --git a/tests/e2e/storage-adt-bool/main.sol b/tests/e2e/storage-adt-bool/main.sol index 00a8e6b8..ee7a810e 100644 --- a/tests/e2e/storage-adt-bool/main.sol +++ b/tests/e2e/storage-adt-bool/main.sol @@ -77,17 +77,25 @@ return b; // Distinguishes Off from On(false): both leave a zero payload slot, so only // the tag can tell them apart. - public function isOn() -> bool { - match toggle { - | Toggle.Off => return false; - | Toggle.On(_) => return true; - } + function isOn() public returns (bool) { + match (toggle) { +case Toggle.Off { +return false; +} +case Toggle.On(_) { +return true; +} +} } - public function toggleValue() -> bool { - match toggle { - | Toggle.Off => revertEmpty(); return false; - | Toggle.On(b) => return b; - } + function toggleValue() public returns (bool) { + match (toggle) { +case Toggle.Off { +revertEmpty(); return false; +} +case Toggle.On(b) { +return b; +} +} } } diff --git a/tests/e2e/storage-adt-enum/main.sol b/tests/e2e/storage-adt-enum/main.sol index 732d6036..5f721fe2 100644 --- a/tests/e2e/storage-adt-enum/main.sol +++ b/tests/e2e/storage-adt-enum/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // An enumeration with more than two constructors. // @@ -17,15 +17,12 @@ import std.StorageGeneric.{*}; // // `Green` is the only constructor that exercises the `inr(inl(...))` path, // which is exactly the sum nesting that CanStore.load has to reconstruct. -data Color = Red | Green | Blue; +enum Color { Red, Green, Blue } // A three-constructor sum whose branches carry payloads of different widths. // rep = sum(uint256, sum((uint256, uint256), ())), so // size = 1 + max(1, 1 + max(2, 0)) = 4. -data Shape = - Dot(uint256) - | Seg(uint256, uint256) - | Nothing; +enum Shape { Dot(uint256), Seg(uint256, uint256), Nothing } contract C { color : Color; @@ -35,58 +32,76 @@ contract C { color = Color.Red; shape = Shape.Nothing; // 1 tag + max(size (), 1 tag + max(size (), size ())) = 1 + 1 + 0 = 2 - assert(StorageSize.size(Proxy : Proxy(Color)) == 2); + assert(StorageSize.size(@Color) == 2); // 1 tag + max(size uint256, 1 tag + max(size (uint256,uint256), size ())) = 1 + 1 + 2 = 4 - assert(StorageSize.size(Proxy : Proxy(Shape)) == 4); + assert(StorageSize.size(@Shape) == 4); } - public function setRed() -> () { + function setRed() public { color = Color.Red; } // inr(inl(())) — the nested-tag branch. - public function setGreen() -> () { + function setGreen() public { color = Color.Green; } - public function setBlue() -> () { + function setBlue() public { color = Color.Blue; } - public function tag() -> uint256 { - match color { - | Color.Red => return uint256(0); - | Color.Green => return uint256(1); - | Color.Blue => return uint256(2); - } + function tag() public returns (uint256) { + match (color) { +case Color.Red { +return uint256(0); +} +case Color.Green { +return uint256(1); +} +case Color.Blue { +return uint256(2); +} +} } - public function setDot(a : uint256) -> () { + function setDot(a: uint256) public { shape = Shape.Dot(a); } // inr(inl(...)) again, this time with a product payload. - public function setSeg(a : uint256, b : uint256) -> () { + function setSeg(a: uint256, b: uint256) public { shape = Shape.Seg(a, b); } - public function setNothing() -> () { + function setNothing() public { shape = Shape.Nothing; } - public function shapeSum() -> uint256 { - match shape { - | Shape.Dot(a) => return a; - | Shape.Seg(a, b) => return a + b; - | Shape.Nothing => return uint256(0); - } + function shapeSum() public returns (uint256) { + match (shape) { +case Shape.Dot(a) { +return a; +} +case Shape.Seg(a, b) { +return a + b; +} +case Shape.Nothing { +return uint256(0); +} +} } - public function shapeTag() -> uint256 { - match shape { - | Shape.Dot(_) => return uint256(0); - | Shape.Seg(_, _) => return uint256(1); - | Shape.Nothing => return uint256(2); - } + function shapeTag() public returns (uint256) { + match (shape) { +case Shape.Dot(_) { +return uint256(0); +} +case Shape.Seg(_, _) { +return uint256(1); +} +case Shape.Nothing { +return uint256(2); +} +} } } diff --git a/tests/e2e/storage-adt-field/main.sol b/tests/e2e/storage-adt-field/main.sol index d1b68cb2..c9bc2ef5 100644 --- a/tests/e2e/storage-adt-field/main.sol +++ b/tests/e2e/storage-adt-field/main.sol @@ -1,7 +1,7 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // Algebraic data types used directly as contract storage fields, including a // nested ADT (Option(Triple)). @@ -10,78 +10,97 @@ import std.StorageGeneric.{*}; // - triple : Triple (product, rep (uint256,(uint256,uint256)) -> 3 slots) // - someTriple : Option(Triple) (sum of product, rep sum((), Triple) -> 4 slots) -data Option(a) = None | Some(a); -data Triple = Triple(uint256, uint256, uint256); +enum Option { None, Some(a) } +enum Triple { Triple(uint256, uint256, uint256) } contract C { - someValue : Option(uint256); + someValue : Option; triple : Triple; - someTriple : Option(Triple); + someTriple : Option; constructor() { // sum: 1 tag + max(size (), size uint256) = 1 + 1 = 2 - assert(StorageSize.size(Proxy : Proxy(Option(uint256))) == 2); + assert(StorageSize.size(@Option) == 2); // product: size uint256 * 3 = 3 - assert(StorageSize.size(Proxy : Proxy(Triple)) == 3); + assert(StorageSize.size(@Triple) == 3); // sum of product: 1 tag + max(size (), size Triple) = 1 + 3 = 4 - assert(StorageSize.size(Proxy : Proxy(Option(Triple))) == 4); + assert(StorageSize.size(@Option) == 4); } - public function setValue(v : uint256) -> () { + function setValue(v: uint256) public { someValue = Option.Some(v); } - public function clearValue() -> () { + function clearValue() public { someValue = Option.None; } - public function getValue() -> uint256 { - match someValue { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(v) => return v; - } + function getValue() public returns (uint256) { + match (someValue) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(v) { +return v; +} +} } - public function isSome() -> bool { - match someValue { - | Option.None => return false; - | Option.Some(_) => return true; - } + function isSome() public returns (bool) { + match (someValue) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } - public function setTriple(a : uint256, b : uint256, c : uint256) -> () { + function setTriple(a: uint256, b: uint256, c: uint256) public { triple = Triple(a, b, c); } - public function tripleSum() -> uint256 { - match triple { - | Triple(a, b, c) => return a + b + c; - } + function tripleSum() public returns (uint256) { + match (triple) { +case Triple(a, b, c) { +return a + b + c; +} +} } // Nested ADT: Option(Triple). - public function setSomeTriple(a : uint256, b : uint256, c : uint256) -> () { + function setSomeTriple(a: uint256, b: uint256, c: uint256) public { someTriple = Option.Some(Triple(a, b, c)); } - public function clearSomeTriple() -> () { + function clearSomeTriple() public { someTriple = Option.None; } - public function someTripleSum() -> uint256 { - match someTriple { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(t) => - match t { - | Triple(a, b, c) => return a + b + c; - } - } + function someTripleSum() public returns (uint256) { + match (someTriple) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(t) { +match (t) { +case Triple(a, b, c) { +return a + b + c; +} +} +} +} } - public function hasSomeTriple() -> bool { - match someTriple { - | Option.None => return false; - | Option.Some(_) => return true; - } + function hasSomeTriple() public returns (bool) { + match (someTriple) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } } diff --git a/tests/e2e/storage-adt-mapping/main.sol b/tests/e2e/storage-adt-mapping/main.sol index ad2f4df8..4cb752ac 100644 --- a/tests/e2e/storage-adt-mapping/main.sol +++ b/tests/e2e/storage-adt-mapping/main.sol @@ -1,82 +1,97 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; // An ADT used as the VALUE of a storage mapping. // // This is the path opened by routing mapping reads through CanStore instead of -// StorageType (std.solc: readStorage / ridx / RValueIdxAccess). The write side +// StorageType (std.sol: readStorage / ridx / RValueIdxAccess). The write side // already went through Assign -> CanStore.store. // // A multi-slot value in a mapping occupies hash2(slot, key) .. + size(v) - 1, // exactly as Solidity lays out a struct behind a mapping. -data Option(a) = None | Some(a); -data Pair = Pair(uint256, uint256); +enum Option { None, Some(a) } +enum Pair { Pair(uint256, uint256) } contract C { // 2 slots per entry: tag + payload - opts : mapping(uint256, Option(uint256)); + opts : mapping(uint256 => Option); // 2 slots per entry: no tag, two words - pairs : mapping(uint256, Pair); + pairs : mapping(uint256 => Pair); // 3 slots per entry: tag + max(0, 2) - optPairs : mapping(uint256, Option(Pair)); + optPairs : mapping(uint256 => Option); constructor() { - assert(StorageSize.size(Proxy : Proxy(Option(uint256))) == 2); - assert(StorageSize.size(Proxy : Proxy(Pair)) == 2); - assert(StorageSize.size(Proxy : Proxy(Option(Pair))) == 3); + assert(StorageSize.size(@Option) == 2); + assert(StorageSize.size(@Pair) == 2); + assert(StorageSize.size(@Option) == 3); } - public function putOpt(k : uint256, v : uint256) -> () { + function putOpt(k: uint256, v: uint256) public { opts[k] = Option.Some(v); } - public function clearOpt(k : uint256) -> () { + function clearOpt(k: uint256) public { opts[k] = Option.None; } // Unset keys read back as the zero slot pattern, i.e. tag 0 = None. - public function hasOpt(k : uint256) -> bool { - match opts[k] { - | Option.None => return false; - | Option.Some(_) => return true; - } + function hasOpt(k: uint256) public returns (bool) { + match (opts[k]) { +case Option.None { +return false; +} +case Option.Some(_) { +return true; +} +} } - public function getOpt(k : uint256) -> uint256 { - match opts[k] { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(v) => return v; - } + function getOpt(k: uint256) public returns (uint256) { + match (opts[k]) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(v) { +return v; +} +} } - public function putPair(k : uint256, a : uint256, b : uint256) -> () { + function putPair(k: uint256, a: uint256, b: uint256) public { pairs[k] = Pair(a, b); } - public function pairSum(k : uint256) -> uint256 { - match pairs[k] { - | Pair(a, b) => return a + b; - } + function pairSum(k: uint256) public returns (uint256) { + match (pairs[k]) { +case Pair(a, b) { +return a + b; +} +} } - public function putOptPair(k : uint256, a : uint256, b : uint256) -> () { + function putOptPair(k: uint256, a: uint256, b: uint256) public { optPairs[k] = Option.Some(Pair(a, b)); } - public function clearOptPair(k : uint256) -> () { + function clearOptPair(k: uint256) public { optPairs[k] = Option.None; } - public function optPairSum(k : uint256) -> uint256 { - match optPairs[k] { - | Option.None => revertEmpty(); return uint256(0); - | Option.Some(p) => - match p { - | Pair(a, b) => return a + b; - } - } + function optPairSum(k: uint256) public returns (uint256) { + match (optPairs[k]) { +case Option.None { +revertEmpty(); return uint256(0); +} +case Option.Some(p) { +match (p) { +case Pair(a, b) { +return a + b; +} +} +} +} } } diff --git a/tests/e2e/storage-adt-recursive-ok/main.sol b/tests/e2e/storage-adt-recursive-ok/main.sol index e28974fc..cacf5e80 100644 --- a/tests/e2e/storage-adt-recursive-ok/main.sol +++ b/tests/e2e/storage-adt-recursive-ok/main.sol @@ -1,30 +1,34 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; -// The counterpart of storage-adt-recursive-fail.solc: skipping storage +// The counterpart of storage-adt-recursive-fail.sol: skipping storage // derivation for a recursive type is a SKIP, not a hard error. The type still // gets its Generic instance and remains usable everywhere except storage. -data IntList = Nil | Cons(uint256, IntList); +enum IntList { Nil, Cons(uint256, IntList) } -function len(xs : IntList) -> uint256 { - match xs { - | IntList.Nil => return uint256(0); - | IntList.Cons(_, r) => return uint256(1) + len(r); - } +function len(xs: IntList) returns (uint256) { + match (xs) { +case IntList.Nil { +return uint256(0); +} +case IntList.Cons(_, r) { +return uint256(1) + len(r); +} +} } // A non-recursive neighbour in the same module still gets its storage // instances, so the skip is per-type rather than per-module. -data Point = Point(uint256, uint256); +enum Point { Point(uint256, uint256) } contract C { p : Point; constructor() { p = Point(uint256(1), uint256(2)); - assert(StorageSize.size(Proxy : Proxy(Point)) == 2); + assert(StorageSize.size(@Point) == 2); } } diff --git a/tests/e2e/storage-array/main.sol b/tests/e2e/storage-array/main.sol index f652f8d5..65057965 100644 --- a/tests/e2e/storage-array/main.sol +++ b/tests/e2e/storage-array/main.sol @@ -1,18 +1,18 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; contract MemberRegistry { - members : array(address); + members : array
; constructor() {} - public function addMember(addr : address) -> () { + function addMember(addr: address) public { ArrayPush.push(members, addr); } // MemberNotFound() selector - public function removeMember(addr : address) -> () { + function removeMember(addr: address) public { // foundIdx == length() acts as the "not found" sentinel. let foundIdx : uint256 = Length.length(members); let i : uint256; @@ -32,11 +32,11 @@ contract MemberRegistry { Array.pop(members); } - public function numberOfMembers() -> uint256 { + function numberOfMembers() public returns (uint256) { return Length.length(members); } - public function getMembers() -> memory(DynArray(address)) { + function getMembers() public returns (memory>) { let count : word = Typedef.rep(Length.length(members)); let totalBytes : word = (count + 1) * 32; let ptr : word = allocate_memory(totalBytes); @@ -47,6 +47,6 @@ contract MemberRegistry { let addr : address = members[uint256(i)]; mstore(ptr + 32 + i * 32, Typedef.rep(addr)); } - return Typedef.abs(ptr) : memory(DynArray(address)); + return Typedef.abs(ptr) ; } } diff --git a/tests/e2e/storage-dynamic-field/main.sol b/tests/e2e/storage-dynamic-field/main.sol index fa863452..7ab845fe 100644 --- a/tests/e2e/storage-dynamic-field/main.sol +++ b/tests/e2e/storage-dynamic-field/main.sol @@ -1,11 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; -import std.Generic.{*}; -import std.StorageGeneric.{*}; +import * from std; +import * from std.dispatch; +import * from std.Generic; +import * from std.StorageGeneric; -data Blob = - NoBlob - | SomeBytes(memory(bytes)); +enum Blob { NoBlob, SomeBytes(memory) } contract C { blob : Blob; @@ -13,31 +11,39 @@ contract C { constructor() { blob = Blob.NoBlob; // A dynamic field occupies one slot, so the sum is 1 (tag) + max(0, 1). - assert(StorageSize.size(Proxy : Proxy(Blob)) == 2); + assert(StorageSize.size(@Blob) == 2); } - public function clear() -> () { + function clear() public { blob = Blob.NoBlob; } // Stores the memory(bytes) payload into the ADT field (round-trips the // dynamic leaf through storage(bytes)). - public function setBytes(b: memory(bytes)) -> () { + function setBytes(b: memory) public { blob = Blob.SomeBytes(b); } - public function getBytes() -> memory(bytes) { - match blob { - | Blob.NoBlob => revertEmpty(); return memory(0); - | Blob.SomeBytes(b) => return b; - } + function getBytes() public returns (memory) { + match (blob) { +case Blob.NoBlob { +revertEmpty(); return memory(0); +} +case Blob.SomeBytes(b) { +return b; +} +} } // Loads the whole ADT back from storage and inspects its tag. - public function isEmpty() -> bool { - match blob { - | Blob.NoBlob => return true; - | Blob.SomeBytes(_) => return false; - } + function isEmpty() public returns (bool) { + match (blob) { +case Blob.NoBlob { +return true; +} +case Blob.SomeBytes(_) { +return false; +} +} } } diff --git a/tests/e2e/storage-index-order/main.sol b/tests/e2e/storage-index-order/main.sol index 6964d64a..668c70b4 100644 --- a/tests/e2e/storage-index-order/main.sol +++ b/tests/e2e/storage-index-order/main.sol @@ -1,11 +1,11 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract StorageIndexOrder { counter: word; - m: mapping(word, word); + m: mapping(word => word); - function next() -> word { + function next() returns (word) { let cur: word = counter; let res: word; assembly { @@ -16,7 +16,7 @@ contract StorageIndexOrder { } // #[() -> 2] - public function run() -> uint256 { + function run() public returns (uint256) { counter = 0; m[1] = 0; m[2] = 0; @@ -31,7 +31,7 @@ contract StorageIndexOrder { return uint256(packed); } - function get(k: word) -> word { + function get(k: word) returns (word) { return m[k]; } } diff --git a/tests/e2e/storage/main.sol b/tests/e2e/storage/main.sol index a1a53781..f7ff51e2 100644 --- a/tests/e2e/storage/main.sol +++ b/tests/e2e/storage/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage support for a `memory(bytes)` contract field: assigning to the // field copies the byte array into storage, reading it back loads it into @@ -7,11 +7,11 @@ import std.dispatch.{*}; contract C { content: bytes; - public function set(value: memory(bytes)) -> () { + function set(value: memory) public { content = value; } - public function get() -> memory(bytes) { + function get() public returns (memory) { return content; } } diff --git a/tests/e2e/stringlit/main.sol b/tests/e2e/stringlit/main.sol index 6136d366..31d4260e 100644 --- a/tests/e2e/stringlit/main.sol +++ b/tests/e2e/stringlit/main.sol @@ -1,6 +1,6 @@ -import std.{*}; -import std.{memory, string, uint256}; -import std.dispatch.{*}; +import * from std; +import {memory, string, uint256} from std; +import * from std.dispatch; pragma no-patterson-condition ; pragma no-coverage-condition ; pragma no-bounded-variable-condition ; @@ -11,14 +11,14 @@ contract C { constructor() {} // terse: concatLit wrapped in Str.fromString by the desugarer - public function greeting() -> memory(string) { + function greeting() public returns (memory) { return concatLit("Hello, ", "world!"); // fromString inserted automatically when using concatLit // later we may have an operator for that e.g. <> } // A2: via an intermediate string-typed let (dead-let substitution path) - public function greetLet() -> memory(string) { + function greetLet() public returns (memory) { let s : string = "Hello, " + "world!"; return Str.fromString(s); // here fromString needs to be inserted manually diff --git a/tests/e2e/sum-wide-product/main.sol b/tests/e2e/sum-wide-product/main.sol index 259047a9..50a9ce58 100644 --- a/tests/e2e/sum-wide-product/main.sol +++ b/tests/e2e/sum-wide-product/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Regression test for a yule backend bug, independent of the storage/Generic // work: matching a sum constructor whose payload is a product of arity >= 3. @@ -12,18 +12,22 @@ import std.dispatch.{*}; // No storage and no Generic derivation involved — just constructing and matching // an ordinary algebraic data type. -data Shape = Dot | Tri(uint256, uint256, uint256); +enum Shape { Dot, Tri(uint256, uint256, uint256) } contract C { constructor() {} // Build Tri(a,b,c) then match it back out: exercises a sum whose payload is // a 3-field product. - public function triSum(a : uint256, b : uint256, c : uint256) -> uint256 { + function triSum(a: uint256, b: uint256, c: uint256) public returns (uint256) { let s : Shape = Shape.Tri(a, b, c); - match s { - | Shape.Dot => return uint256(0); - | Shape.Tri(x, y, z) => return x + y + z; - } + match (s) { +case Shape.Dot { +return uint256(0); +} +case Shape.Tri(x, y, z) { +return x + y + z; +} +} } } diff --git a/tests/e2e/ufcs-array/main.sol b/tests/e2e/ufcs-array/main.sol index 53d7855e..afbe95ca 100644 --- a/tests/e2e/ufcs-array/main.sol +++ b/tests/e2e/ufcs-array/main.sol @@ -1,13 +1,13 @@ -import std.{*}; -import std.dispatch.{*}; -import std.opcodes.{mload, mstore}; +import * from std; +import * from std.dispatch; +import {mload, mstore} from std.opcodes; -// UFCS counterpart of storage_array.solc. +// UFCS counterpart of storage_array.sol. // // This contract is byte-for-byte equivalent in behaviour to -// dispatch/storage_array.solc, but exercises the receiver-style method-call +// dispatch/storage_array.sol, but exercises the receiver-style method-call // sugar resolved by NameResolution: when the receiver of recv.method(args) -// is an (unqualified) contract field and a unique class exposes method, the +// is an (unqualified) contract field and a unique trait exposes the method, the // call is rewritten to Class.method(recv, args). So: // // members.push(addr) ==> ArrayPush.push(members, addr) @@ -19,16 +19,16 @@ import std.opcodes.{mload, mstore}; // the same runtime behaviour. Indexed access members[i] is unaffecte: it // is handled by field-access desugaring, not UFCS. contract MemberRegistry { - members : array(address); + members : array
; constructor() {} - public function addMember(addr : address) -> () { + function addMember(addr: address) public { members.push(addr); } // MemberNotFound() selector - public function removeMember(addr : address) -> () { + function removeMember(addr: address) public { // foundIdx == length() acts as the "not found" sentinel. let foundIdx : uint256 = members.length(); let i : uint256; @@ -48,11 +48,11 @@ contract MemberRegistry { members.pop(); } - public function numberOfMembers() -> uint256 { + function numberOfMembers() public returns (uint256) { return members.length(); } - public function getMembers() -> memory(DynArray(address)) { + function getMembers() public returns (memory>) { let count : word = Typedef.rep(members.length()); let totalBytes : word = (count + 1) * 32; let ptr : word = allocate_memory(totalBytes); @@ -63,6 +63,6 @@ contract MemberRegistry { let addr : address = members[uint256(i)]; mstore(ptr + 32 + i * 32, Typedef.rep(addr)); } - return Typedef.abs(ptr) : memory(DynArray(address)); + return Typedef.abs(ptr) ; } } diff --git a/tests/e2e/weth9/main.sol b/tests/e2e/weth9/main.sol index bd3125ea..b4a25395 100644 --- a/tests/e2e/weth9/main.sol +++ b/tests/e2e/weth9/main.sol @@ -1,37 +1,37 @@ -import std.{*}; -import std.opcodes.{caller as caller_, callvalue as callvalue_, selfbalance, gas, call}; -import std.dispatch.{*}; +import * from std; +import {caller as caller_, callvalue as callvalue_, selfbalance, gas, call} from std.opcodes; +import * from std.dispatch; // Forward `wad` wei to `dst` via a zero-data CALL and revert on failure. -function sendValue(dst: address, wad: uint256) -> () { +function sendValue(dst: address, wad: uint256) { let ret = call(gas(), Typedef.rep(dst), Typedef.rep(wad), 0, 0, 0, 0); require(ret != 0, Error(0x90b8ec18)); // TransferFailed() } -function caller() -> address { +function caller() returns (address) { return address(caller_()); } -function callvalue() -> uint256 { +function callvalue() returns (uint256) { return uint256(callvalue_()); } // Based on https://github.com/gnosis/canonical-weth/blob/master/contracts/WETH9.sol // That code is written WITHOUT checked arithmetic. contract WETH9 { - balances : mapping(address, uint256); - allowance : mapping(address, mapping(address, uint256)); + balances : mapping(address => uint256); + allowance : mapping(address => mapping(address => uint256)); constructor() {} // --- ETH <-> WETH --- - public payable function deposit() -> () { + function deposit() public payable { let sender = caller(); balances[sender] = balances[sender] + callvalue(); } - public function withdraw(wad: uint256) -> () { + function withdraw(wad: uint256) public { let sender = caller(); require(balances[sender] >= wad, Error(0xf4d678b8)); // InsufficientBalance() balances[sender] = balances[sender] - wad; @@ -39,35 +39,35 @@ contract WETH9 { } // totalSupply == ETH held by this contract (matches canonical WETH9). - public function totalSupply() -> uint256 { + function totalSupply() public returns (uint256) { return uint256(selfbalance()); } // --- ERC20 surface --- - public function balanceOf(account: address) -> uint256 { + function balanceOf(account: address) public returns (uint256) { return balances[account]; } - public function allowance(owner_: address, spender: address) -> uint256 { + function allowance(owner_: address, spender: address) public returns (uint256) { return allowance[owner_][spender]; } - public function approve(usr: address, wad: uint256) -> bool { + function approve(usr: address, wad: uint256) public returns (bool) { let sender = caller(); allowance[sender][usr] = wad; return true; } - public function transfer(dst: address, wad: uint256) -> bool { + function transfer(dst: address, wad: uint256) public returns (bool) { return transferFrom(caller(), dst, wad); } - public function transferFrom(src: address, dst: address, wad: uint256) -> bool { + function transferFrom(src: address, dst: address, wad: uint256) public returns (bool) { let sender = caller(); require(balances[src] >= wad, Error(0xf4d678b8)); // InsufficientBalance() - if (src != sender && allowance[src][sender] != (maxVal():uint256)) { + if (src != sender && allowance[src][sender] != (maxVal())) { require(allowance[src][sender] >= wad, Error(0x13be252b)); // InsufficientAllowance() allowance[src][sender] -= wad; } @@ -77,7 +77,7 @@ contract WETH9 { } // Plain ETH transfers (no calldata, just value) auto-wrap into WETH. - payable fallback() -> () { + fallback() payable { let sender = caller(); balances[sender] = balances[sender] + callvalue(); } diff --git a/tests/e2e/yul-special-identifiers/main.sol b/tests/e2e/yul-special-identifiers/main.sol index a1a5f779..349ee529 100644 --- a/tests/e2e/yul-special-identifiers/main.sol +++ b/tests/e2e/yul-special-identifiers/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract YulSpecialIdentifiers { constructor() {} @@ -7,7 +7,7 @@ contract YulSpecialIdentifiers { // Standard Yul identifiers may start with `_` or `$` and may contain `$`. // This exercises those names through both executable backends. // #[() -> 42] - public function identifiers() -> uint256 { + function identifiers() public returns (uint256) { let result : word; assembly { function $add(_left, right$) -> _total { From 5d62c99b027bf205863985479e02178b561987ae Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 095/110] Switch the compiler and fixtures to canonical syntax: uitest Co-authored-by: Codex --- crates/uitest/tests/diagnostics.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/uitest/tests/diagnostics.rs b/crates/uitest/tests/diagnostics.rs index 9a1bda5b..29e7e91d 100644 --- a/crates/uitest/tests/diagnostics.rs +++ b/crates/uitest/tests/diagnostics.rs @@ -17,14 +17,14 @@ define_frontend_test_db!(TestDb, hir_ty); #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/parse", - glob: "**/main.solc" + glob: "**/main.sol" )] fn parse_fail_diagnostics(fixture: Fixture<&str>) { let path = fixture.path().to_owned(); let source = fixture.content().to_string(); run_in_large_stack(move || { let db = TestDb::default(); - let diagnostics = parse_diagnostics_for_source(&db, "main.solc", &source); + let diagnostics = parse_diagnostics_for_source(&db, "main.sol", &source); assert_failure_snapshot( &db, Path::new(&path).parent().expect("case dir"), @@ -35,7 +35,7 @@ fn parse_fail_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/nameres", - glob: "**/main.solc" + glob: "**/main.sol" )] fn nameres_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_case(fixture, |db, entry| nameres_diagnostics(db, &entry)); @@ -43,7 +43,7 @@ fn nameres_fail_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/typeck", - glob: "**/main.solc" + glob: "**/main.sol" )] fn typeck_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_case_with_dependencies(fixture, full_frontend_diagnostics); @@ -51,7 +51,7 @@ fn typeck_fail_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/solver", - glob: "**/main.solc" + glob: "**/main.sol" )] fn solver_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_case_with_dependencies(fixture, full_frontend_diagnostics); @@ -59,7 +59,7 @@ fn solver_fail_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/comptime", - glob: "**/main.solc" + glob: "**/main.sol" )] fn comptime_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_case(fixture, specialize_diagnostics); @@ -67,7 +67,7 @@ fn comptime_fail_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/specialize", - glob: "**/main.solc" + glob: "**/main.sol" )] fn specialize_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_case(fixture, specialize_diagnostics); @@ -75,7 +75,7 @@ fn specialize_fail_diagnostics(fixture: Fixture<&str>) { #[dir_test( dir: "$CARGO_MANIFEST_DIR/tests/fixtures/hull", - glob: "**/main.solc" + glob: "**/main.sol" )] fn hull_fail_diagnostics(fixture: Fixture<&str>) { run_fixture_case_with_dependencies(fixture, hull_diagnostics); From 7f3b15cd3e1125e3f9316173d00d9660ef289262 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 096/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures Co-authored-by: Codex --- .../comptime/ct_asm_ret/diagnostics.snap | 4 +- .../fixtures/comptime/ct_asm_ret/main.sol | 4 +- .../comptime/ct_let_runtime/diagnostics.snap | 10 ++-- .../fixtures/comptime/ct_let_runtime/main.sol | 6 +-- .../ct_overloaded_bad/diagnostics.snap | 20 ++++---- .../comptime/ct_overloaded_bad/main.sol | 12 ++--- .../ct_param_poly_runtime/diagnostics.snap | 6 +-- .../comptime/ct_param_poly_runtime/main.sol | 12 ++--- .../ct_param_runtime/diagnostics.snap | 12 ++--- .../comptime/ct_param_runtime/main.sol | 6 +-- .../comptime/ct_runtime_arg/diagnostics.snap | 12 ++--- .../fixtures/comptime/ct_runtime_arg/main.sol | 6 +-- .../ergo_ct_fuel_infinite/diagnostics.snap | 6 +-- .../comptime/ergo_ct_fuel_infinite/main.sol | 4 +- .../diagnostics.snap | 10 ++-- .../ergo_ct_let_runtime_param/main.sol | 6 +-- .../diagnostics.snap | 4 +- .../hull/assembly_assign_no_return/main.sol | 2 +- .../assembly_assign_non_word/diagnostics.snap | 10 ++-- .../hull/assembly_assign_non_word/main.sol | 4 +- .../diagnostics.snap | 4 +- .../hull/assembly_multi_return_arity/main.sol | 2 +- .../ergo_hull_multi_error/diagnostics.snap | 10 ++-- .../hull/ergo_hull_multi_error/main.sol | 4 +- .../ergo_hull_string_return/diagnostics.snap | 14 +++--- .../hull/ergo_hull_string_return/main.sol | 13 +++-- .../diagnostics.snap | 12 ++--- .../ergo_hull_word_match_no_default/main.sol | 18 ++++--- .../non_exhaustive_match/diagnostics.snap | 12 ++--- .../hull/non_exhaustive_match/main.sol | 16 ++++--- .../hull/ok_dispatch_storage/diagnostics.snap | 2 +- .../hull/ok_dispatch_storage/main.sol | 8 ++-- .../hull/ok_fallback_unit/diagnostics.snap | 6 +++ .../fixtures/hull/ok_fallback_unit/main.sol | 8 ++++ .../diagnostics.snap | 2 +- .../ok_guarded_runtime_recursion/main.sol | 6 +-- .../diagnostics.snap | 15 ------ .../main.solc | 8 ---- .../nameres/ambiguous/diagnostics.snap | 10 ++-- .../tests/fixtures/nameres/ambiguous/main.sol | 4 +- .../clean_undefined_name/diagnostics.snap | 8 ++-- .../nameres/clean_undefined_name/main.sol | 2 +- .../duplicate_export_cross_namespace/a.sol | 2 +- .../duplicate_export_cross_namespace/b.sol | 2 +- .../diagnostics.snap | 4 +- .../duplicate_export_cross_namespace/main.sol | 2 +- .../diagnostics.snap | 8 ++-- .../duplicate_local_declarations/main.sol | 2 +- .../duplicate_qualifier/diagnostics.snap | 4 +- .../duplicate_selector/diagnostics.snap | 12 ++--- .../nameres/duplicate_selector/main.sol | 2 +- .../ergo_dup_data_class/diagnostics.snap | 22 ++++----- .../nameres/ergo_dup_data_class/main.sol | 12 ++--- .../ergo_dup_function/diagnostics.snap | 8 ++-- .../nameres/ergo_dup_function/main.sol | 6 +-- .../ergo_import_module_typo/diagnostics.snap | 10 ++-- .../ergo_import_module_typo/helpers.sol | 2 +- .../nameres/ergo_import_module_typo/main.sol | 4 +- .../ergo_import_symbol_typo/diagnostics.snap | 10 ++-- .../nameres/ergo_import_symbol_typo/main.sol | 4 +- .../nameres/ergo_import_symbol_typo/util.sol | 2 +- .../ergo_private_qualified/diagnostics.snap | 10 ++-- .../nameres/ergo_private_qualified/main.sol | 2 +- .../nameres/ergo_private_qualified/vault.sol | 4 +- .../ergo_typo_did_you_mean/diagnostics.snap | 6 +-- .../nameres/ergo_typo_did_you_mean/main.sol | 4 +- .../nameres/ergo_undef_class/diagnostics.snap | 12 ++--- .../nameres/ergo_undef_class/main.sol | 4 +- .../ergo_undef_constructor/diagnostics.snap | 12 ++--- .../nameres/ergo_undef_constructor/main.sol | 16 ++++--- .../nameres/ergo_undef_type/diagnostics.snap | 6 +-- .../fixtures/nameres/ergo_undef_type/main.sol | 2 +- .../ergo_undef_variable/diagnostics.snap | 6 +-- .../nameres/ergo_undef_variable/main.sol | 2 +- .../ergo_unqual_ctor_sc0106/diagnostics.snap | 10 ++-- .../nameres/ergo_unqual_ctor_sc0106/main.sol | 20 ++++---- .../ergo_value_as_type/diagnostics.snap | 10 ++-- .../nameres/ergo_value_as_type/main.sol | 12 +++-- .../glob_shadow_local/diagnostics.snap | 10 ++-- .../nameres/glob_shadow_local/lib.sol | 2 +- .../nameres/glob_shadow_local/main.sol | 4 +- .../nameres/hidden_ctor/diagnostics.snap | 6 +-- .../fixtures/nameres/hidden_ctor/lib.sol | 4 +- .../fixtures/nameres/hidden_ctor/main.sol | 4 +- .../fixtures/nameres/missing/diagnostics.snap | 8 ++-- .../tests/fixtures/nameres/missing/main.sol | 2 +- .../a.sol | 2 +- .../b.sol | 2 +- .../diagnostics.snap | 10 ++-- .../main.sol | 6 +-- .../a.sol | 4 +- .../b.sol | 4 +- .../diagnostics.snap | 18 +++---- .../main.sol | 6 +-- .../string_type_annotation/diagnostics.snap | 8 ++-- .../nameres/string_type_annotation/main.sol | 2 +- .../diagnostics.snap | 22 ++++----- .../undefined_name_namespaces/main.sol | 2 +- .../nameres/unknown_import/diagnostics.snap | 8 ++-- .../fixtures/nameres/unknown_import/main.sol | 2 +- .../diagnostics.snap | 48 +++++++++---------- .../main.sol | 36 ++++++++------ .../unqualified_ctor_expr/diagnostics.snap | 10 ++-- .../nameres/unqualified_ctor_expr/main.sol | 18 ++++--- .../diagnostics.snap | 16 +++---- .../nameres/unqualified_ctor_imported/lib.sol | 2 +- .../unqualified_ctor_imported/main.sol | 18 ++++--- .../unqualified_ctor_pattern/diagnostics.snap | 14 +++--- 108 files changed, 461 insertions(+), 433 deletions(-) create mode 100644 crates/uitest/tests/fixtures/hull/ok_fallback_unit/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/hull/ok_fallback_unit/main.sol delete mode 100644 crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/main.solc diff --git a/crates/uitest/tests/fixtures/comptime/ct_asm_ret/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ct_asm_ret/diagnostics.snap index 620ac301..c225c3b4 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_asm_ret/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ct_asm_ret/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol --- error[SC0409]: comptime evaluation failed: function annotated '-> comptime' returns a runtime expression - --> /main/main.solc:12:5 + --> /main/main.sol:12:5 | 11 | } 12 | return v; diff --git a/crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol b/crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol index b0d3893b..3ba34ae7 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ct_asm_ret/main.sol @@ -4,14 +4,14 @@ */ contract ComptimeAsmRet { - function loadFromStorage() -> comptime word { + function loadFromStorage() returns (comptime) { let v : word; assembly { v := sload(0) } return v; } - function main() -> word { + function main() returns (word) { return loadFromStorage(); } } diff --git a/crates/uitest/tests/fixtures/comptime/ct_let_runtime/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ct_let_runtime/diagnostics.snap index 4515e9bc..01d0a3b8 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_let_runtime/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ct_let_runtime/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol --- error[SC0409]: comptime evaluation failed: comptime let 'y' is bound to a runtime expression - --> /main/main.solc:18:5 + --> /main/main.sol:18:5 | -17 | function main() -> word { -18 | let y : comptime word = sloadWord(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here +17 | function main() returns (word) { +18 | let y : comptime = sloadWord(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here 19 | return y; | diff --git a/crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol b/crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol index 2db7a7d6..16c9def3 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ct_let_runtime/main.sol @@ -5,7 +5,7 @@ */ import std; -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -14,8 +14,8 @@ function sloadWord() -> word { } contract ComptimeLetRuntime { - function main() -> word { - let y : comptime word = sloadWord(); + function main() returns (word) { + let y : comptime = sloadWord(); return y; } } diff --git a/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/diagnostics.snap index b4e1636e..0ac3209a 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol --- error[SC0409]: comptime evaluation failed: function annotated '-> comptime' returns a runtime expression - --> /main/main.solc:18:5 + --> /main/main.sol:18:5 | 17 | } 18 | return base + x * factor; @@ -14,30 +14,30 @@ error[SC0409]: comptime evaluation failed: function annotated '-> comptime' retu --- error[SC0406]: missing evidence: add - --> /main/main.solc:18:12 + --> /main/main.sol:18:12 | 17 | } 18 | return base + x * factor; - | ^^^^^^^^^^^^^^^^^ class evidence required here + | ^^^^^^^^^^^^^^^^^ trait evidence required here 19 | } | --- error[SC0406]: missing evidence: mul - --> /main/main.solc:18:19 + --> /main/main.sol:18:19 | 17 | } 18 | return base + x * factor; - | ^^^^^^^^^^ class evidence required here + | ^^^^^^^^^^ trait evidence required here 19 | } | --- error[SC0409]: comptime evaluation failed: comptime let 'a' is bound to a runtime expression - --> /main/main.solc:24:5 + --> /main/main.sol:24:5 | -23 | function main() -> word { -24 | let a : comptime word = Scale.scale(3, 10); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here +23 | function main() returns (word) { +24 | let a : comptime = Scale.scale(3, 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here 25 | return a; | diff --git a/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol b/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol index 68042e0a..19af3db5 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ct_overloaded_bad/main.sol @@ -5,12 +5,12 @@ */ import std; -forall a. class a : Scale { - function scale(comptime factor : word, comptime x : a) -> comptime a; +trait Scale { + function scale(comptime factor: word, comptime x: a) returns (comptime) ; } -instance word : Scale { - function scale(comptime factor : word, comptime x : word) -> comptime word { +impl Scale { + function scale(comptime factor: word, comptime x: word) returns (comptime) { let base : word; assembly { base := sload(0) @@ -20,8 +20,8 @@ instance word : Scale { } contract ComptimeOverloadedBad { - function main() -> word { - let a : comptime word = Scale.scale(3, 10); + function main() returns (word) { + let a : comptime = Scale.scale(3, 10); return a; } } diff --git a/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/diagnostics.snap index 8669f4db..d8889107 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol --- error[SC0409]: comptime evaluation failed: runtime value passed to comptime parameter 'x' of 'unwrap' - --> /main/main.solc:20:10 + --> /main/main.sol:20:10 | -19 | forall t. t:Wrap => function process(z : t) -> word { +19 | function process(z: t) returns (word) where t: Wrap { 20 | return Wrap.unwrap(z); | ^^^^^^^^^^^^^^ comptime evaluation failed here 21 | } diff --git a/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol b/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol index e67a24c1..66341e77 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ct_param_poly_runtime/main.sol @@ -6,22 +6,22 @@ */ import std; -forall t. class t : Wrap { - function unwrap(comptime x : t) -> comptime word; +trait Wrap { + function unwrap(comptime x: t) returns (comptime) ; } -instance word : Wrap { - function unwrap(comptime x : word) -> comptime word { +impl Wrap { + function unwrap(comptime x: word) returns (comptime) { return x; } } -forall t. t:Wrap => function process(z : t) -> word { +function process(z: t) returns (word) where t: Wrap { return Wrap.unwrap(z); } contract ComptimeParamPolyRuntime { - function main() -> word { + function main() returns (word) { return process(42); } } diff --git a/crates/uitest/tests/fixtures/comptime/ct_param_runtime/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ct_param_runtime/diagnostics.snap index c002bef0..df0bff94 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_param_runtime/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ct_param_runtime/diagnostics.snap @@ -1,22 +1,22 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol --- error[SC0406]: missing evidence: add - --> /main/main.solc:11:12 + --> /main/main.sol:11:12 | -10 | function double(comptime x : word) -> comptime word { +10 | function double(comptime x: word) returns (comptime) { 11 | return x + x; - | ^^^^^ class evidence required here + | ^^^^^ trait evidence required here 12 | } | --- error[SC0409]: comptime evaluation failed: runtime value passed to comptime parameter 'x' of 'double' - --> /main/main.solc:14:12 + --> /main/main.sol:14:12 | -13 | function process(value : word) -> word { +13 | function process(value: word) returns (word) { 14 | return double(value); | ^^^^^^^^^^^^^ comptime evaluation failed here 15 | } diff --git a/crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol b/crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol index 496cb2a7..d9dd45f3 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ct_param_runtime/main.sol @@ -7,13 +7,13 @@ import std; contract ComptimeParamRuntime { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function process(value : word) -> word { + function process(value: word) returns (word) { return double(value); } - function main() -> word { + function main() returns (word) { return process(21); } } diff --git a/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/diagnostics.snap index ea6836e5..6083a724 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/diagnostics.snap @@ -1,22 +1,22 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol --- error[SC0406]: missing evidence: add - --> /main/main.solc:17:12 + --> /main/main.sol:17:12 | -16 | function double(comptime x : word) -> comptime word { +16 | function double(comptime x: word) returns (comptime) { 17 | return x + x; - | ^^^^^ class evidence required here + | ^^^^^ trait evidence required here 18 | } | --- error[SC0409]: comptime evaluation failed: runtime value passed to comptime parameter 'x' of 'double' - --> /main/main.solc:20:12 + --> /main/main.sol:20:12 | -19 | function main() -> word { +19 | function main() returns (word) { 20 | return double(sloadWord()); | ^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here 21 | } diff --git a/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol b/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol index ed9e0132..d40acb84 100644 --- a/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ct_runtime_arg/main.sol @@ -4,7 +4,7 @@ */ import std; -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -13,10 +13,10 @@ function sloadWord() -> word { } contract ComptimeRuntimeArg { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function main() -> word { + function main() returns (word) { return double(sloadWord()); } } diff --git a/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/diagnostics.snap index 7609fcf5..15d43fb5 100644 --- a/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol --- error[SC0410]: comptime evaluation fuel exhausted in spin at 128 unfold steps - --> /main/main.solc:6:10 + --> /main/main.sol:6:10 | -5 | function spin(comptime n : integer) -> comptime integer { +5 | function spin(comptime n: integer) returns (comptime) { 6 | return spin(integerAdd(n, 1)); | ^^^^^^^^^^^^^^^^^^^^^^ comptime fuel limit reached here 7 | } diff --git a/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol b/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol index 273b9d4e..1b79d188 100644 --- a/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ergo_ct_fuel_infinite/main.sol @@ -2,12 +2,12 @@ // recursive evaluator before the larger total-work fuel budget is consumed. import std; -function spin(comptime n : integer) -> comptime integer { +function spin(comptime n: integer) returns (comptime) { return spin(integerAdd(n, 1)); } contract CtFuelInfinite { - function main() -> word { + function main() returns (word) { return wordFromInteger(spin(0)); } } diff --git a/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/diagnostics.snap b/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/diagnostics.snap index 63b683ab..470f6051 100644 --- a/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/diagnostics.snap +++ b/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.solc +input_file: crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol --- error[SC0401]: cannot specialize expression: type is not concrete - --> /main/main.solc:7:33 + --> /main/main.sol:7:34 | -6 | function scale(k : word) -> word { -7 | let c : comptime word = k + 1; - | ^ type must be concrete here +6 | function scale(k: word) returns (word) { +7 | let c : comptime = k + 1; + | ^ type must be concrete here 8 | return c; | = note: this can happen when a constructor or expression leaves a type parameter unresolved diff --git a/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol b/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol index a97563fb..5f131aa8 100644 --- a/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol +++ b/crates/uitest/tests/fixtures/comptime/ergo_ct_let_runtime_param/main.sol @@ -3,11 +3,11 @@ import std; contract CtLetRuntimeParam { - function scale(k : word) -> word { - let c : comptime word = k + 1; + function scale(k: word) returns (word) { + let c : comptime = k + 1; return c; } - function main() -> word { + function main() returns (word) { let v : word; assembly { v := sload(0) diff --git a/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/diagnostics.snap b/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/diagnostics.snap index c02a1784..e86c925c 100644 --- a/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.solc +input_file: crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol --- error[SC0445]: inline assembly assignment returns 0 values, expected 1 - --> /main/main.solc:6:12 + --> /main/main.sol:6:12 | 5 | assembly { 6 | x := mstore(1, 1) diff --git a/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol b/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol index 445bb347..05809a5b 100644 --- a/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol +++ b/crates/uitest/tests/fixtures/hull/assembly_assign_no_return/main.sol @@ -1,6 +1,6 @@ // mstore does not return a value, so it cannot be assigned. contract Test { - public function main() -> word { + function main() public returns (word) { let x : word; assembly { x := mstore(1, 1) diff --git a/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/diagnostics.snap b/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/diagnostics.snap index 5e3479f2..9ea4d003 100644 --- a/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.solc +input_file: crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol --- error[SC0434]: Hull type mismatch: expected (unit + unit), got word - --> /main/main.solc:7:9 + --> /main/main.sol:7:9 | -6 | public function main() -> word { +6 | function main() public returns (word) { 7 | let b : bool = false; | ^ type mismatch 8 | assembly { b := add(1, 1) } @@ -14,10 +14,10 @@ error[SC0434]: Hull type mismatch: expected (unit + unit), got word --- error[SC0448]: inline assembly assignment to `b` requires word type, got (unit + unit) - --> /main/main.solc:8:16 + --> /main/main.sol:8:16 | 7 | let b : bool = false; 8 | assembly { b := add(1, 1) } | ^^^^^^^^^^^^^^ assembly assignment must be word -9 | if b { return 1; } else { return 0; } +9 | if ( b ) { return 1; } else { return 0; } | diff --git a/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol b/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol index be96a1bb..d77b3f7f 100644 --- a/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol +++ b/crates/uitest/tests/fixtures/hull/assembly_assign_non_word/main.sol @@ -3,9 +3,9 @@ // is a tagged inl/inr pair) would corrupt that layout, so the type checker // must reject this program. contract AsmBool { - public function main() -> word { + function main() public returns (word) { let b : bool = false; assembly { b := add(1, 1) } - if b { return 1; } else { return 0; } + if ( b ) { return 1; } else { return 0; } } } diff --git a/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/diagnostics.snap b/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/diagnostics.snap index 90148e27..b5eff43d 100644 --- a/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.solc +input_file: crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol --- error[SC0445]: inline assembly assignment returns 2 values, expected 3 - --> /main/main.solc:11:18 + --> /main/main.sol:11:18 | 10 | } 11 | x, y, z := pair() diff --git a/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol b/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol index 02263c08..c83ab153 100644 --- a/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol +++ b/crates/uitest/tests/fixtures/hull/assembly_multi_return_arity/main.sol @@ -1,5 +1,5 @@ contract YulMultiRetBad { - public function main() -> word { + function main() public returns (word) { let x : word; let y : word; let z : word; diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/diagnostics.snap b/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/diagnostics.snap index b6fbf316..8505051a 100644 --- a/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.solc +input_file: crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol --- error[SC0421]: cannot lower literal `"oops"` to Hull - --> /main/main.solc:5:12 + --> /main/main.sol:5:12 | -4 | public function main() -> string { +4 | function main() public returns (string) { 5 | return "oops"; | ^^^^^^ unsupported literal 6 | } @@ -14,9 +14,9 @@ error[SC0421]: cannot lower literal `"oops"` to Hull --- error[SC0421]: cannot lower literal `"also bad"` to Hull - --> /main/main.solc:11:12 + --> /main/main.sol:11:12 | -10 | public function main() -> string { +10 | function main() public returns (string) { 11 | return "also bad"; | ^^^^^^^^^^ unsupported literal 12 | } diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol b/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol index 4bfcf091..e749ac19 100644 --- a/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol +++ b/crates/uitest/tests/fixtures/hull/ergo_hull_multi_error/main.sol @@ -1,13 +1,13 @@ // Two independent Hull-level problems in separate contracts: // string literals are not representable in Hull. contract First { - public function main() -> string { + function main() public returns (string) { return "oops"; } } contract Second { - public function main() -> string { + function main() public returns (string) { return "also bad"; } } diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/diagnostics.snap b/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/diagnostics.snap index 80c67d29..631ab476 100644 --- a/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/diagnostics.snap @@ -1,17 +1,17 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.solc +input_file: crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol --- error[SC0411]: runtime lowering cannot represent `string` in return type of `main` - --> /main/main.solc:4:3 + --> /main/main.sol:5:3 | -3 | contract Answer { -4 | / public function main() { -5 | | return "42"; -6 | | } +4 | contract Answer { +5 | / function main() returns (string) { +6 | | return helper(); +7 | | } | |___^ not representable at runtime -7 | } +8 | } | = note: `integer`, `string`, and `comptime` values must be eliminated before runtime lowering = note: help: evaluate the value at comptime or change it to a runtime-representable type diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol b/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol index a7804492..932cf2e4 100644 --- a/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol +++ b/crates/uitest/tests/fixtures/hull/ergo_hull_string_return/main.sol @@ -1,7 +1,12 @@ -// Mirrors reference corpus test/examples/cases/string-const.solc: -// a public function returning a string constant. +// A runtime function whose result type is not representable in Hull. +import {string} from std; + contract Answer { - public function main() { - return "42"; + function main() returns (string) { + return helper(); } } + +function helper() returns (string) { + return "42"; +} diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/diagnostics.snap b/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/diagnostics.snap index c9f9caa1..99cce396 100644 --- a/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.solc +input_file: crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol --- error[SC0302]: non-exhaustive pattern match - --> /main/main.solc:6:11 + --> /main/main.sol:6:12 | -5 | public function name(d : uint256) -> uint256 { -6 | match d { - | ^ match is not exhaustive -7 | | 0 => return 100; +5 | function name(d: uint256) public returns (uint256) { +6 | match (d) { + | ^ match is not exhaustive +7 | case 0 { | = note: missing case: _ = note: help: add a default or catch-all arm that covers the remaining values diff --git a/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol b/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol index 17e323e9..238a62e6 100644 --- a/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol +++ b/crates/uitest/tests/fixtures/hull/ergo_hull_word_match_no_default/main.sol @@ -1,11 +1,15 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Digits { - public function name(d : uint256) -> uint256 { - match d { - | 0 => return 100; - | 1 => return 101; - } + function name(d: uint256) public returns (uint256) { + match (d) { +case 0 { +return 100; +} +case 1 { +return 101; +} +} } } diff --git a/crates/uitest/tests/fixtures/hull/non_exhaustive_match/diagnostics.snap b/crates/uitest/tests/fixtures/hull/non_exhaustive_match/diagnostics.snap index 968ab0d3..8bb14641 100644 --- a/crates/uitest/tests/fixtures/hull/non_exhaustive_match/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/non_exhaustive_match/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.solc +input_file: crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol --- error[SC0302]: non-exhaustive pattern match - --> /main/main.solc:11:9 + --> /main/main.sol:11:10 | -10 | function onlyA(b : B) -> word { -11 | match b { - | ^ match is not exhaustive -12 | | B.A => return 1; +10 | function onlyA(b: B) returns (word) { +11 | match (b) { + | ^ match is not exhaustive +12 | case B.A { | = note: missing case: _ = note: help: add a default or catch-all arm that covers the remaining values diff --git a/crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol b/crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol index 130d7c8d..3b55153e 100644 --- a/crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol +++ b/crates/uitest/tests/fixtures/hull/non_exhaustive_match/main.sol @@ -1,20 +1,22 @@ -data B = A | C; +enum B { A, C } -function choose(x : bool) -> B { +function choose(x: bool) returns (B) { if (x) { return B.A; } return B.C; } -function onlyA(b : B) -> word { - match b { - | B.A => return 1; - } +function onlyA(b: B) returns (word) { + match (b) { +case B.A { +return 1; +} +} } contract C { - public function main() -> word { + function main() public returns (word) { let x: bool; assembly { x := calldataload(0) } return onlyA(choose(x)); diff --git a/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/diagnostics.snap b/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/diagnostics.snap index eb8caeec..d0b9ef69 100644 --- a/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/diagnostics.snap @@ -1,6 +1,6 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.solc +input_file: crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol --- no diagnostics diff --git a/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol b/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol index a1a53781..f7ff51e2 100644 --- a/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol +++ b/crates/uitest/tests/fixtures/hull/ok_dispatch_storage/main.sol @@ -1,5 +1,5 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // Storage support for a `memory(bytes)` contract field: assigning to the // field copies the byte array into storage, reading it back loads it into @@ -7,11 +7,11 @@ import std.dispatch.{*}; contract C { content: bytes; - public function set(value: memory(bytes)) -> () { + function set(value: memory) public { content = value; } - public function get() -> memory(bytes) { + function get() public returns (memory) { return content; } } diff --git a/crates/uitest/tests/fixtures/hull/ok_fallback_unit/diagnostics.snap b/crates/uitest/tests/fixtures/hull/ok_fallback_unit/diagnostics.snap new file mode 100644 index 00000000..541e546e --- /dev/null +++ b/crates/uitest/tests/fixtures/hull/ok_fallback_unit/diagnostics.snap @@ -0,0 +1,6 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/hull/ok_fallback_unit/main.sol +--- +no diagnostics diff --git a/crates/uitest/tests/fixtures/hull/ok_fallback_unit/main.sol b/crates/uitest/tests/fixtures/hull/ok_fallback_unit/main.sol new file mode 100644 index 00000000..8fda5aef --- /dev/null +++ b/crates/uitest/tests/fixtures/hull/ok_fallback_unit/main.sol @@ -0,0 +1,8 @@ +import * from std; +import * from std.dispatch; + +contract C { + fallback() { + return; + } +} diff --git a/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/diagnostics.snap b/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/diagnostics.snap index 2b82fff6..72702a57 100644 --- a/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/diagnostics.snap +++ b/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/diagnostics.snap @@ -1,6 +1,6 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.solc +input_file: crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol --- no diagnostics diff --git a/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol b/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol index 67ecd180..56451306 100644 --- a/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol +++ b/crates/uitest/tests/fixtures/hull/ok_guarded_runtime_recursion/main.sol @@ -1,6 +1,6 @@ -import std.{*}; +import * from std; -function countdown(n: word) -> word { +function countdown(n: word) returns (word) { if (n == 0) { return 0; } else { @@ -9,7 +9,7 @@ function countdown(n: word) -> word { } contract Counter { - public function main() -> word { + function main() public returns (word) { return countdown(3); } } diff --git a/crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/diagnostics.snap b/crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/diagnostics.snap deleted file mode 100644 index f342931f..00000000 --- a/crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/diagnostics.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/main.solc ---- -error[SC0231]: fallback ABI must be unit -> unit - --> /main/main.solc:5:3 - | -4 | contract C { -5 | / fallback() -> word { -6 | | return 1; -7 | | } - | |___^ unsupported fallback ABI -8 | } - | diff --git a/crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/main.solc b/crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/main.solc deleted file mode 100644 index 161fc5ec..00000000 --- a/crates/uitest/tests/fixtures/hull/unsupported_public_fallback_return/main.solc +++ /dev/null @@ -1,8 +0,0 @@ -import std.{*}; -import std.dispatch.{*}; - -contract C { - fallback() -> word { - return 1; - } -} diff --git a/crates/uitest/tests/fixtures/nameres/ambiguous/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ambiguous/diagnostics.snap index 1f2714f1..75482771 100644 --- a/crates/uitest/tests/fixtures/nameres/ambiguous/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ambiguous/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ambiguous/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ambiguous/main.sol --- error[SC0120]: ambiguous selected import `value` in term namespace - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | -1 | import a.{value}; - | ^^^^^^^^^^^^^^^^^ ambiguous selected import in term namespace -2 | import b.{value}; +1 | import {value} from a; + | ^^^^^^^^^^^^^^^^^^^^^^ ambiguous selected import in term namespace +2 | import {value} from b; | = note: `value` is imported from a, b in term namespace = note: use an explicit module qualifier or narrow the selected imports diff --git a/crates/uitest/tests/fixtures/nameres/ambiguous/main.sol b/crates/uitest/tests/fixtures/nameres/ambiguous/main.sol index 02ca1356..285a6509 100644 --- a/crates/uitest/tests/fixtures/nameres/ambiguous/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ambiguous/main.sol @@ -1,2 +1,2 @@ -import a.{value}; -import b.{value}; +import {value} from a; +import {value} from b; diff --git a/crates/uitest/tests/fixtures/nameres/clean_undefined_name/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/clean_undefined_name/diagnostics.snap index 2c73e8b1..d4c87dd8 100644 --- a/crates/uitest/tests/fixtures/nameres/clean_undefined_name/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/clean_undefined_name/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.solc +input_file: crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol --- error[SC0101]: undefined name: missing - --> /main/main.solc:1:36 + --> /main/main.sol:1:43 | -1 | function caller() -> word { return missing; } - | ^^^^^^^ unknown name +1 | function caller() returns (word) { return missing; } + | ^^^^^^^ unknown name diff --git a/crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol b/crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol index 524bf823..21f048b4 100644 --- a/crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol +++ b/crates/uitest/tests/fixtures/nameres/clean_undefined_name/main.sol @@ -1 +1 @@ -function caller() -> word { return missing; } +function caller() returns (word) { return missing; } diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.sol b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.sol index 94fae05c..38437949 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.sol +++ b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/a.sol @@ -1,3 +1,3 @@ -data T = A; +enum T { A } export { T }; diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.sol b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.sol index 4f6e6ca6..89b0bcc5 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.sol +++ b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/b.sol @@ -1,4 +1,4 @@ -function T() -> word { +function T() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/diagnostics.snap index c808d4fc..d9ddeba7 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.solc +input_file: crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol --- error[SC0111]: duplicate exported item name `T` - --> /main/main.solc:2:11 + --> /main/main.sol:2:11 | 1 | export a.{T}; 2 | export b.{T}; diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol index 5e3a31ab..765499d0 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol +++ b/crates/uitest/tests/fixtures/nameres/duplicate_export_cross_namespace/main.sol @@ -1,6 +1,6 @@ export a.{T}; export b.{T}; -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/diagnostics.snap index 717a6f6a..bf62276c 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.solc +input_file: crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol --- error[SC0108]: duplicate declaration `Foo` in type namespace - --> /main/main.solc:2:6 + --> /main/main.sol:2:6 | -1 | data Foo = Foo; +1 | enum Foo { Foo } | --- previous declaration 2 | type Foo = word; | ^^^ duplicate declaration @@ -15,7 +15,7 @@ error[SC0108]: duplicate declaration `Foo` in type namespace --- error[SC0108]: duplicate declaration `dup` in term namespace - --> /main/main.solc:5:10 + --> /main/main.sol:5:10 | 3 | 4 | function dup() {} diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol b/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol index 53873613..3db86d09 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol +++ b/crates/uitest/tests/fixtures/nameres/duplicate_local_declarations/main.sol @@ -1,4 +1,4 @@ -data Foo = Foo; +enum Foo { Foo } type Foo = word; function dup() {} diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/diagnostics.snap index d15f7081..07f7a211 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/duplicate_qualifier/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/duplicate_qualifier/main.solc +input_file: crates/uitest/tests/fixtures/nameres/duplicate_qualifier/main.sol --- error[SC0116]: duplicate import qualifier `bar` - --> /main/main.solc:2:12 + --> /main/main.sol:2:12 | 1 | import foo.bar; | --- first qualifier with this name diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_selector/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/duplicate_selector/diagnostics.snap index 6b574b36..0979c8c8 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_selector/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/duplicate_selector/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/duplicate_selector/main.solc +input_file: crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol --- error[SC0117]: duplicate name `value` in selective import - --> /main/main.solc:1:21 + --> /main/main.sol:1:16 | -1 | import util.{value, value}; - | ----- ^^^^^ duplicate selected import - | | - | first selected import with this name +1 | import {value, value} from util; + | ----- ^^^^^ duplicate selected import + | | + | first selected import with this name | = note: list each selected or hidden name only once diff --git a/crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol b/crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol index 286b8c29..c6939c45 100644 --- a/crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol +++ b/crates/uitest/tests/fixtures/nameres/duplicate_selector/main.sol @@ -1 +1 @@ -import util.{value, value}; +import {value, value} from util; diff --git a/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/diagnostics.snap index 513e43eb..4b72e043 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/diagnostics.snap @@ -1,30 +1,30 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol --- error[SC0108]: duplicate declaration `Shape` in type namespace - --> /main/main.solc:3:6 + --> /main/main.sol:3:6 | -1 | data Shape = Circle(word); +1 | enum Shape { Circle(word) } | ----- previous declaration 2 | -3 | data Shape = Square(word); +3 | enum Shape { Square(word) } | ^^^^^ duplicate declaration 4 | | --- error[SC0108]: duplicate declaration `Render` in type namespace - --> /main/main.solc:9:20 + --> /main/main.sol:9:7 | 4 | - 5 | forall a . class a:Render { - | ------ previous declaration - 6 | function render(x: a) -> word; + 5 | trait Render { + | ------ previous declaration + 6 | function render(x: a) returns (word) ; 7 | } 8 | - 9 | forall a . class a:Render { - | ^^^^^^ duplicate declaration -10 | function paint(x: a) -> word; + 9 | trait Render { + | ^^^^^^ duplicate declaration +10 | function paint(x: a) returns (word) ; | diff --git a/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol index 4e727aa2..4a12014e 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_dup_data_class/main.sol @@ -1,11 +1,11 @@ -data Shape = Circle(word); +enum Shape { Circle(word) } -data Shape = Square(word); +enum Shape { Square(word) } -forall a . class a:Render { - function render(x: a) -> word; +trait Render { + function render(x: a) returns (word) ; } -forall a . class a:Render { - function paint(x: a) -> word; +trait Render { + function paint(x: a) returns (word) ; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_dup_function/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_dup_function/diagnostics.snap index e6f5d824..5e9d4b0d 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_dup_function/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_dup_function/diagnostics.snap @@ -1,18 +1,18 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol --- error[SC0108]: duplicate declaration `twice` in term namespace - --> /main/main.solc:9:10 + --> /main/main.sol:9:10 | - 1 | function twice(x: word) -> word { + 1 | function twice(x: word) returns (word) { | ----- previous declaration 2 | return x; 3 | } ... 8 | - 9 | function twice(x: word) -> word { + 9 | function twice(x: word) returns (word) { | ^^^^^ duplicate declaration 10 | return x; | diff --git a/crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol index 5f708955..e46ad4a7 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_dup_function/main.sol @@ -1,11 +1,11 @@ -function twice(x: word) -> word { +function twice(x: word) returns (word) { return x; } -function helper(y: word) -> word { +function helper(y: word) returns (word) { return y; } -function twice(x: word) -> word { +function twice(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/diagnostics.snap index e4ee7599..ff89f69d 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol --- error[SC0109]: import helprs: file not found - --> /main/main.solc:1:8 + --> /main/main.sol:1:27 | -1 | import helprs.{helperValue}; - | ^^^^^^ module reference +1 | import {helperValue} from helprs; + | ^^^^^^ module reference 2 | -3 | function main() -> word { +3 | function main() returns (word) { | = help: check the module path or add the missing source file = help: did you mean `helpers`? diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.sol b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.sol index e497c9f4..057993ab 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/helpers.sol @@ -1,5 +1,5 @@ export { helperValue }; -function helperValue(x: word) -> word { +function helperValue(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol index 7af60146..dca48485 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_import_module_typo/main.sol @@ -1,5 +1,5 @@ -import helprs.{helperValue}; +import {helperValue} from helprs; -function main() -> word { +function main() returns (word) { return helperValue(1); } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/diagnostics.snap index 6f7470d1..1f45b263 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol --- error[SC0110]: unknown import item `valu` - --> /main/main.solc:1:14 + --> /main/main.sol:1:9 | -1 | import util.{valu}; - | ^^^^ unknown import item +1 | import {valu} from util; + | ^^^^ unknown import item 2 | -3 | function main() -> word { +3 | function main() returns (word) { | = note: `valu` is not exported by module `util` = help: did you mean `value`? diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol index 1dae0969..f57c8e4e 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/main.sol @@ -1,5 +1,5 @@ -import util.{valu}; +import {valu} from util; -function main() -> word { +function main() returns (word) { return valu(1); } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.sol b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.sol index e88bc4d3..9e614c51 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_import_symbol_typo/util.sol @@ -1,5 +1,5 @@ export { value }; -function value(x: word) -> word { +function value(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/diagnostics.snap index 5e268843..726d56d6 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/diagnostics.snap @@ -1,20 +1,20 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol --- error[SC0101]: undefined name: secret - --> /main/main.solc:4:16 + --> /main/main.sol:4:16 | -3 | function main() -> word { +3 | function main() returns (word) { 4 | return vault.secret(1); | ^^^^^^ unknown name 5 | } | - ::: /main/vault.solc:6 + ::: /main/vault.sol:6 | 6 | -7 | function secret(x: word) -> word { +7 | function secret(x: word) returns (word) { | ------ private item declared here 8 | return x; | diff --git a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol index b5fb1d84..76988d72 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/main.sol @@ -1,5 +1,5 @@ import vault; -function main() -> word { +function main() returns (word) { return vault.secret(1); } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.sol b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.sol index 6911fc2e..36917988 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_private_qualified/vault.sol @@ -1,9 +1,9 @@ export { opened }; -function opened(x: word) -> word { +function opened(x: word) returns (word) { return secret(x); } -function secret(x: word) -> word { +function secret(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/diagnostics.snap index 2101a5ce..a5182982 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol --- error[SC0101]: undefined name: computeVale - --> /main/main.solc:6:10 + --> /main/main.sol:6:10 | -5 | function main() -> word { +5 | function main() returns (word) { 6 | return computeVale(1); | ^^^^^^^^^^^ unknown name 7 | } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol index 0f561585..b3c9eccc 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_typo_did_you_mean/main.sol @@ -1,7 +1,7 @@ -function computeValue(x: word) -> word { +function computeValue(x: word) returns (word) { return x; } -function main() -> word { +function main() returns (word) { return computeVale(1); } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_class/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_undef_class/diagnostics.snap index c26208be..996f5a3f 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_class/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_class/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol --- -error[SC0105]: undefined class: NoSuchClass - --> /main/main.solc:1:17 +error[SC0105]: undefined trait: NoSuchClass + --> /main/main.sol:1:6 | -1 | instance word : NoSuchClass { - | ^^^^^^^^^^^ undefined class -2 | function frob(x: word) -> word { +1 | impl NoSuchClass { + | ^^^^^^^^^^^ undefined trait +2 | function frob(x: word) returns (word) { 3 | return x; | diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol index 3cd65960..78d226c5 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_class/main.sol @@ -1,5 +1,5 @@ -instance word : NoSuchClass { - function frob(x: word) -> word { +impl NoSuchClass { + function frob(x: word) returns (word) { return x; } } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/diagnostics.snap index b2de4860..4c50a215 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol --- error[SC0101]: undefined name: Option.Nope - --> /main/main.solc:5:12 + --> /main/main.sol:5:13 | -4 | match o { -5 | | Option.Nope => return 0; - | ^^^^ unknown name -6 | | Option.Some(v) => return v; +4 | match (o) { +5 | case Option.Nope { + | ^^^^ unknown name +6 | return 0; | = help: did you mean `Option.None`? diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol index ab92497d..72f4282d 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_constructor/main.sol @@ -1,8 +1,12 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function unwrap(o: Option) -> word { - match o { - | Option.Nope => return 0; - | Option.Some(v) => return v; - } +function unwrap(o: Option) returns (word) { + match (o) { +case Option.Nope { +return 0; +} +case Option.Some(v) { +return v; +} +} } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_type/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_undef_type/diagnostics.snap index 96364ff4..5e4759f7 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_type/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_type/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol --- error[SC0103]: undefined type constructor: MissingType - --> /main/main.solc:1:20 + --> /main/main.sol:1:20 | -1 | function takeIt(x: MissingType) -> word { +1 | function takeIt(x: MissingType) returns (word) { | ^^^^^^^^^^^ undefined type constructor 2 | return 0; 3 | } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol index c74efea5..e73ef31b 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_type/main.sol @@ -1,3 +1,3 @@ -function takeIt(x: MissingType) -> word { +function takeIt(x: MissingType) returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/diagnostics.snap index 38ecf1f1..a1515d76 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol --- error[SC0101]: undefined name: missingVar - --> /main/main.solc:2:14 + --> /main/main.sol:2:14 | -1 | function addOne(x: word) -> word { +1 | function addOne(x: word) returns (word) { 2 | return x + missingVar; | ^^^^^^^^^^ unknown name 3 | } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol index eaa7a911..996c4b93 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_undef_variable/main.sol @@ -1,3 +1,3 @@ -function addOne(x: word) -> word { +function addOne(x: word) returns (word) { return x + missingVar; } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/diagnostics.snap index a5d17840..a9227220 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol --- error[SC0106]: unqualified constructor: On - --> /main/main.solc:12:15 + --> /main/main.sol:16:15 | -11 | function main() -> word { -12 | return isOn(On); +15 | function main() returns (word) { +16 | return isOn(On); | ^^ constructor must be qualified -13 | } +17 | } | = help: use `Light.On` diff --git a/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol index deca5936..99a7f088 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_unqual_ctor_sc0106/main.sol @@ -1,13 +1,17 @@ -data Light = On | Off; -data Power = Plugged | Battery; +enum Light { On, Off } +enum Power { Plugged, Battery } -function isOn(l: Light) -> word { - match l { - | Light.On => return 1; - | Light.Off => return 0; - } +function isOn(l: Light) returns (word) { + match (l) { +case Light.On { +return 1; +} +case Light.Off { +return 0; +} +} } -function main() -> word { +function main() returns (word) { return isOn(On); } diff --git a/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/diagnostics.snap index 8ef102cf..5bf1c59e 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/diagnostics.snap @@ -1,17 +1,17 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.solc +input_file: crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol --- error[SC0103]: undefined type constructor: MkPair - --> /main/main.solc:3:19 + --> /main/main.sol:3:19 | -1 | data Pair = MkPair(word, word); +1 | enum Pair { MkPair(word, word) } | ------ constructor declared here 2 | -3 | function first(p: MkPair) -> word { +3 | function first(p: MkPair) returns (word) { | ^^^^^^ undefined type constructor -4 | match p { +4 | match (p) { | = note: `MkPair` is a constructor of type `Pair` = help: use `Pair` as the type name diff --git a/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol b/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol index ff8e3173..a62a6bc2 100644 --- a/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol +++ b/crates/uitest/tests/fixtures/nameres/ergo_value_as_type/main.sol @@ -1,7 +1,9 @@ -data Pair = MkPair(word, word); +enum Pair { MkPair(word, word) } -function first(p: MkPair) -> word { - match p { - | Pair.MkPair(a, b) => return a; - } +function first(p: MkPair) returns (word) { + match (p) { +case Pair.MkPair(a, b) { +return a; +} +} } diff --git a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/diagnostics.snap index 483e1d4f..2768226e 100644 --- a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.solc +input_file: crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol --- error[SC0108]: duplicate declaration `value` in term namespace - --> /main/main.solc:3:10 + --> /main/main.sol:3:10 | -1 | import lib.{*}; - | --------------- previous declaration +1 | import * from lib; + | ------------------ previous declaration 2 | -3 | function value(x: word) -> word { +3 | function value(x: word) returns (word) { | ^^^^^ duplicate declaration 4 | return x; | diff --git a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.sol b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.sol index 0d203179..36dd500c 100644 --- a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.sol +++ b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/lib.sol @@ -1,4 +1,4 @@ -function value(x: word) -> word { +function value(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol index 269e54e6..c963b6e0 100644 --- a/crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol +++ b/crates/uitest/tests/fixtures/nameres/glob_shadow_local/main.sol @@ -1,5 +1,5 @@ -import lib.{*}; +import * from lib; -function value(x: word) -> word { +function value(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/nameres/hidden_ctor/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/hidden_ctor/diagnostics.snap index d6a48725..db0475fb 100644 --- a/crates/uitest/tests/fixtures/nameres/hidden_ctor/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/hidden_ctor/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/hidden_ctor/main.solc +input_file: crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol --- error[SC0101]: undefined name: Err - --> /main/main.solc:4:16 + --> /main/main.sol:4:16 | -3 | function main() -> Token { +3 | function main() returns (Token) { 4 | return Token.Err(0); | ^^^ unknown name 5 | } diff --git a/crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.sol b/crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.sol index 597b0300..cec692ef 100644 --- a/crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.sol +++ b/crates/uitest/tests/fixtures/nameres/hidden_ctor/lib.sol @@ -1,7 +1,7 @@ export { Token(Ok), mkErr }; -data Token = Ok(word) | Err(word); +enum Token { Ok(word), Err(word) } -function mkErr(x: word) -> Token { +function mkErr(x: word) returns (Token) { return Token.Err(x); } diff --git a/crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol b/crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol index 02d84415..fb35bb00 100644 --- a/crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol +++ b/crates/uitest/tests/fixtures/nameres/hidden_ctor/main.sol @@ -1,5 +1,5 @@ -import lib.{Token}; +import {Token} from lib; -function main() -> Token { +function main() returns (Token) { return Token.Err(0); } diff --git a/crates/uitest/tests/fixtures/nameres/missing/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/missing/diagnostics.snap index 7a2e91a2..8d580222 100644 --- a/crates/uitest/tests/fixtures/nameres/missing/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/missing/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/missing/main.solc +input_file: crates/uitest/tests/fixtures/nameres/missing/main.sol --- error[SC0109]: import missing: file not found - --> /main/main.solc:1:8 + --> /main/main.sol:1:21 | -1 | import missing.{value}; - | ^^^^^^^ module reference +1 | import {value} from missing; + | ^^^^^^^ module reference | = help: check the module path or add the missing source file diff --git a/crates/uitest/tests/fixtures/nameres/missing/main.sol b/crates/uitest/tests/fixtures/nameres/missing/main.sol index 80f575d9..7babefc7 100644 --- a/crates/uitest/tests/fixtures/nameres/missing/main.sol +++ b/crates/uitest/tests/fixtures/nameres/missing/main.sol @@ -1 +1 @@ -import missing.{value}; +import {value} from missing; diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.sol b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.sol index 94fae05c..38437949 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.sol +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/a.sol @@ -1,3 +1,3 @@ -data T = A; +enum T { A } export { T }; diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.sol b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.sol index 4f6e6ca6..89b0bcc5 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.sol +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/b.sol @@ -1,4 +1,4 @@ -function T() -> word { +function T() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/diagnostics.snap index 18cbe552..347c0981 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.solc +input_file: crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol --- error[SC0120]: ambiguous selected import `T` across term/type namespaces - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | -1 | import a.{T}; - | ^^^^^^^^^^^^^ ambiguous selected import across term/type namespaces -2 | import b.{T}; +1 | import {T} from a; + | ^^^^^^^^^^^^^^^^^^ ambiguous selected import across term/type namespaces +2 | import {T} from b; 3 | | = note: `T` is imported from a, b across term/type namespaces diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol index a25f626a..32ab0288 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_cross_namespace/main.sol @@ -1,6 +1,6 @@ -import a.{T}; -import b.{T}; +import {T} from a; +import {T} from b; -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.sol b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.sol index 7621b143..699035c4 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.sol +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/a.sol @@ -1,6 +1,6 @@ -data T = A; +enum T { A } -function T() -> word { +function T() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.sol b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.sol index 7621b143..699035c4 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.sol +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/b.sol @@ -1,6 +1,6 @@ -data T = A; +enum T { A } -function T() -> word { +function T() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/diagnostics.snap index c07d3f72..2bdbaf2b 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.solc +input_file: crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol --- error[SC0120]: ambiguous selected import `T` in term namespace - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | -1 | import a.{T}; - | ^^^^^^^^^^^^^ ambiguous selected import in term namespace -2 | import b.{T}; +1 | import {T} from a; + | ^^^^^^^^^^^^^^^^^^ ambiguous selected import in term namespace +2 | import {T} from b; 3 | | = note: `T` is imported from a, b in term namespace @@ -16,11 +16,11 @@ error[SC0120]: ambiguous selected import `T` in term namespace --- error[SC0120]: ambiguous selected import `T` in type namespace - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | -1 | import a.{T}; - | ^^^^^^^^^^^^^ ambiguous selected import in type namespace -2 | import b.{T}; +1 | import {T} from a; + | ^^^^^^^^^^^^^^^^^^ ambiguous selected import in type namespace +2 | import {T} from b; 3 | | = note: `T` is imported from a, b in type namespace diff --git a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol index a25f626a..32ab0288 100644 --- a/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol +++ b/crates/uitest/tests/fixtures/nameres/selected_import_ambiguity_namespace_identity/main.sol @@ -1,6 +1,6 @@ -import a.{T}; -import b.{T}; +import {T} from a; +import {T} from b; -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/nameres/string_type_annotation/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/string_type_annotation/diagnostics.snap index d9f07ec1..fffe3fd1 100644 --- a/crates/uitest/tests/fixtures/nameres/string_type_annotation/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/string_type_annotation/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/string_type_annotation/main.solc +input_file: crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol --- error[SC0103]: undefined type constructor: string - --> /main/main.solc:1:17 + --> /main/main.sol:1:23 | -1 | function f() -> string { - | ^^^^^^ undefined type constructor +1 | function f() returns (string) { + | ^^^^^^ undefined type constructor 2 | return "ok"; 3 | } | diff --git a/crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol b/crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol index c80a1a93..8c0cfdbf 100644 --- a/crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol +++ b/crates/uitest/tests/fixtures/nameres/string_type_annotation/main.sol @@ -1,3 +1,3 @@ -function f() -> string { +function f() returns (string) { return "ok"; } diff --git a/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/diagnostics.snap index 2d9f2f07..139eabb4 100644 --- a/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/diagnostics.snap @@ -1,32 +1,32 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.solc +input_file: crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol --- -error[SC0105]: undefined class: MissingClass - --> /main/main.solc:1:14 +error[SC0103]: undefined type constructor: MissingTy + --> /main/main.sol:1:18 | -1 | forall a . a:MissingClass => function f(x: MissingTy) -> word { - | ^^^^^^^^^^^^ undefined class +1 | function f(x: MissingTy) returns (word) where a: MissingClass { + | ^^^^^^^^^ undefined type constructor 2 | return missingName; 3 | } | --- -error[SC0103]: undefined type constructor: MissingTy - --> /main/main.solc:1:44 +error[SC0105]: undefined trait: MissingClass + --> /main/main.sol:1:53 | -1 | forall a . a:MissingClass => function f(x: MissingTy) -> word { - | ^^^^^^^^^ undefined type constructor +1 | function f(x: MissingTy) returns (word) where a: MissingClass { + | ^^^^^^^^^^^^ undefined trait 2 | return missingName; 3 | } | --- error[SC0101]: undefined name: missingName - --> /main/main.solc:2:10 + --> /main/main.sol:2:10 | -1 | forall a . a:MissingClass => function f(x: MissingTy) -> word { +1 | function f(x: MissingTy) returns (word) where a: MissingClass { 2 | return missingName; | ^^^^^^^^^^^ unknown name 3 | } diff --git a/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol b/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol index 806ba090..f2b3c1fc 100644 --- a/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol +++ b/crates/uitest/tests/fixtures/nameres/undefined_name_namespaces/main.sol @@ -1,3 +1,3 @@ -forall a . a:MissingClass => function f(x: MissingTy) -> word { +function f(x: MissingTy) returns (word) where a: MissingClass { return missingName; } diff --git a/crates/uitest/tests/fixtures/nameres/unknown_import/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unknown_import/diagnostics.snap index 4aa9e360..cff08b03 100644 --- a/crates/uitest/tests/fixtures/nameres/unknown_import/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unknown_import/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unknown_import/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unknown_import/main.sol --- error[SC0110]: unknown import item `missing` - --> /main/main.solc:1:14 + --> /main/main.sol:1:9 | -1 | import util.{missing}; - | ^^^^^^^ unknown import item +1 | import {missing} from util; + | ^^^^^^^ unknown import item | = note: `missing` is not exported by module `util` = help: check the imported module's exported names diff --git a/crates/uitest/tests/fixtures/nameres/unknown_import/main.sol b/crates/uitest/tests/fixtures/nameres/unknown_import/main.sol index 38d0deaf..e08ec7b1 100644 --- a/crates/uitest/tests/fixtures/nameres/unknown_import/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unknown_import/main.sol @@ -1 +1 @@ -import util.{missing}; +import {missing} from util; diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/diagnostics.snap index fcc05e96..7643b962 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/diagnostics.snap @@ -1,58 +1,58 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol --- error[SC0106]: unqualified constructor: Some - --> /main/main.solc:4:47 + --> /main/main.sol:4:54 | 3 | -4 | function exprCall(x: word) -> Option { return Some(x); } - | ^^^^ constructor must be qualified -5 | function exprBare(f: flag) -> flag { return on; } +4 | function exprCall(x: word) returns (Option) { return Some(x); } + | ^^^^ constructor must be qualified +5 | function exprBare(f: flag) returns (flag) { return on; } | = help: use `Option.Some` --- error[SC0106]: unqualified constructor: on - --> /main/main.solc:5:45 + --> /main/main.sol:5:52 | -4 | function exprCall(x: word) -> Option { return Some(x); } -5 | function exprBare(f: flag) -> flag { return on; } - | ^^ constructor must be qualified +4 | function exprCall(x: word) returns (Option) { return Some(x); } +5 | function exprBare(f: flag) returns (flag) { return on; } + | ^^ constructor must be qualified 6 | | = help: use `flag.on` --- error[SC0106]: unqualified constructor: off - --> /main/main.solc:9:5 + --> /main/main.sol:9:6 | - 8 | match f { - 9 | | off => return 0; - | ^^^ constructor must be qualified -10 | | on => return 1; + 8 | match (f) { + 9 | case off { + | ^^^ constructor must be qualified +10 | return 0; | = help: use `flag.off` --- error[SC0106]: unqualified constructor: on - --> /main/main.solc:10:5 + --> /main/main.sol:12:6 | - 9 | | off => return 0; -10 | | on => return 1; - | ^^ constructor must be qualified -11 | } +11 | } +12 | case on { + | ^^ constructor must be qualified +13 | return 1; | = help: use `flag.on` --- error[SC0106]: unqualified constructor: None - --> /main/main.solc:16:5 + --> /main/main.sol:20:6 | -15 | match o { -16 | | None => return 0; - | ^^^^ constructor must be qualified -17 | | _ => return 1; +19 | match (o) { +20 | case None { + | ^^^^ constructor must be qualified +21 | return 0; | = help: use `Option.None` diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol b/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol index ca9e2a06..e2b714a2 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_constructor_all_forms/main.sol @@ -1,19 +1,27 @@ -data Option = None | Some(word); -data flag = off | on; +enum Option { None, Some(word) } +enum flag { off, on } -function exprCall(x: word) -> Option { return Some(x); } -function exprBare(f: flag) -> flag { return on; } +function exprCall(x: word) returns (Option) { return Some(x); } +function exprBare(f: flag) returns (flag) { return on; } -function patLower(f: flag) -> word { - match f { - | off => return 0; - | on => return 1; - } +function patLower(f: flag) returns (word) { + match (f) { +case off { +return 0; +} +case on { +return 1; +} +} } -function patUpper(o: Option) -> word { - match o { - | None => return 0; - | _ => return 1; - } +function patUpper(o: Option) returns (word) { + match (o) { +case None { +return 0; +} +default { +return 1; +} +} } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/diagnostics.snap index d18cfee0..59a48aee 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol --- error[SC0106]: unqualified constructor: on - --> /main/main.solc:11:15 + --> /main/main.sol:15:15 | -10 | function main() -> word { -11 | return pick(on); +14 | function main() returns (word) { +15 | return pick(on); | ^^ constructor must be qualified -12 | } +16 | } | = help: use `flag.on` diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol index 01a76d27..e0943254 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_expr/main.sol @@ -1,12 +1,16 @@ -data flag = off | on; +enum flag { off, on } -function pick(f: flag) -> word { - match f { - | flag.off => return 0; - | flag.on => return 1; - } +function pick(f: flag) returns (word) { + match (f) { +case flag.off { +return 0; +} +case flag.on { +return 1; +} +} } -function main() -> word { +function main() returns (word) { return pick(on); } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/diagnostics.snap index dc58f592..00b70136 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol --- error[SC0106]: unqualified constructor: Ok - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function mk(x: word) -> Token { +3 | function mk(x: word) returns (Token) { 4 | return Ok(x); | ^^ constructor must be qualified 5 | } @@ -15,11 +15,11 @@ error[SC0106]: unqualified constructor: Ok --- error[SC0106]: unqualified constructor: Ok - --> /main/main.solc:9:5 + --> /main/main.sol:9:6 | - 8 | match t { - 9 | | Ok(v) => return v; - | ^^ constructor must be qualified -10 | | Token.Err(v) => return v; + 8 | match (t) { + 9 | case Ok(v) { + | ^^ constructor must be qualified +10 | return v; | = help: use Type.Constructor form diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.sol index f5a73f55..30f19027 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/lib.sol @@ -1,3 +1,3 @@ export { Token(Ok, Err) }; -data Token = Ok(word) | Err(word); +enum Token { Ok(word), Err(word) } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol index 961a91bd..f204532b 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_imported/main.sol @@ -1,12 +1,16 @@ -import lib.{Token}; +import {Token} from lib; -function mk(x: word) -> Token { +function mk(x: word) returns (Token) { return Ok(x); } -function classify(t: Token) -> word { - match t { - | Ok(v) => return v; - | Token.Err(v) => return v; - } +function classify(t: Token) returns (word) { + match (t) { +case Ok(v) { +return v; +} +case Token.Err(v) { +return v; +} +} } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap index 72d6f481..5ed959ed 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap @@ -1,21 +1,21 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol --- error[SC0106]: unqualified constructor: off - --> /main/main.solc:5:5 + --> /main/main.sol:5:6 | -4 | match f { -5 | | off => return 0; - | ^^^ constructor must be qualified -6 | | on => return 1; +4 | match (f) { +5 | case off { + | ^^^ constructor must be qualified +6 | return 0; | = help: use `flag.off` --- error[SC0106]: unqualified constructor: on - --> /main/main.solc:6:5 + --> /main/main.sol:8:6 | 5 | | off => return 0; 6 | | on => return 1; From 41dccc2eb7392f276236aed71b92e41df7c88a64 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 097/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures Co-authored-by: Codex --- .../unqualified_ctor_pattern/diagnostics.snap | 8 +- .../nameres/unqualified_ctor_pattern/main.sol | 18 +- .../diagnostics.snap | 22 +- .../main.sol | 18 +- .../diagnostics.snap | 20 +- .../unqualified_ctor_plain_import/lib.sol | 2 +- .../unqualified_ctor_plain_import/main.sol | 12 +- .../unresolved_qualified/diagnostics.snap | 6 +- .../nameres/unresolved_qualified/main.sol | 2 +- .../nameres/unresolved_qualified/util.sol | 2 +- .../diagnostics.snap | 4 +- .../diagnostics.snap | 4 +- .../body_independent_errors/diagnostics.snap | 10 +- .../parse/body_independent_errors/main.sol | 2 +- .../parse/body_invalid_token/diagnostics.snap | 8 +- .../parse/body_invalid_token/main.sol | 2 +- .../parse/bom_only_file/diagnostics.snap | 4 +- .../class_missing_body_brace/diagnostics.snap | 13 - .../parse/class_missing_body_brace/main.solc | 1 - .../parse/data_trailing_pipe/diagnostics.snap | 13 +- .../parse/data_trailing_pipe/main.sol | 2 +- .../delimiter_nesting_limit/diagnostics.snap | 4 +- .../parse/delimiter_nesting_limit/main.sol | 2 +- .../diagnostics.snap | 6 +- .../ergo_assembly_unclosed_call/main.sol | 2 +- .../diagnostics.snap | 6 +- .../parse/ergo_contract_missing_name/main.sol | 2 +- .../diagnostics.snap | 6 +- .../ergo_hull_empty_match/diagnostics.snap | 14 +- .../parse/ergo_hull_empty_match/main.sol | 8 +- .../ergo_hull_fallback_args/diagnostics.snap | 6 +- .../parse/ergo_hull_fallback_args/main.sol | 8 +- .../ergo_import_trailing_dot/diagnostics.snap | 7 +- .../parse/ergo_import_trailing_dot/main.sol | 2 +- .../diagnostics.snap | 6 +- .../parse/ergo_invalid_token_unicode/main.sol | 2 +- .../ergo_keyword_as_ident/diagnostics.snap | 6 +- .../parse/ergo_keyword_as_ident/main.sol | 2 +- .../diagnostics.snap | 16 +- .../parse/ergo_lambda_missing_parens/main.sol | 2 +- .../diagnostics.snap | 10 +- .../ergo_missing_semicolon_stmts/main.sol | 2 +- .../ergo_pragma_missing_semi/diagnostics.snap | 6 +- .../parse/ergo_pragma_missing_semi/main.sol | 2 +- .../diagnostics.snap | 6 +- .../parse/ergo_stray_top_level_semi/main.sol | 4 +- .../ergo_two_errors_recovery/diagnostics.snap | 14 +- .../parse/ergo_two_errors_recovery/main.sol | 8 +- .../ergo_unclosed_brace_eof/diagnostics.snap | 6 +- .../parse/ergo_unclosed_brace_eof/main.sol | 2 +- .../diagnostics.snap | 6 +- .../ergo_unterminated_block_comment/main.sol | 4 +- .../ergo_unterminated_string/diagnostics.snap | 6 +- .../parse/ergo_unterminated_string/main.sol | 2 +- .../diagnostics.snap | 132 ++++++++- .../excessive_conditional_nesting/main.sol | 262 +++++++++--------- .../diagnostics.snap | 8 +- .../excessive_expression_nesting/main.sol | 2 +- .../diagnostics.snap | 11 +- .../fallback_with_non_unit_return/main.sol | 2 +- .../fallback_with_params/diagnostics.snap | 4 +- .../function_param_recovery/diagnostics.snap | 4 +- .../diagnostics.snap | 4 +- .../if_trailing_semicolon/diagnostics.snap | 4 +- .../parse/if_trailing_semicolon/main.sol | 2 +- .../parse/impl_missing_head/diagnostics.snap | 13 + .../fixtures/parse/impl_missing_head/main.sol | 1 + .../import_ctor_group_syntax/diagnostics.snap | 8 +- .../parse/import_ctor_group_syntax/main.sol | 2 +- .../diagnostics.snap | 10 +- .../import_selector_unterminated/main.sol | 2 +- .../instance_missing_head/diagnostics.snap | 13 - .../parse/instance_missing_head/main.solc | 1 - .../parse/invalid_token/diagnostics.snap | 4 +- .../diagnostics.snap | 15 +- .../keyword_comptime_identifier/main.sol | 2 +- .../parse/match_arm_arity/diagnostics.snap | 15 + .../fixtures/parse/match_arm_arity/main.sol | 21 ++ 78 files changed, 529 insertions(+), 371 deletions(-) delete mode 100644 crates/uitest/tests/fixtures/parse/class_missing_body_brace/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/parse/class_missing_body_brace/main.solc create mode 100644 crates/uitest/tests/fixtures/parse/impl_missing_head/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/parse/impl_missing_head/main.sol delete mode 100644 crates/uitest/tests/fixtures/parse/instance_missing_head/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/parse/instance_missing_head/main.solc create mode 100644 crates/uitest/tests/fixtures/parse/match_arm_arity/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/parse/match_arm_arity/main.sol diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap index 5ed959ed..1c1a64f4 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/diagnostics.snap @@ -17,9 +17,9 @@ error[SC0106]: unqualified constructor: off error[SC0106]: unqualified constructor: on --> /main/main.sol:8:6 | -5 | | off => return 0; -6 | | on => return 1; - | ^^ constructor must be qualified -7 | } +7 | } +8 | case on { + | ^^ constructor must be qualified +9 | return 1; | = help: use `flag.on` diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol index bfef502d..352d9547 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern/main.sol @@ -1,12 +1,16 @@ -data flag = off | on; +enum flag { off, on } -function pick(f: flag) -> word { - match f { - | off => return 0; - | on => return 1; - } +function pick(f: flag) returns (word) { + match (f) { +case off { +return 0; +} +case on { +return 1; +} +} } -function main() -> word { +function main() returns (word) { return pick(flag.on); } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/diagnostics.snap index 13ca30bc..d3ea5ed5 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/diagnostics.snap @@ -1,25 +1,25 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol --- error[SC0106]: unqualified constructor: north - --> /main/main.solc:5:5 + --> /main/main.sol:5:6 | -4 | match d { -5 | | north => return 1; - | ^^^^^ constructor must be qualified -6 | | south => return 2; +4 | match (d) { +5 | case north { + | ^^^^^ constructor must be qualified +6 | return 1; | = help: use `direction.north` --- error[SC0106]: unqualified constructor: south - --> /main/main.solc:6:5 + --> /main/main.sol:8:6 | -5 | | north => return 1; -6 | | south => return 2; - | ^^^^^ constructor must be qualified -7 | } +7 | } +8 | case south { + | ^^^^^ constructor must be qualified +9 | return 2; | = help: use `direction.south` diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol index 14613022..f4e83e89 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_pattern_direction/main.sol @@ -1,12 +1,16 @@ -data direction = north | south; +enum direction { north, south } -function pick(d: direction) -> word { - match d { - | north => return 1; - | south => return 2; - } +function pick(d: direction) returns (word) { + match (d) { +case north { +return 1; +} +case south { +return 2; +} +} } -function main() -> word { +function main() returns (word) { return pick(direction.south); } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/diagnostics.snap index 3c8755a5..6c166319 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/diagnostics.snap @@ -1,25 +1,25 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol --- error[SC0106]: unqualified constructor: wrapper - --> /main/main.solc:5:5 + --> /main/main.sol:5:6 | -4 | match u { -5 | | wrapper(w) => return w; - | ^^^^^^^ constructor must be qualified -6 | } +4 | match (u) { +5 | case wrapper(w) { + | ^^^^^^^ constructor must be qualified +6 | return w; | = help: use Type.Constructor form --- error[SC0106]: unqualified constructor: wrapper - --> /main/main.solc:10:17 + --> /main/main.sol:12:17 | - 9 | function main() -> word { -10 | return unwrap(wrapper(3)); +11 | function main() returns (word) { +12 | return unwrap(wrapper(3)); | ^^^^^^^ constructor must be qualified -11 | } +13 | } | = help: use Type.Constructor form diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.sol index fdfd1361..b547863a 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/lib.sol @@ -1,3 +1,3 @@ export { wrapper(wrapper) }; -data wrapper = wrapper(word); +enum wrapper { wrapper(word) } diff --git a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol index 483b0690..5224176b 100644 --- a/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unqualified_ctor_plain_import/main.sol @@ -1,11 +1,13 @@ import lib; -function unwrap(u: lib.wrapper) -> word { - match u { - | wrapper(w) => return w; - } +function unwrap(u: lib.wrapper) returns (word) { + match (u) { +case wrapper(w) { +return w; +} +} } -function main() -> word { +function main() returns (word) { return unwrap(wrapper(3)); } diff --git a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/diagnostics.snap b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/diagnostics.snap index 06d5aecc..b63de61b 100644 --- a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/diagnostics.snap +++ b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.solc +input_file: crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol --- error[SC0101]: undefined name: missing - --> /main/main.solc:4:15 + --> /main/main.sol:4:15 | -3 | function main() -> word { +3 | function main() returns (word) { 4 | return util.missing(); | ^^^^^^^ unknown name 5 | } diff --git a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol index 8090a9fa..11ba6564 100644 --- a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol +++ b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/main.sol @@ -1,5 +1,5 @@ import util; -function main() -> word { +function main() returns (word) { return util.missing(); } diff --git a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.sol b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.sol index 816f96ee..41eb3ad7 100644 --- a/crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.sol +++ b/crates/uitest/tests/fixtures/nameres/unresolved_qualified/util.sol @@ -1,5 +1,5 @@ export { value }; -function value() -> word { +function value() returns (word) { return 1; } diff --git a/crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/diagnostics.snap b/crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/diagnostics.snap index 7598c808..f787881a 100644 --- a/crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/main.solc +input_file: crates/uitest/tests/fixtures/parse/assembly_trailing_semicolon/main.sol --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:4:4 + --> /main/main.sol:4:4 | 3 | mstore(0, 0) 4 | }; diff --git a/crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/diagnostics.snap b/crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/diagnostics.snap index 68f1df72..f68456e0 100644 --- a/crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/main.solc +input_file: crates/uitest/tests/fixtures/parse/assignment_missing_semicolon/main.sol --- error[SC0001]: assignment statement requires trailing `;` - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | function bad() { 2 | x = 1 diff --git a/crates/uitest/tests/fixtures/parse/body_independent_errors/diagnostics.snap b/crates/uitest/tests/fixtures/parse/body_independent_errors/diagnostics.snap index 8b952327..669981a0 100644 --- a/crates/uitest/tests/fixtures/parse/body_independent_errors/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/body_independent_errors/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/body_independent_errors/main.solc +input_file: crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol --- error[SC0001]: invalid token `§` - --> /main/main.solc:2:1 + --> /main/main.sol:2:1 | -1 | function main() -> word { +1 | function main() returns (word) { 2 | § | ^ invalid token 3 | let broken = ; @@ -14,11 +14,11 @@ error[SC0001]: invalid token `§` --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:3:14 + --> /main/main.sol:3:14 | 2 | § 3 | let broken = ; | ^ unexpected token 4 | return 0; | - = note: expecting expression after `=` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` diff --git a/crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol b/crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol index 98c12f9c..38461834 100644 --- a/crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol +++ b/crates/uitest/tests/fixtures/parse/body_independent_errors/main.sol @@ -1,4 +1,4 @@ -function main() -> word { +function main() returns (word) { § let broken = ; return 0; diff --git a/crates/uitest/tests/fixtures/parse/body_invalid_token/diagnostics.snap b/crates/uitest/tests/fixtures/parse/body_invalid_token/diagnostics.snap index c884a545..34df822e 100644 --- a/crates/uitest/tests/fixtures/parse/body_invalid_token/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/body_invalid_token/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/body_invalid_token/main.solc +input_file: crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol --- error[SC0001]: invalid token `§` - --> /main/main.solc:1:34 + --> /main/main.sol:1:41 | -1 | function main() -> word { return §; } - | ^ invalid token +1 | function main() returns (word) { return §; } + | ^ invalid token diff --git a/crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol b/crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol index efed509d..a18154fc 100644 --- a/crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol +++ b/crates/uitest/tests/fixtures/parse/body_invalid_token/main.sol @@ -1 +1 @@ -function main() -> word { return §; } +function main() returns (word) { return §; } diff --git a/crates/uitest/tests/fixtures/parse/bom_only_file/diagnostics.snap b/crates/uitest/tests/fixtures/parse/bom_only_file/diagnostics.snap index d715561c..d1dd1eb9 100644 --- a/crates/uitest/tests/fixtures/parse/bom_only_file/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/bom_only_file/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/bom_only_file/main.solc +input_file: crates/uitest/tests/fixtures/parse/bom_only_file/main.sol --- error[SC0001]: invalid token `` - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | 1 |  | ^ invalid token diff --git a/crates/uitest/tests/fixtures/parse/class_missing_body_brace/diagnostics.snap b/crates/uitest/tests/fixtures/parse/class_missing_body_brace/diagnostics.snap deleted file mode 100644 index 7030b07b..00000000 --- a/crates/uitest/tests/fixtures/parse/class_missing_body_brace/diagnostics.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/parse/class_missing_body_brace/main.solc ---- -error[SC0001]: parse error: unexpected end of input - --> /main/main.solc:1:13 - | -1 | class T: Eq - | ^ unexpected token - | - = note: expecting `(`, or `{` - = note: while parsing predicate diff --git a/crates/uitest/tests/fixtures/parse/class_missing_body_brace/main.solc b/crates/uitest/tests/fixtures/parse/class_missing_body_brace/main.solc deleted file mode 100644 index 8e27f54d..00000000 --- a/crates/uitest/tests/fixtures/parse/class_missing_body_brace/main.solc +++ /dev/null @@ -1 +0,0 @@ -class T: Eq diff --git a/crates/uitest/tests/fixtures/parse/data_trailing_pipe/diagnostics.snap b/crates/uitest/tests/fixtures/parse/data_trailing_pipe/diagnostics.snap index 783edf38..c990a88f 100644 --- a/crates/uitest/tests/fixtures/parse/data_trailing_pipe/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/data_trailing_pipe/diagnostics.snap @@ -1,12 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.solc +input_file: crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol --- -error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:1:28 +error[SC0001]: parse error: unexpected `|` + --> /main/main.sol:1:26 | -1 | data Option(T) = Some(T) | ; - | ^ unexpected token +1 | enum Option { Some(T) | } + | ^ unexpected token | - = note: while parsing data declaration + = note: expecting `,`, or `}` + = note: while parsing enum declaration diff --git a/crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol b/crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol index 6ff3e4c4..36f75971 100644 --- a/crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol +++ b/crates/uitest/tests/fixtures/parse/data_trailing_pipe/main.sol @@ -1 +1 @@ -data Option(T) = Some(T) | ; +enum Option { Some(T) | } diff --git a/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/diagnostics.snap b/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/diagnostics.snap index f36cf5f5..1aeacbef 100644 --- a/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.solc +input_file: crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol --- error[SC0001]: delimiter nesting exceeds the compiler limit of 128 - --> /main/main.solc:1:164 + --> /main/main.sol:1:172 | 1 | ...((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((... | ^ diff --git a/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol b/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol index 72be801d..5ff7c981 100644 --- a/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol +++ b/crates/uitest/tests/fixtures/parse/delimiter_nesting_limit/main.sol @@ -1 +1 @@ -function f(x:word) -> word { return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); } +function f(x: word) returns (word) { return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); } diff --git a/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/diagnostics.snap index a2f7cb67..0d86945a 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol --- error[SC0001]: parse error: unexpected `(` - --> /main/main.solc:4:17 + --> /main/main.sol:4:17 | 3 | assembly { 4 | r := add(1, @@ -14,7 +14,7 @@ error[SC0001]: parse error: unexpected `(` --- error[SC0001]: parse error: unexpected `,` - --> /main/main.solc:4:19 + --> /main/main.sol:4:19 | 3 | assembly { 4 | r := add(1, diff --git a/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol b/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol index 2a9b5ab2..2f8465ac 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_assembly_unclosed_call/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let r : word; assembly { r := add(1, diff --git a/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/diagnostics.snap index 0883f5c7..8632b0a2 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol --- error[SC0001]: parse error: unexpected `{` - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract { | ^ unexpected token -2 | function f() -> word { +2 | function f() returns (word) { 3 | return 1; | = note: expecting identifier diff --git a/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol b/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol index 516bdf25..806d8334 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_contract_missing_name/main.sol @@ -1,5 +1,5 @@ contract { - function f() -> word { + function f() returns (word) { return 1; } } diff --git a/crates/uitest/tests/fixtures/parse/ergo_function_missing_params/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_function_missing_params/diagnostics.snap index c618f371..4923bd80 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_function_missing_params/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_function_missing_params/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_function_missing_params/main.sol --- error[SC0001]: parse error: unexpected `->` - --> /main/main.solc:1:12 + --> /main/main.sol:1:12 | 1 | function f -> word { | ^^ unexpected token 2 | return 1; 3 | } | - = note: expecting `(` + = note: expecting `(`, or `<` = note: while parsing function signature diff --git a/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/diagnostics.snap index d98676ba..20d51988 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/diagnostics.snap @@ -1,16 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol --- -error[SC0001]: match statement requires at least one arm - --> /main/main.solc:4:11 +error[SC0001]: match requires at least one `case` or `default` arm + --> /main/main.sol:4:3 | -3 | function impossible(b : B) -> word { -4 | match b { - | ___________^ +3 | function impossible(b: B) returns (word) { +4 | / match (b) { 5 | | } - | |___^ empty match arm list + | |___^ 6 | } | - = note: add a `| pattern =>` arm diff --git a/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol b/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol index 139fc1dc..b026d22d 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_hull_empty_match/main.sol @@ -1,12 +1,12 @@ -data B = A | C; +enum B { A, C } -function impossible(b : B) -> word { - match b { +function impossible(b: B) returns (word) { + match (b) { } } contract T { - public function main(x : word) -> word { + function main(x: word) public returns (word) { return impossible(B.A); } } diff --git a/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/diagnostics.snap index e4b23b12..9039605f 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol --- error[SC0001]: fallback function must not declare input parameters - --> /main/main.solc:9:13 + --> /main/main.sol:9:13 | 8 | - 9 | fallback(x: uint256) -> () { + 9 | fallback(x: uint256) { | ^^^^^^^^^^^^ 10 | revert("fallback-was-called"); | diff --git a/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol b/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol index 8928a4a7..8f6aeaa8 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_hull_fallback_args/main.sol @@ -1,12 +1,12 @@ -// Mirrors reference corpus test/examples/cases/fallback-with-args.solc +// Mirrors reference corpus test/examples/cases/fallback-with-args.sol // (expected failure there): fallback must take no arguments. -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract BadFallback { constructor() {} - fallback(x: uint256) -> () { + fallback(x: uint256) { revert("fallback-was-called"); } } diff --git a/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/diagnostics.snap index 35577677..88d09442 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/diagnostics.snap @@ -1,15 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:1:12 + --> /main/main.sol:1:12 | 1 | import a.b.; | ^ unexpected token 2 | -3 | function f() -> word { +3 | function f() returns (word) { | - = note: expecting import selector after `.` = note: while parsing import declaration diff --git a/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol b/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol index 81a5f777..0a18d6ba 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_import_trailing_dot/main.sol @@ -1,5 +1,5 @@ import a.b.; -function f() -> word { +function f() returns (word) { return 1; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/diagnostics.snap index f5c2b1a3..079563ec 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol --- error[SC0001]: invalid token `§` - --> /main/main.solc:2:15 + --> /main/main.sol:2:15 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | let x = 1 § 2; | ^ invalid token 3 | return x; diff --git a/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol b/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol index 6072f816..c7a88ee1 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_invalid_token_unicode/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let x = 1 § 2; return x; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/diagnostics.snap index f5a63638..383a64ad 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol --- error[SC0001]: parse error: unexpected `match` - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | -1 | function match(x : word) -> word { +1 | function match(x: word) returns (word) { | ^^^^^ unexpected token 2 | return x; 3 | } diff --git a/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol b/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol index de4dce67..5cb9ee82 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_keyword_as_ident/main.sol @@ -1,3 +1,3 @@ -function match(x : word) -> word { +function match(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/diagnostics.snap index 812a438a..74b49c51 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/diagnostics.snap @@ -1,23 +1,23 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol --- -error[SC0001]: parse error: unexpected identifier `x` - --> /main/main.solc:2:17 +error[SC0001]: parse error: unexpected `;` + --> /main/main.sol:2:29 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | let g = lam x { return x; }; - | ^ unexpected token + | ^ unexpected token 3 | return g(1); | - = note: expecting `(` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` --- error[SC0001]: parse error: unexpected `}` - --> /main/main.solc:2:31 + --> /main/main.sol:2:31 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | let g = lam x { return x; }; | ^ unexpected token 3 | return g(1); diff --git a/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol b/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol index cb9032ad..367eb2a5 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_lambda_missing_parens/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let g = lam x { return x; }; return g(1); } diff --git a/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/diagnostics.snap index 5e1dcbe7..2a7a245b 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol --- -error[SC0001]: parse error: unexpected `return` - --> /main/main.solc:3:5 +error[SC0001]: parse error: unexpected `;` + --> /main/main.sol:3:13 | 2 | let x = 1 3 | return x; - | ^^^^^^ unexpected token + | ^ unexpected token 4 | } | - = note: expecting `;` after let statement + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` diff --git a/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol b/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol index 1d87720c..e8c0ca0e 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_missing_semicolon_stmts/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let x = 1 return x; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/diagnostics.snap index 5902cf8b..ac5f4d1f 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol --- error[SC0001]: parse error: unexpected `function` - --> /main/main.solc:3:1 + --> /main/main.sol:3:1 | 2 | -3 | function f() -> word { +3 | function f() returns (word) { | ^^^^^^^^ unexpected token 4 | return 1; | diff --git a/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol b/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol index 037f935e..38b6a517 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_pragma_missing_semi/main.sol @@ -1,5 +1,5 @@ pragma no-coverage-condition -function f() -> word { +function f() returns (word) { return 1; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/diagnostics.snap index 04254226..7c1b1e8a 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol --- -error[SC0001]: could not parse top-level item near `;`; expected a declaration starting with `import`, `pragma`, `type`, `data`, `class`, `instance`, `contract`, or `function` - --> /main/main.solc:3:2 +error[SC0001]: could not parse top-level item near `;`; expected a declaration starting with `import`, `pragma`, `type`, `enum`, `trait`, `impl`, `contract`, or `function` + --> /main/main.sol:3:2 | 2 | return 1; 3 | }; diff --git a/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol b/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol index 42538fb7..00006570 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_stray_top_level_semi/main.sol @@ -1,7 +1,7 @@ -function f() -> word { +function f() returns (word) { return 1; }; -function g() -> word { +function g() returns (word) { return 2; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/diagnostics.snap index 05fc270b..2e7d3c1d 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/diagnostics.snap @@ -1,25 +1,25 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:2:13 + --> /main/main.sol:2:13 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | let x = ; | ^ unexpected token 3 | return 0; | - = note: expecting expression after `=` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:12:14 + --> /main/main.sol:12:14 | -11 | function h() -> word { +11 | function h() returns (word) { 12 | return (1; | ^ unexpected token 13 | } | - = note: expecting `&&`, `&`, `(`, `)`, `,`, `.`, `:`, `?`, `[`, `^`, `|`, or `||` + = note: expecting `&&`, `&`, `(`, `)`, `,`, `.`, `?`, `[`, `^`, `|`, or `||` diff --git a/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol b/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol index 43ce3b01..51b4909b 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_two_errors_recovery/main.sol @@ -1,13 +1,13 @@ -function f() -> word { +function f() returns (word) { let x = ; return 0; } -function g(y : word) -> word { - if y { return 1; } +function g(y: word) returns (word) { + if ( y ) { return 1; } return 0; } -function h() -> word { +function h() returns (word) { return (1; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/diagnostics.snap index 9fdd331b..e1056927 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol --- error[SC0001]: parse error: unexpected end of input - --> /main/main.solc:4:7 + --> /main/main.sol:4:7 | -2 | function f() -> word { +2 | function f() returns (word) { 3 | return 1; 4 | } | ^ unexpected token diff --git a/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol b/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol index 878ca7a0..ff5c44b8 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_unclosed_brace_eof/main.sol @@ -1,4 +1,4 @@ contract C { - function f() -> word { + function f() returns (word) { return 1; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/diagnostics.snap index 01321e01..fb0b1b97 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol --- error[SC0001]: unterminated block comment - --> /main/main.solc:4:1 + --> /main/main.sol:4:1 | 3 | } 4 | / /* this comment never ends -5 | | function g() -> word { +5 | | function g() returns (word) { 6 | | return 2; 7 | | } | |__^ comment starts here diff --git a/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol b/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol index 194cb14c..a0b611a1 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_unterminated_block_comment/main.sol @@ -1,7 +1,7 @@ -function f() -> word { +function f() returns (word) { return 1; } /* this comment never ends -function g() -> word { +function g() returns (word) { return 2; } diff --git a/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/diagnostics.snap b/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/diagnostics.snap index a7ab6aa1..9af9a886 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.solc +input_file: crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol --- error[SC0001]: unterminated string literal - --> /main/main.solc:2:13 + --> /main/main.sol:2:13 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | let s = "hello; | _____________^ 3 | | return 1; diff --git a/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol b/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol index 6bfccb64..bb3e97a9 100644 --- a/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol +++ b/crates/uitest/tests/fixtures/parse/ergo_unterminated_string/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let s = "hello; return 1; } diff --git a/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/diagnostics.snap b/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/diagnostics.snap index a44b7093..31f1a87f 100644 --- a/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/diagnostics.snap @@ -1,13 +1,131 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.solc +input_file: crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol --- -error[SC0001]: conditional expression nesting exceeds the compiler limit of 128 - --> /main/main.solc:131:17 +error[SC0001]: expression nesting exceeds the compiler limit of 32 + --> /main/main.sol:34:18 + | +33 | true ? 0 : +34 | true ? 0 : + | ^^^^ +35 | true ? 0 : + | +--- + +error[SC0001]: expression nesting exceeds the compiler limit of 32 + --> /main/main.sol:34:27 + | +33 | true ? 0 : +34 | true ? 0 : + | ^ +35 | true ? 0 : + | +--- + +error[SC0001]: expression nesting exceeds the compiler limit of 32 + --> /main/main.sol:35:18 | -130 | if true then 0 else -131 | if true then 0 else - | ^^ -132 | if true then 0 else + 34 | true ? 0 : + 35 | / true ? 0 : + 36 | | true ? 0 : + 37 | | true ? 0 : + 38 | | true ? 0 : + 39 | | true ? 0 : + 40 | | true ? 0 : + 41 | | true ? 0 : + 42 | | true ? 0 : + 43 | | true ? 0 : + 44 | | true ? 0 : + 45 | | true ? 0 : + 46 | | true ? 0 : + 47 | | true ? 0 : + 48 | | true ? 0 : + 49 | | true ? 0 : + 50 | | true ? 0 : + 51 | | true ? 0 : + 52 | | true ? 0 : + 53 | | true ? 0 : + 54 | | true ? 0 : + 55 | | true ? 0 : + 56 | | true ? 0 : + 57 | | true ? 0 : + 58 | | true ? 0 : + 59 | | true ? 0 : + 60 | | true ? 0 : + 61 | | true ? 0 : + 62 | | true ? 0 : + 63 | | true ? 0 : + 64 | | true ? 0 : + 65 | | true ? 0 : + 66 | | true ? 0 : + 67 | | true ? 0 : + 68 | | true ? 0 : + 69 | | true ? 0 : + 70 | | true ? 0 : + 71 | | true ? 0 : + 72 | | true ? 0 : + 73 | | true ? 0 : + 74 | | true ? 0 : + 75 | | true ? 0 : + 76 | | true ? 0 : + 77 | | true ? 0 : + 78 | | true ? 0 : + 79 | | true ? 0 : + 80 | | true ? 0 : + 81 | | true ? 0 : + 82 | | true ? 0 : + 83 | | true ? 0 : + 84 | | true ? 0 : + 85 | | true ? 0 : + 86 | | true ? 0 : + 87 | | true ? 0 : + 88 | | true ? 0 : + 89 | | true ? 0 : + 90 | | true ? 0 : + 91 | | true ? 0 : + 92 | | true ? 0 : + 93 | | true ? 0 : + 94 | | true ? 0 : + 95 | | true ? 0 : + 96 | | true ? 0 : + 97 | | true ? 0 : + 98 | | true ? 0 : + 99 | | true ? 0 : +100 | | true ? 0 : +101 | | true ? 0 : +102 | | true ? 0 : +103 | | true ? 0 : +104 | | true ? 0 : +105 | | true ? 0 : +106 | | true ? 0 : +107 | | true ? 0 : +108 | | true ? 0 : +109 | | true ? 0 : +110 | | true ? 0 : +111 | | true ? 0 : +112 | | true ? 0 : +113 | | true ? 0 : +114 | | true ? 0 : +115 | | true ? 0 : +116 | | true ? 0 : +117 | | true ? 0 : +118 | | true ? 0 : +119 | | true ? 0 : +120 | | true ? 0 : +121 | | true ? 0 : +122 | | true ? 0 : +123 | | true ? 0 : +124 | | true ? 0 : +125 | | true ? 0 : +126 | | true ? 0 : +127 | | true ? 0 : +128 | | true ? 0 : +129 | | true ? 0 : +130 | | true ? 0 : +131 | | true ? 0 : +132 | | true ? 0 : +133 | | 0; + | |___^ +134 | } | diff --git a/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol b/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol index 309f09e9..fb685df4 100644 --- a/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol +++ b/crates/uitest/tests/fixtures/parse/excessive_conditional_nesting/main.sol @@ -1,134 +1,134 @@ -function main() -> word { +function main() returns (word) { return - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else - if true then 0 else + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : + true ? 0 : 0; } diff --git a/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/diagnostics.snap b/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/diagnostics.snap index 0f9738c4..dc82095d 100644 --- a/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.solc +input_file: crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol --- error[SC0001]: expression nesting exceeds the compiler limit of 32 - --> /main/main.solc:1:66 + --> /main/main.sol:1:73 | -1 | function main() -> word { return !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!true; } - | ^^^^^^^^^^^^ +1 | function main() returns (word) { return !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!true; } + | ^^^^^^^^^^^^ diff --git a/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol b/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol index c000fcad..df75f702 100644 --- a/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol +++ b/crates/uitest/tests/fixtures/parse/excessive_expression_nesting/main.sol @@ -1 +1 @@ -function main() -> word { return !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!true; } +function main() returns (word) { return !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!true; } diff --git a/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/diagnostics.snap b/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/diagnostics.snap index e0a2d443..d8bdf585 100644 --- a/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/diagnostics.snap @@ -1,14 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.solc +input_file: crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol --- -error[SC0001]: fallback function must return unit (`()`) - --> /main/main.solc:2:17 +error[SC0001]: parse error: unexpected identifier `returns` + --> /main/main.sol:2:14 | 1 | contract Bad { -2 | fallback() -> word {} - | ^^^^ +2 | fallback() returns (word) {} + | ^^^^^^^ unexpected token 3 | | + = note: expecting `payable`, `public`, or `{` = note: while parsing fallback definition diff --git a/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol b/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol index d10c3f58..cd30dedd 100644 --- a/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol +++ b/crates/uitest/tests/fixtures/parse/fallback_with_non_unit_return/main.sol @@ -1,5 +1,5 @@ contract Bad { - fallback() -> word {} + fallback() returns (word) {} function after() {} } diff --git a/crates/uitest/tests/fixtures/parse/fallback_with_params/diagnostics.snap b/crates/uitest/tests/fixtures/parse/fallback_with_params/diagnostics.snap index 797ceb94..4251346b 100644 --- a/crates/uitest/tests/fixtures/parse/fallback_with_params/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/fallback_with_params/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/fallback_with_params/main.solc +input_file: crates/uitest/tests/fixtures/parse/fallback_with_params/main.sol --- error[SC0001]: fallback function must not declare input parameters - --> /main/main.solc:2:11 + --> /main/main.sol:2:11 | 1 | contract Bad { 2 | fallback(x: word) {} diff --git a/crates/uitest/tests/fixtures/parse/function_param_recovery/diagnostics.snap b/crates/uitest/tests/fixtures/parse/function_param_recovery/diagnostics.snap index 400cc596..70c779b2 100644 --- a/crates/uitest/tests/fixtures/parse/function_param_recovery/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/function_param_recovery/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/function_param_recovery/main.solc +input_file: crates/uitest/tests/fixtures/parse/function_param_recovery/main.sol --- error[SC0001]: parse error: unexpected `,` - --> /main/main.solc:1:16 + --> /main/main.sol:1:16 | 1 | function bad(x:, y: U) {} | ^ unexpected token diff --git a/crates/uitest/tests/fixtures/parse/function_signature_missing_type/diagnostics.snap b/crates/uitest/tests/fixtures/parse/function_signature_missing_type/diagnostics.snap index 6b10bc21..6b306e2c 100644 --- a/crates/uitest/tests/fixtures/parse/function_signature_missing_type/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/function_signature_missing_type/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/function_signature_missing_type/main.solc +input_file: crates/uitest/tests/fixtures/parse/function_signature_missing_type/main.sol --- error[SC0001]: parse error: unexpected `)` - --> /main/main.solc:1:17 + --> /main/main.sol:1:17 | 1 | function bad(x: ) {} | ^ unexpected token diff --git a/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/diagnostics.snap b/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/diagnostics.snap index 6e2e1be9..53c61a7a 100644 --- a/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.solc +input_file: crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:4:4 + --> /main/main.sol:4:4 | 3 | return (); 4 | }; diff --git a/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol b/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol index 2ab5a6fd..abf01766 100644 --- a/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol +++ b/crates/uitest/tests/fixtures/parse/if_trailing_semicolon/main.sol @@ -1,5 +1,5 @@ function f() { - if true { + if ( true ) { return (); }; } diff --git a/crates/uitest/tests/fixtures/parse/impl_missing_head/diagnostics.snap b/crates/uitest/tests/fixtures/parse/impl_missing_head/diagnostics.snap new file mode 100644 index 00000000..abce0d12 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/impl_missing_head/diagnostics.snap @@ -0,0 +1,13 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/parse/impl_missing_head/main.sol +--- +error[SC0001]: parse error: unexpected `{` + --> /main/main.sol:1:6 + | +1 | impl {} + | ^ unexpected token + | + = note: expecting `<` + = note: while parsing impl declaration diff --git a/crates/uitest/tests/fixtures/parse/impl_missing_head/main.sol b/crates/uitest/tests/fixtures/parse/impl_missing_head/main.sol new file mode 100644 index 00000000..21261d48 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/impl_missing_head/main.sol @@ -0,0 +1 @@ +impl {} diff --git a/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/diagnostics.snap b/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/diagnostics.snap index 7035f84e..835155f7 100644 --- a/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.solc +input_file: crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol --- error[SC0001]: parse error: unexpected `(` - --> /main/main.solc:1:14 + --> /main/main.sol:1:10 | -1 | import lib.{D(C)}; - | ^ unexpected token +1 | import {D(C)} from lib; + | ^ unexpected token | = note: expecting `,`, `as`, or `}` = note: while parsing import declaration diff --git a/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol b/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol index e9299abd..b1815643 100644 --- a/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol +++ b/crates/uitest/tests/fixtures/parse/import_ctor_group_syntax/main.sol @@ -1 +1 @@ -import lib.{D(C)}; +import {D(C)} from lib; diff --git a/crates/uitest/tests/fixtures/parse/import_selector_unterminated/diagnostics.snap b/crates/uitest/tests/fixtures/parse/import_selector_unterminated/diagnostics.snap index 089c3525..efb404cd 100644 --- a/crates/uitest/tests/fixtures/parse/import_selector_unterminated/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/import_selector_unterminated/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.solc +input_file: crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol --- error[SC0001]: parse error: unexpected end of input - --> /main/main.solc:1:14 + --> /main/main.sol:1:10 | -1 | import mod.{ - | ^ unexpected token +1 | import { + | ^ unexpected token | - = note: expecting `*`, or selector name + = note: expecting selector name = note: while parsing import declaration diff --git a/crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol b/crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol index f91674fe..c762184a 100644 --- a/crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol +++ b/crates/uitest/tests/fixtures/parse/import_selector_unterminated/main.sol @@ -1 +1 @@ -import mod.{ +import { diff --git a/crates/uitest/tests/fixtures/parse/instance_missing_head/diagnostics.snap b/crates/uitest/tests/fixtures/parse/instance_missing_head/diagnostics.snap deleted file mode 100644 index 375100c3..00000000 --- a/crates/uitest/tests/fixtures/parse/instance_missing_head/diagnostics.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/parse/instance_missing_head/main.solc ---- -error[SC0001]: parse error: unexpected `{` - --> /main/main.solc:1:10 - | -1 | instance {} - | ^ unexpected token - | - = note: expecting `(`, `=>`, or predicate - = note: while parsing instance declaration diff --git a/crates/uitest/tests/fixtures/parse/instance_missing_head/main.solc b/crates/uitest/tests/fixtures/parse/instance_missing_head/main.solc deleted file mode 100644 index d45578e9..00000000 --- a/crates/uitest/tests/fixtures/parse/instance_missing_head/main.solc +++ /dev/null @@ -1 +0,0 @@ -instance {} diff --git a/crates/uitest/tests/fixtures/parse/invalid_token/diagnostics.snap b/crates/uitest/tests/fixtures/parse/invalid_token/diagnostics.snap index 4cdc756c..e922f996 100644 --- a/crates/uitest/tests/fixtures/parse/invalid_token/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/invalid_token/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/invalid_token/main.solc +input_file: crates/uitest/tests/fixtures/parse/invalid_token/main.sol --- error[SC0001]: invalid token `§` - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | 1 | § | ^ invalid token diff --git a/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/diagnostics.snap b/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/diagnostics.snap index b37f29ac..7815869d 100644 --- a/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/diagnostics.snap @@ -1,12 +1,21 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.solc +input_file: crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol --- error[SC0001]: `comptime` is a parameter modifier; expected parameter name - --> /main/main.solc:1:12 + --> /main/main.sol:1:12 | -1 | function f(comptime) -> word { return comptime; } +1 | function f(comptime) returns (word) { return comptime; } | ^^^^^^^^ | = note: while parsing function parameter +--- + +error[SC0001]: named function parameter requires an explicit type + --> /main/main.sol:1:12 + | +1 | function f(comptime) returns (word) { return comptime; } + | ^^^^^^^^ + | + = note: while parsing function signature diff --git a/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol b/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol index 72a73f39..e12b366c 100644 --- a/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol +++ b/crates/uitest/tests/fixtures/parse/keyword_comptime_identifier/main.sol @@ -1 +1 @@ -function f(comptime) -> word { return comptime; } +function f(comptime) returns (word) { return comptime; } diff --git a/crates/uitest/tests/fixtures/parse/match_arm_arity/diagnostics.snap b/crates/uitest/tests/fixtures/parse/match_arm_arity/diagnostics.snap new file mode 100644 index 00000000..a762dc58 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/match_arm_arity/diagnostics.snap @@ -0,0 +1,15 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/parse/match_arm_arity/main.sol +--- +error[SC0001]: match has 2 scrutinees but this case has 1 patterns + --> /main/main.sol:5:1 + | +4 | match (x, y) { +5 | / case Nat.Zero { +6 | | return 0; +7 | | } + | |_^ +8 | case (Nat.Succ(a), Nat.Zero) { + | diff --git a/crates/uitest/tests/fixtures/parse/match_arm_arity/main.sol b/crates/uitest/tests/fixtures/parse/match_arm_arity/main.sol new file mode 100644 index 00000000..f2f6bc02 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/match_arm_arity/main.sol @@ -0,0 +1,21 @@ +enum Nat { Zero, Succ(Nat) } + +function pick(x: Nat, y: Nat) returns (word) { + match (x, y) { +case Nat.Zero { +return 0; +} +case (Nat.Succ(a), Nat.Zero) { +return 1; +} +case (Nat.Succ(a), Nat.Succ(b)) { +return 2; +} +} +} + +contract T { + function main() public returns (word) { + return pick(Nat.Zero, Nat.Zero); + } +} From 4abd53ead698f92c2dc5adc21d31aed4f2869563 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 098/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures Co-authored-by: Codex --- .../missing_data_semicolon/diagnostics.snap | 13 ------ .../parse/missing_data_semicolon/main.solc | 1 - .../parse/missing_semicolon/diagnostics.snap | 6 +-- .../multibyte_eof_string/diagnostics.snap | 6 +-- .../parse/multibyte_eof_string/main.sol | 2 +- .../multiple_emitted_errors/diagnostics.snap | 6 +-- .../multiple_errors_continue/diagnostics.snap | 8 ++-- .../diagnostics.snap | 14 ++++++ .../main.sol | 9 ++++ .../diagnostics.snap | 14 ++++++ .../main.sol | 9 ++++ .../diagnostics.snap | 25 ++++++++++ .../parse/named_params_missing_types/main.sol | 16 +++++++ .../diagnostics.snap | 30 ++++++------ .../nullary_ctor_applied_pattern/main.sol | 12 +++-- .../pragma_missing_name/diagnostics.snap | 4 +- .../parse/public_constructor/diagnostics.snap | 8 ++-- .../parse/public_constructor/main.sol | 2 +- .../parse/public_fallback/diagnostics.snap | 8 ++-- .../fixtures/parse/public_fallback/main.sol | 2 +- .../public_free_function/diagnostics.snap | 8 ++-- .../parse/public_free_function/main.sol | 2 +- .../parse/string_bad_escape/diagnostics.snap | 8 ++-- .../fixtures/parse/string_bad_escape/main.sol | 2 +- .../parse/top_level_recovery/diagnostics.snap | 6 +-- .../trailing_call_comma/diagnostics.snap | 24 +++++----- .../parse/trailing_call_comma/main.sol | 4 +- .../diagnostics.snap | 8 ++-- .../parse/trailing_constructor_comma/main.sol | 2 +- .../trailing_import_comma/diagnostics.snap | 13 ------ .../parse/trailing_import_comma/main.solc | 1 - .../trait_missing_body_brace/diagnostics.snap | 13 ++++++ .../parse/trait_missing_body_brace/main.sol | 1 + .../diagnostics.snap | 4 +- .../diagnostics.snap | 10 ++-- .../bounded_variable_condition/main.sol | 8 ++-- .../coverage_condition/diagnostics.snap | 14 +++--- .../solver/coverage_condition/main.sol | 6 +-- .../diagnostics.snap | 12 ++--- .../main.sol | 4 +- .../diagnostics.snap | 18 ++++---- .../solver/ergo_ambiguous_defaulting/main.sol | 30 ++++++------ .../ergo_constraint_escape/diagnostics.snap | 14 +++--- .../solver/ergo_constraint_escape/main.sol | 8 ++-- .../diagnostics.snap | 12 ++--- .../solver/ergo_contract_no_instance/main.sol | 10 ++-- .../solver/ergo_fuel_blowup/diagnostics.snap | 10 ++-- .../fixtures/solver/ergo_fuel_blowup/main.sol | 12 ++--- .../ergo_inst_class_arity/diagnostics.snap | 12 ++--- .../solver/ergo_inst_class_arity/main.sol | 8 ++-- .../diagnostics.snap | 14 +++--- .../ergo_inst_method_sig_mismatch/main.sol | 10 ++-- .../ergo_inst_wrong_kind/diagnostics.snap | 10 ++-- .../solver/ergo_inst_wrong_kind/main.sol | 6 +-- .../solver/ergo_no_instance/diagnostics.snap | 12 ++--- .../fixtures/solver/ergo_no_instance/main.sol | 12 ++--- .../diagnostics.snap | 24 +++++----- .../ergo_overlapping_instances/main.sol | 14 +++--- .../ergo_patterson_violation/diagnostics.snap | 16 +++---- .../solver/ergo_patterson_violation/main.sol | 6 +-- .../diagnostics.snap | 46 +++++++++---------- .../main.sol | 8 ++-- .../pragma_scope_lib.sol | 2 +- .../instance_extra_method/diagnostics.snap | 14 +++--- .../solver/instance_extra_method/main.sol | 10 ++-- .../invalid_default_instance/diagnostics.snap | 12 ++--- .../solver/invalid_default_instance/main.sol | 4 +- .../diagnostics.snap | 12 ++--- .../main.sol | 6 +-- .../method_extra_forall/diagnostics.snap | 14 +++--- .../solver/method_extra_forall/main.sol | 10 ++-- .../non_ground_unique_answer/diagnostics.snap | 10 ++-- .../solver/non_ground_unique_answer/main.sol | 12 ++--- .../diagnostics.snap | 4 +- .../noncallable_invokable_constraint/main.sol | 2 +- .../patterson_condition/diagnostics.snap | 16 +++---- .../solver/patterson_condition/main.sol | 6 +-- .../poly_int_defaulting/diagnostics.snap | 12 ++--- .../solver/poly_int_defaulting/main.sol | 4 +- .../diagnostics.snap | 10 ++-- .../comptime_evaluation_failed/main.sol | 6 +-- .../diagnostics.snap | 6 +-- .../main.sol | 6 +-- .../ergo_ct_public_param/diagnostics.snap | 8 ++-- .../specialize/ergo_ct_public_param/main.sol | 6 +-- .../ergo_free_tyvar_ctor/diagnostics.snap | 6 +-- .../specialize/ergo_free_tyvar_ctor/main.sol | 4 +- .../diagnostics.snap | 4 +- .../ergo_integer_erasure_branch/main.sol | 12 +++-- .../ergo_poly_entry/diagnostics.snap | 6 +-- .../specialize/ergo_poly_entry/main.sol | 2 +- .../free_type_variable/diagnostics.snap | 6 +-- .../specialize/free_type_variable/main.sol | 4 +- .../integer_erasure/diagnostics.snap | 6 +-- 94 files changed, 489 insertions(+), 410 deletions(-) delete mode 100644 crates/uitest/tests/fixtures/parse/missing_data_semicolon/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/parse/missing_data_semicolon/main.solc create mode 100644 crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/main.sol create mode 100644 crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/main.sol create mode 100644 crates/uitest/tests/fixtures/parse/named_params_missing_types/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/parse/named_params_missing_types/main.sol delete mode 100644 crates/uitest/tests/fixtures/parse/trailing_import_comma/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/parse/trailing_import_comma/main.solc create mode 100644 crates/uitest/tests/fixtures/parse/trait_missing_body_brace/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/parse/trait_missing_body_brace/main.sol diff --git a/crates/uitest/tests/fixtures/parse/missing_data_semicolon/diagnostics.snap b/crates/uitest/tests/fixtures/parse/missing_data_semicolon/diagnostics.snap deleted file mode 100644 index 508d8d19..00000000 --- a/crates/uitest/tests/fixtures/parse/missing_data_semicolon/diagnostics.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/parse/missing_data_semicolon/main.solc ---- -error[SC0001]: parse error: unexpected end of input - --> /main/main.solc:1:12 - | -1 | data D = C - | ^ unexpected token - | - = note: expecting `(`, `;`, or `|` - = note: while parsing data declaration diff --git a/crates/uitest/tests/fixtures/parse/missing_data_semicolon/main.solc b/crates/uitest/tests/fixtures/parse/missing_data_semicolon/main.solc deleted file mode 100644 index 8e327275..00000000 --- a/crates/uitest/tests/fixtures/parse/missing_data_semicolon/main.solc +++ /dev/null @@ -1 +0,0 @@ -data D = C diff --git a/crates/uitest/tests/fixtures/parse/missing_semicolon/diagnostics.snap b/crates/uitest/tests/fixtures/parse/missing_semicolon/diagnostics.snap index f049be89..718c3124 100644 --- a/crates/uitest/tests/fixtures/parse/missing_semicolon/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/missing_semicolon/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/missing_semicolon/main.solc +input_file: crates/uitest/tests/fixtures/parse/missing_semicolon/main.sol --- error[SC0001]: parse error: unexpected end of input - --> /main/main.solc:1:18 + --> /main/main.sol:1:18 | 1 | import core.math | ^ unexpected token | - = note: expecting `.`, `;`, or `as` + = note: expecting `.`, or `;` = note: while parsing import declaration diff --git a/crates/uitest/tests/fixtures/parse/multibyte_eof_string/diagnostics.snap b/crates/uitest/tests/fixtures/parse/multibyte_eof_string/diagnostics.snap index 060fd1e4..6ca23e3b 100644 --- a/crates/uitest/tests/fixtures/parse/multibyte_eof_string/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/multibyte_eof_string/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.solc +input_file: crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol --- error[SC0001]: unterminated string literal - --> /main/main.solc:2:11 + --> /main/main.sol:2:11 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | let s = "café | ^^^^^ string literal starts here | diff --git a/crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol b/crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol index 5c5dcaf2..b9627b80 100644 --- a/crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol +++ b/crates/uitest/tests/fixtures/parse/multibyte_eof_string/main.sol @@ -1,2 +1,2 @@ -function f() -> word { +function f() returns (word) { let s = "café \ No newline at end of file diff --git a/crates/uitest/tests/fixtures/parse/multiple_emitted_errors/diagnostics.snap b/crates/uitest/tests/fixtures/parse/multiple_emitted_errors/diagnostics.snap index 02f8aa0f..477f9af0 100644 --- a/crates/uitest/tests/fixtures/parse/multiple_emitted_errors/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/multiple_emitted_errors/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/multiple_emitted_errors/main.solc +input_file: crates/uitest/tests/fixtures/parse/multiple_emitted_errors/main.sol --- error[SC0001]: invalid token `§` - --> /main/main.solc:1:1 + --> /main/main.sol:1:1 | 1 | § | ^ invalid token @@ -13,7 +13,7 @@ error[SC0001]: invalid token `§` --- error[SC0001]: invalid token `§` - --> /main/main.solc:2:1 + --> /main/main.sol:2:1 | 1 | § 2 | § diff --git a/crates/uitest/tests/fixtures/parse/multiple_errors_continue/diagnostics.snap b/crates/uitest/tests/fixtures/parse/multiple_errors_continue/diagnostics.snap index 5b65fafd..fb35dd34 100644 --- a/crates/uitest/tests/fixtures/parse/multiple_errors_continue/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/multiple_errors_continue/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.solc +input_file: crates/uitest/tests/fixtures/parse/multiple_errors_continue/main.sol --- error[SC0001]: import declaration requires trailing `;` - --> /main/main.solc:2:1 + --> /main/main.sol:2:1 | 1 | import core.math 2 | function bad() { @@ -15,11 +15,11 @@ error[SC0001]: import declaration requires trailing `;` --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:3:13 + --> /main/main.sol:3:13 | 2 | function bad() { 3 | let x = ; | ^ unexpected token 4 | return 1; | - = note: expecting expression after `=` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` diff --git a/crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/diagnostics.snap b/crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/diagnostics.snap new file mode 100644 index 00000000..d6e04282 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/diagnostics.snap @@ -0,0 +1,14 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/main.sol +--- +error[SC0001]: named function parameter requires an explicit type + --> /main/main.sol:2:15 + | +1 | contract C { +2 | function id(x) public { + | ^ +3 | return x; + | + = note: while parsing function signature diff --git a/crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/main.sol b/crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/main.sol new file mode 100644 index 00000000..1ef672a2 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/named_param_missing_type_contract/main.sol @@ -0,0 +1,9 @@ +contract C { + function id(x) public { + return x; + } + + function main() returns (word) { + return 0; + } +} diff --git a/crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/diagnostics.snap b/crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/diagnostics.snap new file mode 100644 index 00000000..c03aa122 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/diagnostics.snap @@ -0,0 +1,14 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/main.sol +--- +error[SC0001]: named function parameter requires an explicit type + --> /main/main.sol:1:13 + | +1 | function id(x) { + | ^ +2 | return x; +3 | } + | + = note: while parsing function signature diff --git a/crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/main.sol b/crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/main.sol new file mode 100644 index 00000000..40d70dca --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/named_param_missing_type_top_level/main.sol @@ -0,0 +1,9 @@ +function id(x) { + return x; +} + +contract C { + function main() public returns (word) { + return id(42); + } +} diff --git a/crates/uitest/tests/fixtures/parse/named_params_missing_types/diagnostics.snap b/crates/uitest/tests/fixtures/parse/named_params_missing_types/diagnostics.snap new file mode 100644 index 00000000..f1d20139 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/named_params_missing_types/diagnostics.snap @@ -0,0 +1,25 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/parse/named_params_missing_types/main.sol +--- +error[SC0001]: named function parameter requires an explicit type + --> /main/main.sol:2:20 + | +1 | contract C { +2 | function compose(f, g) public { + | ^ +3 | return lam (x) { + | + = note: while parsing function signature +--- + +error[SC0001]: named function parameter requires an explicit type + --> /main/main.sol:2:23 + | +1 | contract C { +2 | function compose(f, g) public { + | ^ +3 | return lam (x) { + | + = note: while parsing function signature diff --git a/crates/uitest/tests/fixtures/parse/named_params_missing_types/main.sol b/crates/uitest/tests/fixtures/parse/named_params_missing_types/main.sol new file mode 100644 index 00000000..ef0c6756 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/named_params_missing_types/main.sol @@ -0,0 +1,16 @@ +contract C { + function compose(f, g) public { + return lam (x) { + return f(g(x)); + }; + } + + function id(x: word) public returns (word) { + return x; + } + + function main() public returns (word) { + let f = compose(id, id); + return f(42); + } +} diff --git a/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/diagnostics.snap b/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/diagnostics.snap index 244258bb..93123fa5 100644 --- a/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/diagnostics.snap @@ -1,25 +1,25 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.solc +input_file: crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol --- -error[SC0001]: parse error: unexpected `match` - --> /main/main.solc:4:3 +error[SC0001]: parse error: unexpected `)` + --> /main/main.sol:4:11 | -3 | function f(x: D) -> word { -4 | match x { - | ^^^^^ unexpected token -5 | | C() => return 1; +3 | function f(x: D) returns (word) { +4 | match (x) { + | ^ unexpected token +5 | case C() { | - = note: expecting `!`, `(`, `.`, `@`, `[`, `if`, `lam`, or `~` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` --- -error[SC0001]: parse error: unexpected `=>` - --> /main/main.solc:5:9 +error[SC0001]: parse error: unexpected `)` + --> /main/main.sol:5:8 | -4 | match x { -5 | | C() => return 1; - | ^^ unexpected token -6 | } +4 | match (x) { +5 | case C() { + | ^ unexpected token +6 | return 1; | - = note: expecting `%=`, `&&`, `&=`, `&`, `(`, `*=`, `+=`, `-=`, `.`, `/=`, `:`, `;`, `=`, `?`, `[`, `^=`, `^`, `|=`, `|`, `||`, `~=`, end of input, or statement + = note: expecting `(`, `.`, or `_` diff --git a/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol b/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol index cd6787a2..3dad6cef 100644 --- a/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol +++ b/crates/uitest/tests/fixtures/parse/nullary_ctor_applied_pattern/main.sol @@ -1,7 +1,9 @@ -data D = C; +enum D { C } -function f(x: D) -> word { - match x { - | C() => return 1; - } +function f(x: D) returns (word) { + match (x) { +case C() { +return 1; +} +} } diff --git a/crates/uitest/tests/fixtures/parse/pragma_missing_name/diagnostics.snap b/crates/uitest/tests/fixtures/parse/pragma_missing_name/diagnostics.snap index a234f096..1fda092e 100644 --- a/crates/uitest/tests/fixtures/parse/pragma_missing_name/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/pragma_missing_name/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/pragma_missing_name/main.solc +input_file: crates/uitest/tests/fixtures/parse/pragma_missing_name/main.sol --- error[SC0001]: parse error: unexpected `;` - --> /main/main.solc:1:8 + --> /main/main.sol:1:8 | 1 | pragma ; | ^ unexpected token diff --git a/crates/uitest/tests/fixtures/parse/public_constructor/diagnostics.snap b/crates/uitest/tests/fixtures/parse/public_constructor/diagnostics.snap index fd84c524..71723703 100644 --- a/crates/uitest/tests/fixtures/parse/public_constructor/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/public_constructor/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/public_constructor/main.solc +input_file: crates/uitest/tests/fixtures/parse/public_constructor/main.sol --- error[SC0001]: constructor is implicitly public; remove the 'public' keyword - --> /main/main.solc:2:3 + --> /main/main.sol:2:17 | 1 | contract Bad { -2 | public constructor() {} - | ^^^^^^ +2 | constructor() public {} + | ^^^^^^ 3 | | = note: while parsing constructor definition diff --git a/crates/uitest/tests/fixtures/parse/public_constructor/main.sol b/crates/uitest/tests/fixtures/parse/public_constructor/main.sol index bc487a53..9bc248c4 100644 --- a/crates/uitest/tests/fixtures/parse/public_constructor/main.sol +++ b/crates/uitest/tests/fixtures/parse/public_constructor/main.sol @@ -1,5 +1,5 @@ contract Bad { - public constructor() {} + constructor() public {} function after() {} } diff --git a/crates/uitest/tests/fixtures/parse/public_fallback/diagnostics.snap b/crates/uitest/tests/fixtures/parse/public_fallback/diagnostics.snap index 7bbaa7c5..d1a56320 100644 --- a/crates/uitest/tests/fixtures/parse/public_fallback/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/public_fallback/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/public_fallback/main.solc +input_file: crates/uitest/tests/fixtures/parse/public_fallback/main.sol --- error[SC0001]: fallback is implicitly public; remove the 'public' keyword - --> /main/main.solc:2:3 + --> /main/main.sol:2:14 | 1 | contract Bad { -2 | public fallback() {} - | ^^^^^^ +2 | fallback() public {} + | ^^^^^^ 3 | | = note: while parsing fallback definition diff --git a/crates/uitest/tests/fixtures/parse/public_fallback/main.sol b/crates/uitest/tests/fixtures/parse/public_fallback/main.sol index 5bc8b97e..6ec041f2 100644 --- a/crates/uitest/tests/fixtures/parse/public_fallback/main.sol +++ b/crates/uitest/tests/fixtures/parse/public_fallback/main.sol @@ -1,5 +1,5 @@ contract Bad { - public fallback() {} + fallback() public {} function after() {} } diff --git a/crates/uitest/tests/fixtures/parse/public_free_function/diagnostics.snap b/crates/uitest/tests/fixtures/parse/public_free_function/diagnostics.snap index 22f093d8..a52ce449 100644 --- a/crates/uitest/tests/fixtures/parse/public_free_function/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/public_free_function/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/public_free_function/main.solc +input_file: crates/uitest/tests/fixtures/parse/public_free_function/main.sol --- error[SC0001]: 'public' is only allowed on functions declared inside a contract - --> /main/main.solc:1:1 + --> /main/main.sol:1:16 | -1 | public function bad() {} - | ^^^^^^ +1 | function bad() public {} + | ^^^^^^ 2 | 3 | function after() {} | diff --git a/crates/uitest/tests/fixtures/parse/public_free_function/main.sol b/crates/uitest/tests/fixtures/parse/public_free_function/main.sol index 5983ec5f..5dffb2f9 100644 --- a/crates/uitest/tests/fixtures/parse/public_free_function/main.sol +++ b/crates/uitest/tests/fixtures/parse/public_free_function/main.sol @@ -1,3 +1,3 @@ -public function bad() {} +function bad() public {} function after() {} diff --git a/crates/uitest/tests/fixtures/parse/string_bad_escape/diagnostics.snap b/crates/uitest/tests/fixtures/parse/string_bad_escape/diagnostics.snap index faffbbb5..7db2f98a 100644 --- a/crates/uitest/tests/fixtures/parse/string_bad_escape/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/string_bad_escape/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/string_bad_escape/main.solc +input_file: crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol --- error[SC0001]: invalid string escape `/q` - --> /main/main.solc:1:33 + --> /main/main.sol:1:40 | -1 | function f() -> string { return "a/q"; } - | ^^^^^ invalid escape sequence +1 | function f() returns (string) { return "a/q"; } + | ^^^^^ invalid escape sequence diff --git a/crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol b/crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol index e5178a88..5de7e713 100644 --- a/crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol +++ b/crates/uitest/tests/fixtures/parse/string_bad_escape/main.sol @@ -1 +1 @@ -function f() -> string { return "a\q"; } +function f() returns (string) { return "a\q"; } diff --git a/crates/uitest/tests/fixtures/parse/top_level_recovery/diagnostics.snap b/crates/uitest/tests/fixtures/parse/top_level_recovery/diagnostics.snap index f66f4ded..30cc2f64 100644 --- a/crates/uitest/tests/fixtures/parse/top_level_recovery/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/top_level_recovery/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/top_level_recovery/main.solc +input_file: crates/uitest/tests/fixtures/parse/top_level_recovery/main.sol --- -error[SC0001]: could not parse top-level item near `unknown nonsense tokens`; expected a declaration starting with `import`, `pragma`, `type`, `data`, `class`, `instance`, `contract`, or `function` - --> /main/main.solc:2:1 +error[SC0001]: could not parse top-level item near `unknown nonsense tokens`; expected a declaration starting with `import`, `pragma`, `type`, `enum`, `trait`, `impl`, `contract`, or `function` + --> /main/main.sol:2:1 | 1 | function first() {} 2 | unknown nonsense tokens diff --git a/crates/uitest/tests/fixtures/parse/trailing_call_comma/diagnostics.snap b/crates/uitest/tests/fixtures/parse/trailing_call_comma/diagnostics.snap index 4786f703..57b8b531 100644 --- a/crates/uitest/tests/fixtures/parse/trailing_call_comma/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/trailing_call_comma/diagnostics.snap @@ -1,23 +1,23 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/trailing_call_comma/main.solc +input_file: crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol --- -error[SC0001]: parse error: unexpected `return` - --> /main/main.solc:2:24 +error[SC0001]: parse error: unexpected `,` + --> /main/main.sol:2:41 | -1 | function g(x: word) -> word { return x; } -2 | function f() -> word { return g(1,); } - | ^^^^^^ unexpected token +1 | function g(x: word) returns (word) { return x; } +2 | function f() returns (word) { return g(1,); } + | ^ unexpected token | - = note: expecting `!`, `(`, `.`, `@`, `[`, `if`, `lam`, or `~` + = note: expecting `&&`, `&`, `(`, `.`, `?`, `[`, `^`, `|`, or `||` --- error[SC0001]: parse error: unexpected `)` - --> /main/main.solc:2:35 + --> /main/main.sol:2:42 | -1 | function g(x: word) -> word { return x; } -2 | function f() -> word { return g(1,); } - | ^ unexpected token +1 | function g(x: word) returns (word) { return x; } +2 | function f() returns (word) { return g(1,); } + | ^ unexpected token | - = note: expecting `!`, `(`, `.`, `@`, `[`, `if`, `lam`, or `~` + = note: expecting `!`, `(`, `.`, `@`, `[`, `lam`, or `~` diff --git a/crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol b/crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol index 78e36bd3..9cf897f6 100644 --- a/crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol +++ b/crates/uitest/tests/fixtures/parse/trailing_call_comma/main.sol @@ -1,2 +1,2 @@ -function g(x: word) -> word { return x; } -function f() -> word { return g(1,); } +function g(x: word) returns (word) { return x; } +function f() returns (word) { return g(1,); } diff --git a/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/diagnostics.snap b/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/diagnostics.snap index 0708b14f..cc363273 100644 --- a/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.solc +input_file: crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol --- error[SC0001]: parse error: unexpected `)` - --> /main/main.solc:1:17 + --> /main/main.sol:1:17 | -1 | data D = C(word,); +1 | enum D { C(word,) } | ^ unexpected token | = note: expecting type - = note: while parsing data declaration + = note: while parsing enum declaration diff --git a/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol b/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol index 3625006e..033dc120 100644 --- a/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol +++ b/crates/uitest/tests/fixtures/parse/trailing_constructor_comma/main.sol @@ -1 +1 @@ -data D = C(word,); +enum D { C(word,) } diff --git a/crates/uitest/tests/fixtures/parse/trailing_import_comma/diagnostics.snap b/crates/uitest/tests/fixtures/parse/trailing_import_comma/diagnostics.snap deleted file mode 100644 index ae369e1f..00000000 --- a/crates/uitest/tests/fixtures/parse/trailing_import_comma/diagnostics.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/parse/trailing_import_comma/main.solc ---- -error[SC0001]: parse error: unexpected `}` - --> /main/main.solc:1:16 - | -1 | import m.{a, b,}; - | ^ unexpected token - | - = note: expecting `*`, or selector name - = note: while parsing import declaration diff --git a/crates/uitest/tests/fixtures/parse/trailing_import_comma/main.solc b/crates/uitest/tests/fixtures/parse/trailing_import_comma/main.solc deleted file mode 100644 index f0bdad5e..00000000 --- a/crates/uitest/tests/fixtures/parse/trailing_import_comma/main.solc +++ /dev/null @@ -1 +0,0 @@ -import m.{a, b,}; diff --git a/crates/uitest/tests/fixtures/parse/trait_missing_body_brace/diagnostics.snap b/crates/uitest/tests/fixtures/parse/trait_missing_body_brace/diagnostics.snap new file mode 100644 index 00000000..e53ffa9b --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/trait_missing_body_brace/diagnostics.snap @@ -0,0 +1,13 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/parse/trait_missing_body_brace/main.sol +--- +error[SC0001]: parse error: unexpected end of input + --> /main/main.sol:1:12 + | +1 | trait T + | ^ unexpected token + | + = note: expecting `{` + = note: while parsing trait declaration diff --git a/crates/uitest/tests/fixtures/parse/trait_missing_body_brace/main.sol b/crates/uitest/tests/fixtures/parse/trait_missing_body_brace/main.sol new file mode 100644 index 00000000..a48771e8 --- /dev/null +++ b/crates/uitest/tests/fixtures/parse/trait_missing_body_brace/main.sol @@ -0,0 +1 @@ +trait T diff --git a/crates/uitest/tests/fixtures/parse/type_alias_missing_equals/diagnostics.snap b/crates/uitest/tests/fixtures/parse/type_alias_missing_equals/diagnostics.snap index f13eb5c7..d95091ab 100644 --- a/crates/uitest/tests/fixtures/parse/type_alias_missing_equals/diagnostics.snap +++ b/crates/uitest/tests/fixtures/parse/type_alias_missing_equals/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/parse/type_alias_missing_equals/main.solc +input_file: crates/uitest/tests/fixtures/parse/type_alias_missing_equals/main.sol --- error[SC0001]: parse error: unexpected identifier `U` - --> /main/main.solc:1:13 + --> /main/main.sol:1:13 | 1 | type Amount U; | ^ unexpected token diff --git a/crates/uitest/tests/fixtures/solver/bounded_variable_condition/diagnostics.snap b/crates/uitest/tests/fixtures/solver/bounded_variable_condition/diagnostics.snap index b51fe158..86ed9f22 100644 --- a/crates/uitest/tests/fixtures/solver/bounded_variable_condition/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/bounded_variable_condition/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.solc +input_file: crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol --- error[SC0214]: Bounded variable condition fails! - --> /main/main.solc:5:31 + --> /main/main.sol:5:12 | -3 | forall a b . class a:Container(b) {} +3 | trait Container {} 4 | -5 | forall a c . c:Eq => instance Box(a):Container(a) {} - | ^^^^^^^^^^^^^^^^^^^ instance head is missing context variables +5 | impl Container, a> where c: Eq {} + | ^^^^^^^^^^^^^^^^^^^^ impl head is missing context variables diff --git a/crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol b/crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol index 43dc0a1f..61c97af8 100644 --- a/crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol +++ b/crates/uitest/tests/fixtures/solver/bounded_variable_condition/main.sol @@ -1,5 +1,5 @@ -data Box(a) = Box(word); -forall a . class a:Eq {} -forall a b . class a:Container(b) {} +enum Box { Box(word) } +trait Eq {} +trait Container {} -forall a c . c:Eq => instance Box(a):Container(a) {} +impl Container, a> where c: Eq {} diff --git a/crates/uitest/tests/fixtures/solver/coverage_condition/diagnostics.snap b/crates/uitest/tests/fixtures/solver/coverage_condition/diagnostics.snap index 2d0737c2..5aedac0d 100644 --- a/crates/uitest/tests/fixtures/solver/coverage_condition/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/coverage_condition/diagnostics.snap @@ -1,17 +1,17 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/coverage_condition/main.solc +input_file: crates/uitest/tests/fixtures/solver/coverage_condition/main.sol --- -error[SC0212]: Coverage condition fails for class: +error[SC0212]: Coverage condition fails for trait: MyClass - the type: - Box(a) + Box does not determine: b - --> /main/main.solc:4:23 + --> /main/main.sol:4:12 | -2 | forall a b . class a:MyClass(b) {} +2 | trait MyClass {} 3 | -4 | forall a b . instance Box(a):MyClass(b) {} - | ^^^^^^^^^^^^^^^^^ instance head does not determine these variables +4 | impl MyClass, b> {} + | ^^^^^^^^^^^^^^^^^^ impl head does not determine these variables diff --git a/crates/uitest/tests/fixtures/solver/coverage_condition/main.sol b/crates/uitest/tests/fixtures/solver/coverage_condition/main.sol index 1f8d5cc4..27feb73d 100644 --- a/crates/uitest/tests/fixtures/solver/coverage_condition/main.sol +++ b/crates/uitest/tests/fixtures/solver/coverage_condition/main.sol @@ -1,4 +1,4 @@ -data Box(a) = Box(word); -forall a b . class a:MyClass(b) {} +enum Box { Box(word) } +trait MyClass {} -forall a b . instance Box(a):MyClass(b) {} +impl MyClass, b> {} diff --git a/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/diagnostics.snap b/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/diagnostics.snap index 48886b07..ef4ce899 100644 --- a/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/diagnostics.snap @@ -1,17 +1,17 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.solc +input_file: crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol --- -error[SC0212]: Coverage condition fails for class: +error[SC0212]: Coverage condition fails for trait: MyClass - the type: word does not determine: a - --> /main/main.solc:4:21 + --> /main/main.sol:4:9 | -2 | forall a b . class a:MyClass(b) {} +2 | trait MyClass {} 3 | -4 | forall a . instance Phantom(a):MyClass(a) {} - | ^^^^^^^^^^^^^^^^^^^^^ instance head does not determine these variables +4 | impl MyClass, a> {} + | ^^^^^^^^^^^^^^^^^^^^^^ impl head does not determine these variables diff --git a/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol b/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol index 0a9b5c14..31ba7b74 100644 --- a/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol +++ b/crates/uitest/tests/fixtures/solver/coverage_condition_alias_expansion/main.sol @@ -1,4 +1,4 @@ type Phantom(a) = word; -forall a b . class a:MyClass(b) {} +trait MyClass {} -forall a . instance Phantom(a):MyClass(a) {} +impl MyClass, a> {} diff --git a/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/diagnostics.snap index 6e11392b..ea4e7a38 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/diagnostics.snap @@ -1,17 +1,17 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol --- error[SC0299]: ambiguous inferred type - --> /main/main.solc:28:22 + --> /main/main.sol:30:29 | -27 | -28 | function f() -> word { - | ______________________^ -29 | | return Conv.out(Conv.make(1)); -30 | | } +29 | +30 | function f() returns (word) { + | _____________________________^ +31 | | return Conv.out(Conv.make(1)); +32 | | } | |_^ ambiguous inferred type | - = note: forall _ . _ : Conv => () -> word - = help: add a type annotation or a matching instance to fix the ambiguous type variable + = note: <_> function() returns (word) where _: Conv + = help: add a type annotation or a matching impl to fix the ambiguous type variable diff --git a/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol b/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol index 873fad24..f1a502c3 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_ambiguous_defaulting/main.sol @@ -1,30 +1,32 @@ -data Wrap = Wrap(word); +enum Wrap { Wrap(word) } -forall a . class a : Conv { - function make(x: word) -> a; - function out(y: a) -> word; +trait Conv { + function make(x: word) returns (a) ; + function out(y: a) returns (word) ; } -instance word : Conv { - function make(x: word) -> word { +impl Conv { + function make(x: word) returns (word) { return x; } - function out(y: word) -> word { + function out(y: word) returns (word) { return y; } } -instance Wrap : Conv { - function make(x: word) -> Wrap { +impl Conv { + function make(x: word) returns (Wrap) { return Wrap(x); } - function out(y: Wrap) -> word { - match y { - | Wrap(w) => return w; - } + function out(y: Wrap) returns (word) { + match (y) { +case Wrap(w) { +return w; +} +} } } -function f() -> word { +function f() returns (word) { return Conv.out(Conv.make(1)); } diff --git a/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/diagnostics.snap index 22116269..44bfb589 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol --- -error[SC0207]: cannot satisfy class constraint: a : Same - --> /main/main.solc:7:8 +error[SC0207]: cannot satisfy trait constraint: a: Same + --> /main/main.sol:7:12 | 6 | -7 | forall a . function f(x: a) -> Bool { - | ^ constraint originates here +7 | function f(x: a) returns (Bool) { + | ^ constraint originates here 8 | return Same.same(x, x); | - = note: no visible instance matches `a : Same` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `a: Same` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol b/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol index c0e7035f..4be339ab 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_constraint_escape/main.sol @@ -1,9 +1,9 @@ -data Bool = True | False; +enum Bool { True, False } -forall a . class a : Same { - function same(x: a, y: a) -> Bool; +trait Same { + function same(x: a, y: a) returns (Bool) ; } -forall a . function f(x: a) -> Bool { +function f(x: a) returns (Bool) { return Same.same(x, x); } diff --git a/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/diagnostics.snap index dc40d04e..8b5f836b 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol --- -error[SC0207]: cannot satisfy class constraint: word : Eq - --> /main/main.solc:9:12 +error[SC0207]: cannot satisfy trait constraint: word: Eq + --> /main/main.sol:9:12 | - 8 | function go(x: word) -> Bool { + 8 | function go(x: word) returns (Bool) { 9 | return Eq.eq(x, x); | ^^^^^^^^^^^ constraint originates here 10 | } | - = note: no visible instance matches `word : Eq` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `word: Eq` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol b/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol index 5a2784cf..c4c4436c 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_contract_no_instance/main.sol @@ -1,13 +1,13 @@ -data Bool = True | False; +enum Bool { True, False } -forall a . class a : Eq { - function eq(x: a, y: a) -> Bool; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } contract Check { - function go(x: word) -> Bool { + function go(x: word) returns (Bool) { return Eq.eq(x, x); } - function main() -> () {} + function main() {} } diff --git a/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/diagnostics.snap index 0354cfb1..565f04f5 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol --- -error[SC0209]: cannot solve class constraint `word : C`: solver exceeded its iteration bound - --> /main/main.solc:16:10 +error[SC0209]: cannot solve trait constraint `word: C`: solver exceeded its iteration bound + --> /main/main.sol:16:10 | -15 | function f() -> word { +15 | function f() returns (word) { 16 | return C.c(0); | ^^^^^^ constraint originates here 17 | } | - = help: simplify the instance chain or add a more direct instance + = help: simplify the impl chain or add a more direct impl diff --git a/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol b/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol index cfb7df44..59e1c010 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_fuel_blowup/main.sol @@ -1,17 +1,17 @@ pragma no-patterson-condition ; -data Box(a) = MkBox(a); +enum Box { MkBox(a) } -forall a . class a : C { - function c(x: a) -> word; +trait C { + function c(x: a) returns (word) ; } -forall a . Box(a) : C => instance a : C { - function c(x: a) -> word { +impl C where Box: C { + function c(x: a) returns (word) { return 1; } } -function f() -> word { +function f() returns (word) { return C.c(0); } diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/diagnostics.snap index 5ee9a662..92fce73a 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol --- -error[SC0217]: class arity mismatch for `Rel`: expected 1, got 0 - --> /main/main.solc:5:10 +error[SC0217]: trait arity mismatch for `Rel`: expected 1, got 0 + --> /main/main.sol:5:6 | 4 | -5 | instance word : Rel { - | ^^^^^^^^^^ class predicate arity mismatch -6 | function rel(x: word, y: word) -> word { +5 | impl Rel { + | ^^^^^^^^^ trait predicate arity mismatch +6 | function rel(x: word, y: word) returns (word) { | diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol b/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol index 8f6e8c9f..f9340fc4 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_inst_class_arity/main.sol @@ -1,9 +1,9 @@ -forall a b . class a : Rel(b) { - function rel(x: a, y: b) -> word; +trait Rel { + function rel(x: a, y: b) returns (word) ; } -instance word : Rel { - function rel(x: word, y: word) -> word { +impl Rel { + function rel(x: word, y: word) returns (word) { return 1; } } diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/diagnostics.snap index 04f5de57..abb91d19 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol --- -error[SC0221]: invalid instance member signature for `size`: expected (Bool) -> word, got (Bool) -> Bool - --> /main/main.solc:8:3 +error[SC0221]: invalid impl member signature for `size`: expected function(Bool) returns (word), got function(Bool) returns (Bool) + --> /main/main.sol:8:3 | -7 | instance Bool : Sz { -8 | function size(x: Bool) -> Bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid instance method signature +7 | impl Sz { +8 | function size(x: Bool) returns (Bool) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid impl method signature 9 | return x; | - = note: the instance method must match the class method after substituting the instance head + = note: the impl method must match the trait method after substituting the impl head diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol b/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol index 0c2ea9e7..0c48e493 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_inst_method_sig_mismatch/main.sol @@ -1,11 +1,11 @@ -data Bool = True | False; +enum Bool { True, False } -forall a . class a : Sz { - function size(x: a) -> word; +trait Sz { + function size(x: a) returns (word) ; } -instance Bool : Sz { - function size(x: Bool) -> Bool { +impl Sz { + function size(x: Bool) returns (Bool) { return x; } } diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/diagnostics.snap index 59d222f7..d43aeb47 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol --- error[SC0299]: Invalid number of type arguments! - --> /main/main.solc:5:10 + --> /main/main.sol:5:8 | -3 | forall a . class a : C {} +3 | trait C {} 4 | -5 | instance Box : C {} - | ^^^ diagnostic reported here +5 | impl C {} + | ^^^ diagnostic reported here | = note: Type Box is expected to have 1 type arguments = note: but, type Box has 0 arguments diff --git a/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol b/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol index a279b387..b319980b 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_inst_wrong_kind/main.sol @@ -1,5 +1,5 @@ -data Box(a) = Box(a); +enum Box { Box(a) } -forall a . class a : C {} +trait C {} -instance Box : C {} +impl C {} diff --git a/crates/uitest/tests/fixtures/solver/ergo_no_instance/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_no_instance/diagnostics.snap index 45c69a81..8c0353cb 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_no_instance/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_no_instance/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_no_instance/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol --- -error[SC0207]: cannot satisfy class constraint: Bool : Eq - --> /main/main.solc:14:10 +error[SC0207]: cannot satisfy trait constraint: Bool: Eq + --> /main/main.sol:14:10 | -13 | function f() -> Bool { +13 | function f() returns (Bool) { 14 | return Eq.eq(Bool.True, Bool.False); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constraint originates here 15 | } | - = note: no visible instance matches `Bool : Eq` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `Bool: Eq` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol b/crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol index 8cf56c6e..20bf66a8 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_no_instance/main.sol @@ -1,15 +1,15 @@ -data Bool = True | False; +enum Bool { True, False } -forall a . class a : Eq { - function eq(x: a, y: a) -> Bool; +trait Eq { + function eq(x: a, y: a) returns (Bool) ; } -instance word : Eq { - function eq(x: word, y: word) -> Bool { +impl Eq { + function eq(x: word, y: word) returns (Bool) { return Bool.True; } } -function f() -> Bool { +function f() returns (Bool) { return Eq.eq(Bool.True, Bool.False); } diff --git a/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/diagnostics.snap index 8aa65cbd..e6bbe085 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/diagnostics.snap @@ -1,22 +1,22 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol --- -error[SC0218]: Overlapping instances are not supported - instance: - word : C +error[SC0218]: Overlapping impls are not supported + impl: + word: C overlaps with: - word : C - --> /main/main.solc:11:10 + word: C + --> /main/main.sol:11:6 | 4 | - 5 | instance word : C { - | -------- previous overlapping instance - 6 | function c(x: word) -> word { + 5 | impl C { + | ------- previous overlapping impl + 6 | function c(x: word) returns (word) { ... 10 | -11 | instance word : C { - | ^^^^^^^^ overlapping instance -12 | function c(x: word) -> word { +11 | impl C { + | ^^^^^^^ overlapping impl +12 | function c(x: word) returns (word) { | diff --git a/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol b/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol index 1896cddf..8ed46eb3 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_overlapping_instances/main.sol @@ -1,19 +1,19 @@ -forall a . class a : C { - function c(x: a) -> word; +trait C { + function c(x: a) returns (word) ; } -instance word : C { - function c(x: word) -> word { +impl C { + function c(x: word) returns (word) { return 1; } } -instance word : C { - function c(x: word) -> word { +impl C { + function c(x: word) returns (word) { return 2; } } -function f() -> word { +function f() returns (word) { return C.c(0); } diff --git a/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/diagnostics.snap b/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/diagnostics.snap index 6940aedd..9e0d562c 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.solc +input_file: crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol --- -error[SC0213]: instance `U : C1` does not satisfy the Patterson conditions - --> /main/main.solc:4:39 +error[SC0213]: impl `U: C1` does not satisfy the Patterson conditions + --> /main/main.sol:4:9 | -2 | forall a . class a : C2 {} +2 | trait C2 {} 3 | -4 | forall U . U : C1, U : C2 => instance U : C1 {} - | ^^^^^^ instance head violates Patterson condition +4 | impl C1 where U: C1, U: C2 {} + | ^^^^^ impl head violates Patterson condition | - = note: each instance context must be structurally smaller than the instance head - = help: remove the recursive context, add a more specific instance, or use the Patterson-condition pragma intentionally + = note: each impl context must be structurally smaller than the impl head + = help: remove the recursive context, add a more specific impl, or use the Patterson-condition pragma intentionally diff --git a/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol b/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol index b5689070..772f9d7f 100644 --- a/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol +++ b/crates/uitest/tests/fixtures/solver/ergo_patterson_violation/main.sol @@ -1,4 +1,4 @@ -forall a . class a : C1 {} -forall a . class a : C2 {} +trait C1 {} +trait C2 {} -forall U . U : C1, U : C2 => instance U : C1 {} +impl C1 where U: C1, U: C2 {} diff --git a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/diagnostics.snap b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/diagnostics.snap index d5f1cb92..6fcbeab5 100644 --- a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/diagnostics.snap @@ -1,44 +1,44 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.solc +input_file: crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol --- -error[SC0212]: Coverage condition fails for class: +error[SC0212]: Coverage condition fails for trait: C - the type: - List(b) + List does not determine: a - --> /main/main.solc:7:23 + --> /main/main.sol:7:12 | 6 | -7 | forall a b . instance List(b) : C(a, List(a)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ instance head does not determine these variables -8 | forall x . x:C(word, word) => instance x:C(word, word) {} +7 | impl C, a, List> {} + | ^^^^^^^^^^^^^^^^^^^^^^ impl head does not determine these variables +8 | impl C where x: C {} | --- -error[SC0213]: instance `x : C(word, word)` does not satisfy the Patterson conditions - --> /main/main.solc:8:40 +error[SC0213]: impl `x: C` does not satisfy the Patterson conditions + --> /main/main.sol:8:9 | 6 | -7 | forall a b . instance List(b) : C(a, List(a)) {} -8 | forall x . x:C(word, word) => instance x:C(word, word) {} - | ^^^^^^^^^^^^^^^ instance head violates Patterson condition +7 | impl C, a, List> {} +8 | impl C where x: C {} + | ^^^^^^^^^^^^^^^^ impl head violates Patterson condition | - = note: each instance context must be structurally smaller than the instance head - = help: remove the recursive context, add a more specific instance, or use the Patterson-condition pragma intentionally + = note: each impl context must be structurally smaller than the impl head + = help: remove the recursive context, add a more specific impl, or use the Patterson-condition pragma intentionally --- -error[SC0218]: Overlapping instances are not supported - instance: - x : C(word, word) +error[SC0218]: Overlapping impls are not supported + impl: + x: C overlaps with: - List(_) : C(_, List(_)) - --> /main/main.solc:8:40 + List<_>: C<_, List<_>> + --> /main/main.sol:8:9 | 6 | -7 | forall a b . instance List(b) : C(a, List(a)) {} - | ----------------------- previous overlapping instance -8 | forall x . x:C(word, word) => instance x:C(word, word) {} - | ^^^^^^^^^^^^^^^ overlapping instance +7 | impl C, a, List> {} + | ---------------------- previous overlapping impl +8 | impl C where x: C {} + | ^^^^^^^^^^^^^^^^ overlapping impl diff --git a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol index ae9ca254..c77fdb30 100644 --- a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol +++ b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/main.sol @@ -1,8 +1,8 @@ import pragma_scope_lib; -data List(a) = Nil | Cons(a, List(a)); +enum List { Nil, Cons(a, List) } -forall a b c . class a : C(b, c) {} +trait C {} -forall a b . instance List(b) : C(a, List(a)) {} -forall x . x:C(word, word) => instance x:C(word, word) {} +impl C, a, List> {} +impl C where x: C {} diff --git a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.sol b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.sol index 035f940a..100259b8 100644 --- a/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.sol +++ b/crates/uitest/tests/fixtures/solver/imported_pragma_does_not_suppress_local/pragma_scope_lib.sol @@ -2,6 +2,6 @@ export { helper }; pragma no-patterson-condition C; -function helper() -> word { +function helper() returns (word) { return 1; } diff --git a/crates/uitest/tests/fixtures/solver/instance_extra_method/diagnostics.snap b/crates/uitest/tests/fixtures/solver/instance_extra_method/diagnostics.snap index 14353455..dc8f92e4 100644 --- a/crates/uitest/tests/fixtures/solver/instance_extra_method/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/instance_extra_method/diagnostics.snap @@ -1,18 +1,18 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/instance_extra_method/main.solc +input_file: crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol --- error[SC0202]: undefined name: C.g - --> /main/main.solc:7:12 + --> /main/main.sol:7:12 | -1 | forall a . class a : C { - | - class defined here -2 | function f(x: a) -> word; +1 | trait C { + | - trait defined here +2 | function f(x: a) returns (word) ; 3 | } ... -6 | function f(x: word) -> word { return x; } -7 | function g(x: word) -> word { return x; } +6 | function f(x: word) returns (word) { return x; } +7 | function g(x: word) returns (word) { return x; } | ^ unknown name 8 | } | diff --git a/crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol b/crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol index 20a5d184..38f86b23 100644 --- a/crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol +++ b/crates/uitest/tests/fixtures/solver/instance_extra_method/main.sol @@ -1,8 +1,8 @@ -forall a . class a : C { - function f(x: a) -> word; +trait C { + function f(x: a) returns (word) ; } -instance word : C { - function f(x: word) -> word { return x; } - function g(x: word) -> word { return x; } +impl C { + function f(x: word) returns (word) { return x; } + function g(x: word) returns (word) { return x; } } diff --git a/crates/uitest/tests/fixtures/solver/invalid_default_instance/diagnostics.snap b/crates/uitest/tests/fixtures/solver/invalid_default_instance/diagnostics.snap index 35ccb7bf..238950db 100644 --- a/crates/uitest/tests/fixtures/solver/invalid_default_instance/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/invalid_default_instance/diagnostics.snap @@ -1,11 +1,11 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/invalid_default_instance/main.solc +input_file: crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol --- -error[SC0219]: Cannot have a default instance whose main argument contains no type variable: word : C - --> /main/main.solc:2:18 +error[SC0219]: Cannot have a default impl whose main argument contains no type variable: word: C + --> /main/main.sol:2:14 | -1 | forall a . class a:C {} -2 | default instance word:C {} - | ^^^^^^ invalid default instance head +1 | trait C {} +2 | default impl C {} + | ^^^^^^^ invalid default impl head diff --git a/crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol b/crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol index 8113191f..8f959b16 100644 --- a/crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol +++ b/crates/uitest/tests/fixtures/solver/invalid_default_instance/main.sol @@ -1,2 +1,2 @@ -forall a . class a:C {} -default instance word:C {} +trait C {} +default impl C {} diff --git a/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/diagnostics.snap b/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/diagnostics.snap index 3921ecd6..280f1502 100644 --- a/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.solc +input_file: crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol --- -error[SC0207]: cannot satisfy class constraint: word : C - --> /main/main.solc:6:10 +error[SC0207]: cannot satisfy trait constraint: word: C + --> /main/main.sol:6:10 | -5 | forall a . a:C => function bad() -> word { +5 | function bad() returns (word) where a: C { 6 | return C.c(1); | ^^^^^^ constraint originates here 7 | } | - = note: no visible instance matches `word : C` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `word: C` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol b/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol index 2ce22b22..9ecfa84b 100644 --- a/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol +++ b/crates/uitest/tests/fixtures/solver/local_given_rigid_var_unsatisfied/main.sol @@ -1,7 +1,7 @@ -forall a . class a:C { - function c(x:a) -> word; +trait C { + function c(x: a) returns (word) ; } -forall a . a:C => function bad() -> word { +function bad() returns (word) where a: C { return C.c(1); } diff --git a/crates/uitest/tests/fixtures/solver/method_extra_forall/diagnostics.snap b/crates/uitest/tests/fixtures/solver/method_extra_forall/diagnostics.snap index 16d2e3cb..89808cdd 100644 --- a/crates/uitest/tests/fixtures/solver/method_extra_forall/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/method_extra_forall/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/method_extra_forall/main.solc +input_file: crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol --- error[SC0299]: ambiguous inferred type - --> /main/main.solc:7:10 + --> /main/main.sol:7:6 | 6 | -7 | instance word : C { - | ^^^^^^^^ ambiguous inferred type -8 | forall b . b:D => function f(x: word) -> word { return x; } +7 | impl C { + | ^^^^^^^ ambiguous inferred type +8 | function f(x: word) returns (word) where b: D { return x; } | - = note: forall b. b : D => (word) -> word - = help: add a type annotation or a matching instance to fix the ambiguous type variable + = note: function(word) returns (word) where b: D + = help: add a type annotation or a matching impl to fix the ambiguous type variable diff --git a/crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol b/crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol index f64d3892..526952f7 100644 --- a/crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol +++ b/crates/uitest/tests/fixtures/solver/method_extra_forall/main.sol @@ -1,9 +1,9 @@ -forall a . class a : C { - function f(x: a) -> word; +trait C { + function f(x: a) returns (word) ; } -forall b . class b : D {} +trait D {} -instance word : C { - forall b . b:D => function f(x: word) -> word { return x; } +impl C { + function f(x: word) returns (word) where b: D { return x; } } diff --git a/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/diagnostics.snap b/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/diagnostics.snap index 74a91d29..b3c40b58 100644 --- a/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.solc +input_file: crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol --- -error[SC0208]: ambiguous class constraint: word : Parent - --> /main/main.solc:12:10 +error[SC0208]: ambiguous trait constraint: word: Parent + --> /main/main.sol:12:10 | -11 | forall unused . function trigger() -> word { +11 | function trigger() returns (word) { 12 | return use(0); | ^^^^^^ ambiguous constraint here 13 | } | = note: the matching proof leaves existential type variables unresolved - = help: make the type more specific or remove overlapping instances + = help: make the type more specific or remove overlapping impls diff --git a/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol b/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol index 85ad78a1..70c817ae 100644 --- a/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol +++ b/crates/uitest/tests/fixtures/solver/non_ground_unique_answer/main.sol @@ -1,17 +1,17 @@ pragma no-coverage-condition; -forall a . class a:Parent {} -forall a b . a:Parent => class a:Child(b) {} -forall b . instance word:Child(b) {} +trait Parent {} +trait Child where a: Parent {} +impl Child {} -forall a . a:Parent => function use(x: a) -> a { +function use(x: a) returns (a) where a: Parent { return x; } -forall unused . function trigger() -> word { +function trigger() returns (word) { return use(0); } -function main() -> word { +function main() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/diagnostics.snap b/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/diagnostics.snap index f7f0385c..66216b0c 100644 --- a/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.solc +input_file: crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol --- error[SC0206]: non-callable value of type word - --> /main/main.solc:3:10 + --> /main/main.sol:3:10 | 2 | let x : word = 1; 3 | return x(); diff --git a/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol b/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol index 0f223160..bb19a5e0 100644 --- a/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol +++ b/crates/uitest/tests/fixtures/solver/noncallable_invokable_constraint/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let x : word = 1; return x(); } diff --git a/crates/uitest/tests/fixtures/solver/patterson_condition/diagnostics.snap b/crates/uitest/tests/fixtures/solver/patterson_condition/diagnostics.snap index a911d31f..ab4862e3 100644 --- a/crates/uitest/tests/fixtures/solver/patterson_condition/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/patterson_condition/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/patterson_condition/main.solc +input_file: crates/uitest/tests/fixtures/solver/patterson_condition/main.sol --- -error[SC0213]: instance `U : C1` does not satisfy the Patterson conditions - --> /main/main.solc:4:35 +error[SC0213]: impl `U: C1` does not satisfy the Patterson conditions + --> /main/main.sol:4:9 | -2 | forall a . class a:C2 {} +2 | trait C2 {} 3 | -4 | forall U . U:C1, U:C2 => instance U:C1 {} - | ^^^^ instance head violates Patterson condition +4 | impl C1 where U: C1, U: C2 {} + | ^^^^^ impl head violates Patterson condition | - = note: each instance context must be structurally smaller than the instance head - = help: remove the recursive context, add a more specific instance, or use the Patterson-condition pragma intentionally + = note: each impl context must be structurally smaller than the impl head + = help: remove the recursive context, add a more specific impl, or use the Patterson-condition pragma intentionally diff --git a/crates/uitest/tests/fixtures/solver/patterson_condition/main.sol b/crates/uitest/tests/fixtures/solver/patterson_condition/main.sol index df603eb1..772f9d7f 100644 --- a/crates/uitest/tests/fixtures/solver/patterson_condition/main.sol +++ b/crates/uitest/tests/fixtures/solver/patterson_condition/main.sol @@ -1,4 +1,4 @@ -forall a . class a:C1 {} -forall a . class a:C2 {} +trait C1 {} +trait C2 {} -forall U . U:C1, U:C2 => instance U:C1 {} +impl C1 where U: C1, U: C2 {} diff --git a/crates/uitest/tests/fixtures/solver/poly_int_defaulting/diagnostics.snap b/crates/uitest/tests/fixtures/solver/poly_int_defaulting/diagnostics.snap index 263334a8..26a0e202 100644 --- a/crates/uitest/tests/fixtures/solver/poly_int_defaulting/diagnostics.snap +++ b/crates/uitest/tests/fixtures/solver/poly_int_defaulting/diagnostics.snap @@ -1,18 +1,18 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.solc +input_file: crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol --- error[SC0299]: ambiguous inferred type - --> /main/main.solc:5:22 + --> /main/main.sol:5:29 | 4 | -5 | function f() -> word { - | ______________________^ +5 | function f() returns (word) { + | _____________________________^ 6 | | let y = poly(7); 7 | | return 0; 8 | | } | |_^ ambiguous inferred type | - = note: forall _ . _ : Int => () -> word - = help: add a type annotation or a matching instance to fix the ambiguous type variable + = note: <_> function() returns (word) where _: Int + = help: add a type annotation or a matching impl to fix the ambiguous type variable diff --git a/crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol b/crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol index 1051a71e..5d1bee2b 100644 --- a/crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol +++ b/crates/uitest/tests/fixtures/solver/poly_int_defaulting/main.sol @@ -1,8 +1,8 @@ -forall a . a:Int => function poly(x:a) -> a { +function poly(x: a) returns (a) where a: Int { return x; } -function f() -> word { +function f() returns (word) { let y = poly(7); return 0; } diff --git a/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/diagnostics.snap index 86ea0dfc..fbe0227c 100644 --- a/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.solc +input_file: crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol --- error[SC0409]: comptime evaluation failed: comptime let 'y' is bound to a runtime expression - --> /main/main.solc:11:5 + --> /main/main.sol:11:5 | -10 | public function main() -> word { -11 | let y : comptime word = sloadWord(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here +10 | function main() public returns (word) { +11 | let y : comptime = sloadWord(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here 12 | return y; | diff --git a/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol b/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol index f3d76258..d705ec2f 100644 --- a/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol +++ b/crates/uitest/tests/fixtures/specialize/comptime_evaluation_failed/main.sol @@ -1,4 +1,4 @@ -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -7,8 +7,8 @@ function sloadWord() -> word { } contract C { - public function main() -> word { - let y : comptime word = sloadWord(); + function main() public returns (word) { + let y : comptime = sloadWord(); return y; } } diff --git a/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/diagnostics.snap index 62e09b7e..a010de32 100644 --- a/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.solc +input_file: crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol --- error[SC0409]: comptime evaluation failed: function annotated '-> comptime' returns a runtime expression - --> /main/main.solc:10:3 + --> /main/main.sol:10:3 | - 9 | function leak(comptime x: word) -> comptime word { + 9 | function leak(comptime x: word) returns (comptime) { 10 | return sloadWord(); | ^^^^^^^^^^^^^^^^^^^ comptime evaluation failed here 11 | } diff --git a/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol b/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol index 0adcb263..a20c08b7 100644 --- a/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol +++ b/crates/uitest/tests/fixtures/specialize/comptime_return_evaluation_failed/main.sol @@ -1,4 +1,4 @@ -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -6,12 +6,12 @@ function sloadWord() -> word { return v; } -function leak(comptime x: word) -> comptime word { +function leak(comptime x: word) returns (comptime) { return sloadWord(); } contract C { - public function main() -> word { + function main() public returns (word) { return leak(1); } } diff --git a/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/diagnostics.snap index ccb5e4be..929e04ba 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.solc +input_file: crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol --- error[SC0413]: public function `double` cannot take comptime parameter `x` - --> /main/main.solc:9:26 + --> /main/main.sol:9:19 | 8 | contract CtPublicParam { - 9 | public function double(comptime x : word) -> word { - | ^^^^^^^^^^^^^^^^^ public entry parameter is runtime + 9 | function double(comptime x: word) public returns (word) { + | ^^^^^^^^^^^^^^^^ public entry parameter is runtime 10 | return x + x; | = note: public function parameters are supplied from calldata at runtime diff --git a/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol b/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol index 0bf6b6ae..a9e931d2 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol +++ b/crates/uitest/tests/fixtures/specialize/ergo_ct_public_param/main.sol @@ -2,11 +2,11 @@ // arguments come from calldata at runtime, so this can never be satisfied. // Should be rejected with a clear "public functions cannot take comptime // parameters" style error. -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract CtPublicParam { - public function double(comptime x : word) -> word { + function double(comptime x: word) public returns (word) { return x + x; } } diff --git a/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/diagnostics.snap index 37ee6ce1..8a075634 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.solc +input_file: crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol --- error[SC0401]: cannot specialize expression: unresolved type parameter in Option(_) - --> /main/main.solc:10:13 + --> /main/main.sol:10:13 | - 9 | function main() -> word { + 9 | function main() returns (word) { 10 | let x = Option.None; | ^^^^^^^^^^^ type must be concrete here 11 | return 1; diff --git a/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol b/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol index cf1e3df1..4fad5d0f 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol +++ b/crates/uitest/tests/fixtures/specialize/ergo_free_tyvar_ctor/main.sol @@ -3,10 +3,10 @@ // points at `None` and names the type variable usefully. import std; -data Option(a) = None | Some(a); +enum Option { None, Some(a) } contract FreeTyVarCtor { - function main() -> word { + function main() returns (word) { let x = Option.None; return 1; } diff --git a/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/diagnostics.snap index 64d7ea5e..dac8087b 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.solc +input_file: crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol --- error[SC0401]: cannot specialize expression: type is not concrete - --> /main/main.solc:15:13 + --> /main/main.sol:15:13 | 14 | let b : Box = Box.MkBox(1); 15 | if (v > 0) { diff --git a/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol b/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol index f23c4beb..ef0eaf15 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol +++ b/crates/uitest/tests/fixtures/specialize/ergo_integer_erasure_branch/main.sol @@ -3,10 +3,10 @@ // Box cannot be erased. Judge cascade volume and span quality. import std; -data Box = MkBox(integer); +enum Box { MkBox(integer) } contract IntegerEscapesBranch { - function main() -> word { + function main() returns (word) { let v : word; assembly { v := sload(0) @@ -15,8 +15,10 @@ contract IntegerEscapesBranch { if (v > 0) { b = Box.MkBox(2); } - match b { - | Box.MkBox(i) => return wordFromInteger(i); - } + match (b) { +case Box.MkBox(i) { +return wordFromInteger(i); +} +} } } diff --git a/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/diagnostics.snap index 2ea6e4b4..2b2ae0e2 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.solc +input_file: crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol --- error[SC0401]: entry point must have a concrete, non-polymorphic type before specialization - --> /main/main.solc:5:1 + --> /main/main.sol:5:1 | 4 | -5 | / forall a . function main(x : a) -> a { +5 | / function main(x: a) returns (a) { 6 | | return x; 7 | | } | |_^ type must be concrete here diff --git a/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol b/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol index 0035c63c..cc064337 100644 --- a/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol +++ b/crates/uitest/tests/fixtures/specialize/ergo_poly_entry/main.sol @@ -2,6 +2,6 @@ // the specialization root (no contract), so ensure_closed fails with // context "entry specialization". Judge the phrasing of that message. -forall a . function main(x : a) -> a { +function main(x: a) returns (a) { return x; } diff --git a/crates/uitest/tests/fixtures/specialize/free_type_variable/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/free_type_variable/diagnostics.snap index 00990fe9..cb45eaad 100644 --- a/crates/uitest/tests/fixtures/specialize/free_type_variable/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/free_type_variable/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/free_type_variable/main.solc +input_file: crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol --- error[SC0401]: cannot specialize expression: type is not concrete - --> /main/main.solc:8:13 + --> /main/main.sol:8:13 | -7 | public function main() -> () { +7 | function main() public { 8 | let x = leak(); | ^^^^^^ type must be concrete here 9 | return (); diff --git a/crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol b/crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol index 7ee19421..45f2b1a1 100644 --- a/crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol +++ b/crates/uitest/tests/fixtures/specialize/free_type_variable/main.sol @@ -1,10 +1,10 @@ -forall a . function leak() -> a { +function leak() returns (a) { let y : a; return y; } contract C { - public function main() -> () { + function main() public { let x = leak(); return (); } diff --git a/crates/uitest/tests/fixtures/specialize/integer_erasure/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/integer_erasure/diagnostics.snap index 6870eb9c..15245fea 100644 --- a/crates/uitest/tests/fixtures/specialize/integer_erasure/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/integer_erasure/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/integer_erasure/main.solc +input_file: crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol --- error[SC0411]: runtime lowering cannot represent `integer` in return type of `main` - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | / public function main() -> integer { +2 | / function main() public returns (integer) { 3 | | return 1; 4 | | } | |___^ not representable at runtime From e12fcd0efb8332231e6f9a74e8a0f66e4025a384 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 099/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures Co-authored-by: Codex --- .../specialize/integer_erasure/main.sol | 2 +- .../diagnostics.snap | 10 +-- .../main.sol | 6 +- .../polyrec_type_size_fuel/diagnostics.snap | 6 +- .../polyrec_type_size_fuel/main.sol | 4 +- .../diagnostics.snap | 18 +++--- .../audit_class_as_type_lowering/main.sol | 6 +- .../audit_ctor_arity_none/diagnostics.snap | 12 ++-- .../typeck/audit_ctor_arity_none/main.sol | 4 +- .../diagnostics.snap | 62 +++++++++---------- .../audit_literal_concrete_matrix/main.sol | 22 +++---- .../audit_literal_vs_opt/diagnostics.snap | 6 +- .../typeck/audit_literal_vs_opt/main.sol | 4 +- .../diagnostics.snap | 30 ++++----- .../audit_obligation_classification/main.sol | 8 +-- .../audit_return_type_name/diagnostics.snap | 6 +- .../typeck/audit_return_type_name/main.sol | 4 +- .../diagnostics.snap | 60 +++++++++--------- .../audit_value_namespace_matrix/main.sol | 30 ++++----- .../audit_value_namespace_matrix/util.sol | 2 +- .../call_arg_defined_here/diagnostics.snap | 12 ++-- .../typeck/call_arg_defined_here/lib.sol | 4 +- .../typeck/call_arg_defined_here/main.sol | 4 +- .../call_arity_defined_here/diagnostics.snap | 12 ++-- .../typeck/call_arity_defined_here/lib.sol | 2 +- .../typeck/call_arity_defined_here/main.sol | 4 +- .../typeck/call_wrong_arity/diagnostics.snap | 10 +-- .../fixtures/typeck/call_wrong_arity/main.sol | 4 +- .../diagnostics.snap | 28 ++++----- .../main.sol | 8 +-- .../diagnostics.snap | 14 ++--- .../main.sol | 8 +-- .../diagnostics.snap | 6 +- .../main.sol | 14 ++--- .../diagnostics.snap | 6 +- .../main.sol | 2 +- .../desugar_origin_spans/diagnostics.snap | 38 ++++++------ .../typeck/desugar_origin_spans/main.sol | 20 +++--- .../diagnostics.snap | 10 +-- .../dispatch_name_collision_full/main.sol | 8 +-- .../diagnostics.snap | 14 +++-- .../duplicate_literal_unreachable/main.sol | 18 ++++-- .../diagnostics.snap | 26 ++++---- .../main.sol | 54 ++++++++++------ .../ergo_arg_type_mismatch/diagnostics.snap | 10 +-- .../typeck/ergo_arg_type_mismatch/main.sol | 6 +- .../ergo_assign_mismatch/diagnostics.snap | 4 +- .../typeck/ergo_assign_mismatch/main.sol | 2 +- .../ergo_call_too_few_args/diagnostics.snap | 10 +-- .../typeck/ergo_call_too_few_args/main.sol | 4 +- .../ergo_call_too_many_args/diagnostics.snap | 10 +-- .../typeck/ergo_call_too_many_args/main.sol | 4 +- .../diagnostics.snap | 10 --- .../ergo_class_head_no_forall/main.solc | 1 - .../ergo_ct_indirect_escape/diagnostics.snap | 16 ++--- .../typeck/ergo_ct_indirect_escape/main.sol | 6 +- .../ergo_ctor_arity_expr/diagnostics.snap | 10 +-- .../typeck/ergo_ctor_arity_expr/main.sol | 4 +- .../ergo_ctor_arity_pattern/diagnostics.snap | 12 ++-- .../typeck/ergo_ctor_arity_pattern/main.sol | 12 ++-- .../diagnostics.snap | 8 +-- .../typeck/ergo_deep_nested_mismatch/main.sol | 4 +- .../diagnostics.snap | 6 +- .../ergo_field_access_non_struct/main.sol | 4 +- .../diagnostics.snap | 14 ++--- .../ergo_forall_tyvar_mismatch/main.sol | 2 +- .../ergo_hull_asm_call_arity/diagnostics.snap | 4 +- .../typeck/ergo_hull_asm_call_arity/main.sol | 2 +- .../diagnostics.snap | 4 +- .../ergo_hull_asm_undefined_var/main.sol | 2 +- .../diagnostics.snap | 15 ----- .../ergo_hull_match_arm_arity/main.solc | 15 ----- .../diagnostics.snap | 10 +-- .../ergo_if_expr_branch_mismatch/main.sol | 4 +- .../diagnostics.snap | 15 ----- .../ergo_incomplete_sig_accepted/main.solc | 9 --- .../diagnostics.snap | 6 +- .../typeck/ergo_lambda_body_mismatch/main.sol | 4 +- .../diagnostics.snap | 20 +++--- .../ergo_match_branch_divergence/main.sol | 2 +- 80 files changed, 434 insertions(+), 465 deletions(-) delete mode 100644 crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/main.solc delete mode 100644 crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/main.solc delete mode 100644 crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/main.solc diff --git a/crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol b/crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol index 09f639c8..74f1f2d9 100644 --- a/crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol +++ b/crates/uitest/tests/fixtures/specialize/integer_erasure/main.sol @@ -1,5 +1,5 @@ contract C { - public function main() -> integer { + function main() public returns (integer) { return 1; } } diff --git a/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/diagnostics.snap index 21245e69..4479d9f7 100644 --- a/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.solc +input_file: crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol --- error[SC0414]: `id` cannot be reduced at compile time: recursive calls form a cycle with no base case (infinite recursion) - --> /main/main.solc:4:48 + --> /main/main.sol:4:55 | -3 | contract Answer { function main() -> word { return id(0); } -4 | public function id(x: word) -> word { return id(x); } - | ^^^^^ recursive call cannot be reduced here +3 | contract Answer { function main() returns (word) { return id(0); } +4 | function id(x: word) public returns (word) { return id(x); } + | ^^^^^ recursive call cannot be reduced here 5 | } | = note: help: add a base case, or guard the recursive call behind a runtime condition so it compiles to a runtime call diff --git a/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol b/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol index e31178f5..41d54c43 100644 --- a/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol +++ b/crates/uitest/tests/fixtures/specialize/non_comptime_unconditional_recursion/main.sol @@ -1,5 +1,5 @@ -function id(x: word) -> word { return x; } +function id(x: word) returns (word) { return x; } -contract Answer { function main() -> word { return id(0); } - public function id(x: word) -> word { return id(x); } +contract Answer { function main() returns (word) { return id(0); } + function id(x: word) public returns (word) { return id(x); } } diff --git a/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/diagnostics.snap b/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/diagnostics.snap index 29b632d4..e42061e8 100644 --- a/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/diagnostics.snap +++ b/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.solc +input_file: crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol --- error[SC0412]: specialization type size exceeded at 4096 type nodes - --> /main/main.solc:2:10 + --> /main/main.sol:2:10 | -1 | forall a . function go(x: a) -> word { +1 | function go(x: a) returns (word) { 2 | return go((x, x)); | ^^^^^^^^^^ specialization type size limit reached here 3 | } diff --git a/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol b/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol index 0b0948e3..eb6e49b3 100644 --- a/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol +++ b/crates/uitest/tests/fixtures/specialize/polyrec_type_size_fuel/main.sol @@ -1,9 +1,9 @@ -forall a . function go(x: a) -> word { +function go(x: a) returns (word) { return go((x, x)); } contract C { - public function main(x: word) -> word { + function main(x: word) public returns (word) { return go(x); } } diff --git a/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/diagnostics.snap index 72c069dc..808d823e 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/diagnostics.snap @@ -1,23 +1,23 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol --- -error[SC0229]: class name used as type: `C` - --> /main/main.solc:4:10 +error[SC0229]: trait name used as type: `C` + --> /main/main.sol:4:10 | -3 | function class_annotation() -> word { +3 | function class_annotation() returns (word) { 4 | let x: C; - | ^ class is not a type + | ^ trait is not a type 5 | return 0; | --- -error[SC0229]: class name used as type: `Int` - --> /main/main.solc:9:10 +error[SC0229]: trait name used as type: `Int` + --> /main/main.sol:9:10 | - 8 | function builtin_class_annotation() -> word { + 8 | function builtin_class_annotation() returns (word) { 9 | let x: Int = 1; - | ^^^ class is not a type + | ^^^ trait is not a type 10 | return x; | diff --git a/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol b/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol index b5373087..bda4ce80 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_class_as_type_lowering/main.sol @@ -1,11 +1,11 @@ -forall a . class a:C {} +trait C {} -function class_annotation() -> word { +function class_annotation() returns (word) { let x: C; return 0; } -function builtin_class_annotation() -> word { +function builtin_class_annotation() returns (word) { let x: Int = 1; return x; } diff --git a/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/diagnostics.snap index d38f72ac..2927f527 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/diagnostics.snap @@ -1,19 +1,19 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol --- error[SC0203]: constructor expects 0 arguments, but 1 was provided - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -1 | data Opt = Some(word) | None; - | ---- `None` defined here +1 | enum Opt { Some(word), None } + | ---- `None` defined here 2 | -3 | function f() -> Opt { +3 | function f() returns (Opt) { 4 | return Opt.None(1); | ^^^^^^^^^^^ wrong number of arguments 5 | } | = note: expected 0 arguments = note: found 1 argument - = note: `None` has signature `None() -> Opt` + = note: `None` has signature `None() returns (Opt)` diff --git a/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol b/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol index a2ed2b1e..43a3ad50 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_ctor_arity_none/main.sol @@ -1,5 +1,5 @@ -data Opt = Some(word) | None; +enum Opt { Some(word), None } -function f() -> Opt { +function f() returns (Opt) { return Opt.None(1); } diff --git a/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/diagnostics.snap index 38ebfe9c..fd37c451 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol --- error[SC0201]: type mismatch: expected numeric, found Opt - --> /main/main.solc:5:10 + --> /main/main.sol:5:10 | -4 | function opt_ret() -> Opt { +4 | function opt_ret() returns (Opt) { 5 | return 1; | ^ expression has mismatched type 6 | } @@ -16,9 +16,9 @@ error[SC0201]: type mismatch: expected numeric, found Opt --- error[SC0201]: type mismatch: expected numeric, found bool - --> /main/main.solc:9:10 + --> /main/main.sol:9:10 | - 8 | function bool_ret() -> bool { + 8 | function bool_ret() returns (bool) { 9 | return 1; | ^ expression has mismatched type 10 | } @@ -28,34 +28,34 @@ error[SC0201]: type mismatch: expected numeric, found bool --- error[SC0103]: undefined type constructor: string - --> /main/main.solc:12:26 + --> /main/main.sol:12:32 | 11 | -12 | function string_ret() -> string { - | ^^^^^^ undefined type constructor +12 | function string_ret() returns (string) { + | ^^^^^^ undefined type constructor 13 | return 1; | --- error[SC0299]: ambiguous inferred type - --> /main/main.solc:12:33 + --> /main/main.sol:12:40 | 11 | -12 | function string_ret() -> string { - | _________________________________^ +12 | function string_ret() returns (string) { + | ________________________________________^ 13 | | return 1; 14 | | } | |_^ ambiguous inferred type 15 | | - = note: forall _ . _ : Int => () -> - = help: add a type annotation or a matching instance to fix the ambiguous type variable + = note: <_> function() returns () where _: Int + = help: add a type annotation or a matching impl to fix the ambiguous type variable --- error[SC0201]: type mismatch: expected numeric, found () - --> /main/main.solc:17:10 + --> /main/main.sol:17:10 | -16 | function unit_ret() -> () { +16 | function unit_ret() { 17 | return 1; | ^ expression has mismatched type 18 | } @@ -65,9 +65,9 @@ error[SC0201]: type mismatch: expected numeric, found () --- error[SC0201]: type mismatch: expected numeric, found K - --> /main/main.solc:21:10 + --> /main/main.sol:21:10 | -20 | function contract_ret() -> K { +20 | function contract_ret() returns (K) { 21 | return 1; | ^ expression has mismatched type 22 | } @@ -76,34 +76,34 @@ error[SC0201]: type mismatch: expected numeric, found K = note: found type: K --- -error[SC0201]: type mismatch: expected numeric, found pair(word, word) - --> /main/main.solc:25:10 +error[SC0201]: type mismatch: expected numeric, found pair + --> /main/main.sol:25:10 | -24 | function pair_ret() -> pair(word, word) { +24 | function pair_ret() returns (pair) { 25 | return 1; | ^ expression has mismatched type 26 | } | = note: expected type: numeric - = note: found type: pair(word, word) + = note: found type: pair --- -error[SC0201]: type mismatch: expected numeric, found sum(word, word) - --> /main/main.solc:29:10 +error[SC0201]: type mismatch: expected numeric, found sum + --> /main/main.sol:29:10 | -28 | function sum_ret() -> sum(word, word) { +28 | function sum_ret() returns (sum) { 29 | return 1; | ^ expression has mismatched type 30 | } | = note: expected type: numeric - = note: found type: sum(word, word) + = note: found type: sum --- error[SC0201]: type mismatch: expected numeric, found (word, word) - --> /main/main.solc:33:10 + --> /main/main.sol:33:10 | -32 | function tuple_ret() -> (word, word) { +32 | function tuple_ret() returns (word, word) { 33 | return 1; | ^ expression has mismatched type 34 | } @@ -112,13 +112,13 @@ error[SC0201]: type mismatch: expected numeric, found (word, word) = note: found type: (word, word) --- -error[SC0201]: type mismatch: expected numeric, found () -> word - --> /main/main.solc:37:10 +error[SC0201]: type mismatch: expected numeric, found function() returns (word) + --> /main/main.sol:37:10 | -36 | function function_ret() -> () -> word { +36 | function function_ret() returns (function() returns (word)) { 37 | return 1; | ^ expression has mismatched type 38 | } | = note: expected type: numeric - = note: found type: () -> word + = note: found type: function() returns (word) diff --git a/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol b/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol index 956ee781..0916de9e 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_literal_concrete_matrix/main.sol @@ -1,38 +1,38 @@ -data Opt = Some(word) | None; -contract K { function main() -> word { return 0; } } +enum Opt { Some(word), None } +contract K { function main() returns (word) { return 0; } } -function opt_ret() -> Opt { +function opt_ret() returns (Opt) { return 1; } -function bool_ret() -> bool { +function bool_ret() returns (bool) { return 1; } -function string_ret() -> string { +function string_ret() returns (string) { return 1; } -function unit_ret() -> () { +function unit_ret() { return 1; } -function contract_ret() -> K { +function contract_ret() returns (K) { return 1; } -function pair_ret() -> pair(word, word) { +function pair_ret() returns (pair) { return 1; } -function sum_ret() -> sum(word, word) { +function sum_ret() returns (sum) { return 1; } -function tuple_ret() -> (word, word) { +function tuple_ret() returns (word, word) { return 1; } -function function_ret() -> () -> word { +function function_ret() returns (function() returns (word)) { return 1; } diff --git a/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/diagnostics.snap index 5264f289..07f3b85e 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol --- error[SC0201]: type mismatch: expected numeric, found Opt - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function f() -> Opt { +3 | function f() returns (Opt) { 4 | return 1; | ^ expression has mismatched type 5 | } diff --git a/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol b/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol index 144221a0..1f6f82e8 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_literal_vs_opt/main.sol @@ -1,5 +1,5 @@ -data Opt = Some(word) | None; +enum Opt { Some(word), None } -function f() -> Opt { +function f() returns (Opt) { return 1; } diff --git a/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/diagnostics.snap index cba4e522..88ff553c 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/diagnostics.snap @@ -1,22 +1,22 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol --- -error[SC0201]: type mismatch: expected numeric, found () -> word - --> /main/main.solc:2:10 +error[SC0201]: type mismatch: expected numeric, found function() returns (word) + --> /main/main.sol:2:10 | -1 | function literal_as_callee() -> word { +1 | function literal_as_callee() returns (word) { 2 | return 1(); | ^ expression has mismatched type 3 | } | = note: expected type: numeric - = note: found type: () -> word + = note: found type: function() returns (word) --- error[SC0206]: non-callable value of type word - --> /main/main.solc:7:10 + --> /main/main.sol:7:10 | 6 | let x: word; 7 | return x(); @@ -26,25 +26,25 @@ error[SC0206]: non-callable value of type word --- error[SC0201]: argument type mismatch in call to `fromInteger` - --> /main/main.solc:11:26 + --> /main/main.sol:11:26 | -10 | function from_integer_bad_arg() -> word { +10 | function from_integer_bad_arg() returns (word) { 11 | return Int.fromInteger(true); | ^^^^ argument has mismatched type 12 | } | = note: expected `integer` because parameter 1 of `fromInteger` has type `integer` = note: found type: bool - = note: `fromInteger` has signature `fromInteger(integer) -> _` + = note: `fromInteger` has signature `fromInteger(integer) returns (_)` --- -error[SC0207]: cannot satisfy class constraint: a : invokable((), word) - --> /main/main.solc:14:8 +error[SC0207]: cannot satisfy trait constraint: a: invokable<(), word> + --> /main/main.sol:14:25 | 13 | -14 | forall a . function open_invokable(x: a) -> word { - | ^ constraint originates here +14 | function open_invokable(x: a) returns (word) { + | ^ constraint originates here 15 | return invoke(x, ()); | - = note: no visible instance matches `a : invokable((), word)` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `a: invokable<(), word>` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol b/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol index 0e19263c..e1282080 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_obligation_classification/main.sol @@ -1,16 +1,16 @@ -function literal_as_callee() -> word { +function literal_as_callee() returns (word) { return 1(); } -function word_as_callee() -> word { +function word_as_callee() returns (word) { let x: word; return x(); } -function from_integer_bad_arg() -> word { +function from_integer_bad_arg() returns (word) { return Int.fromInteger(true); } -forall a . function open_invokable(x: a) -> word { +function open_invokable(x: a) returns (word) { return invoke(x, ()); } diff --git a/crates/uitest/tests/fixtures/typeck/audit_return_type_name/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_return_type_name/diagnostics.snap index 331459d1..685df53f 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_return_type_name/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_return_type_name/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol --- error[SC0228]: type name used as value: `Opt` - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function f() -> Opt { +3 | function f() returns (Opt) { 4 | return Opt; | ^^^ not a value 5 | } diff --git a/crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol b/crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol index 2a916f46..03576ac9 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_return_type_name/main.sol @@ -1,5 +1,5 @@ -data Opt = Some(word) | None; +enum Opt { Some(word), None } -function f() -> Opt { +function f() returns (Opt) { return Opt; } diff --git a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/diagnostics.snap index 95a41815..26102ed0 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.solc +input_file: crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol --- error[SC0228]: type name used as value: `Opt` - --> /main/main.solc:9:10 + --> /main/main.sol:9:10 | - 8 | function adt_value() -> word { + 8 | function adt_value() returns (word) { 9 | return Opt; | ^^^ not a value 10 | } @@ -15,9 +15,9 @@ error[SC0228]: type name used as value: `Opt` --- error[SC0228]: type name used as value: `Alias` - --> /main/main.solc:13:10 + --> /main/main.sol:13:10 | -12 | function alias_value() -> word { +12 | function alias_value() returns (word) { 13 | return Alias; | ^^^^^ not a value 14 | } @@ -26,9 +26,9 @@ error[SC0228]: type name used as value: `Alias` --- error[SC0228]: type name used as value: `K` - --> /main/main.solc:17:10 + --> /main/main.sol:17:10 | -16 | function contract_value() -> word { +16 | function contract_value() returns (word) { 17 | return K; | ^ not a value 18 | } @@ -36,10 +36,10 @@ error[SC0228]: type name used as value: `K` = help: use a constructor or value binding here, not a namespace name --- -error[SC0228]: class name used as value: `C` - --> /main/main.solc:21:10 +error[SC0228]: trait name used as value: `C` + --> /main/main.sol:21:10 | -20 | function class_value() -> word { +20 | function class_value() returns (word) { 21 | return C; | ^ not a value 22 | } @@ -48,9 +48,9 @@ error[SC0228]: class name used as value: `C` --- error[SC0228]: type name used as value: `word` - --> /main/main.solc:25:10 + --> /main/main.sol:25:10 | -24 | function builtin_type_value() -> word { +24 | function builtin_type_value() returns (word) { 25 | return word; | ^^^^ not a value 26 | } @@ -58,10 +58,10 @@ error[SC0228]: type name used as value: `word` = help: use a constructor or value binding here, not a namespace name --- -error[SC0228]: class name used as value: `Int` - --> /main/main.solc:29:10 +error[SC0228]: trait name used as value: `Int` + --> /main/main.sol:29:10 | -28 | function builtin_class_value() -> word { +28 | function builtin_class_value() returns (word) { 29 | return Int; | ^^^ not a value 30 | } @@ -70,9 +70,9 @@ error[SC0228]: class name used as value: `Int` --- error[SC0228]: type variable used as value: `a` - --> /main/main.solc:33:10 + --> /main/main.sol:33:10 | -32 | forall a . function type_var_value() -> word { +32 | function type_var_value() returns (word) { 33 | return a; | ^ not a value 34 | } @@ -81,9 +81,9 @@ error[SC0228]: type variable used as value: `a` --- error[SC0228]: module used as value: `U` - --> /main/main.solc:37:10 + --> /main/main.sol:37:10 | -36 | function module_value() -> word { +36 | function module_value() returns (word) { 37 | return U; | ^ not a value 38 | } @@ -92,9 +92,9 @@ error[SC0228]: module used as value: `U` --- error[SC0228]: type name used as callee: `Opt` - --> /main/main.solc:41:10 + --> /main/main.sol:41:10 | -40 | function type_as_callee() -> word { +40 | function type_as_callee() returns (word) { 41 | return Opt(); | ^^^ not a value 42 | } @@ -103,9 +103,9 @@ error[SC0228]: type name used as callee: `Opt` --- error[SC0228]: module used as callee: `U` - --> /main/main.solc:45:10 + --> /main/main.sol:45:10 | -44 | function module_as_callee() -> word { +44 | function module_as_callee() returns (word) { 45 | return U(); | ^ not a value 46 | } @@ -113,22 +113,22 @@ error[SC0228]: module used as callee: `U` = help: use a constructor or value binding here, not a namespace name --- -error[SC0207]: cannot satisfy class constraint: operator Add.add - --> /main/main.solc:49:10 +error[SC0207]: cannot satisfy trait constraint: operator Add.add + --> /main/main.sol:49:10 | -48 | function type_in_binop() -> word { +48 | function type_in_binop() returns (word) { 49 | return Opt + 1; | ^^^^^^^ constraint originates here 50 | } | - = note: no visible instance matches `operator Add.add` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `operator Add.add` + = help: add a matching impl or strengthen the surrounding type context --- error[SC0228]: type name used as value: `Opt` - --> /main/main.solc:49:10 + --> /main/main.sol:49:10 | -48 | function type_in_binop() -> word { +48 | function type_in_binop() returns (word) { 49 | return Opt + 1; | ^^^ not a value 50 | } diff --git a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol index b9ed700d..a3ac8db1 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/main.sol @@ -1,50 +1,50 @@ -import util as U; +import * as U from util; -data Opt = Some(word) | None; +enum Opt { Some(word), None } type Alias = word; -contract K { function main() -> word { return 0; } } -forall a . class a:C {} +contract K { function main() returns (word) { return 0; } } +trait C {} -function adt_value() -> word { +function adt_value() returns (word) { return Opt; } -function alias_value() -> word { +function alias_value() returns (word) { return Alias; } -function contract_value() -> word { +function contract_value() returns (word) { return K; } -function class_value() -> word { +function class_value() returns (word) { return C; } -function builtin_type_value() -> word { +function builtin_type_value() returns (word) { return word; } -function builtin_class_value() -> word { +function builtin_class_value() returns (word) { return Int; } -forall a . function type_var_value() -> word { +function type_var_value() returns (word) { return a; } -function module_value() -> word { +function module_value() returns (word) { return U; } -function type_as_callee() -> word { +function type_as_callee() returns (word) { return Opt(); } -function module_as_callee() -> word { +function module_as_callee() returns (word) { return U(); } -function type_in_binop() -> word { +function type_in_binop() returns (word) { return Opt + 1; } diff --git a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.sol b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.sol index dd7050c6..763b1212 100644 --- a/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.sol +++ b/crates/uitest/tests/fixtures/typeck/audit_value_namespace_matrix/util.sol @@ -1,3 +1,3 @@ -function g() -> word { +function g() returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/diagnostics.snap index 8c9793a6..bcb9164b 100644 --- a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/diagnostics.snap @@ -1,23 +1,23 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.solc +input_file: crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol --- error[SC0201]: argument type mismatch in call to `paint` - --> /main/main.solc:4:21 + --> /main/main.sol:4:21 | -3 | function go() -> L.Color { +3 | function go() returns (L.Color) { 4 | return L.paint(1, true); | ^^^^ argument has mismatched type 5 | } | - ::: /main/lib.solc:4 + ::: /main/lib.sol:4 | 4 | -5 | function paint(name: word, c: Color) -> Color { +5 | function paint(name: word, c: Color) returns (Color) { | - parameter `c` defined here 6 | return c; | = note: expected `Color` because parameter `c` of `paint` has type `Color` = note: found type: bool - = note: `paint` has signature `paint(name: word, c: Color) -> Color` + = note: `paint` has signature `paint(name: word, c: Color) returns (Color)` diff --git a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.sol b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.sol index 77c0e4e6..7e951062 100644 --- a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.sol +++ b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/lib.sol @@ -1,7 +1,7 @@ export { Color(*), paint }; -data Color = Red | Green; +enum Color { Red, Green } -function paint(name: word, c: Color) -> Color { +function paint(name: word, c: Color) returns (Color) { return c; } diff --git a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol index c229ec8a..89ebf496 100644 --- a/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol +++ b/crates/uitest/tests/fixtures/typeck/call_arg_defined_here/main.sol @@ -1,5 +1,5 @@ -import lib as L; +import * as L from lib; -function go() -> L.Color { +function go() returns (L.Color) { return L.paint(1, true); } diff --git a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/diagnostics.snap index fd3c113e..f7300c2d 100644 --- a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/diagnostics.snap @@ -1,23 +1,23 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.solc +input_file: crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol --- error[SC0203]: call expects 1 argument, but 0 were provided - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function go() -> word { +3 | function go() returns (word) { 4 | return L.id(); | ^^^^^^ wrong number of arguments 5 | } | - ::: /main/lib.solc:2 + ::: /main/lib.sol:2 | 2 | -3 | function id(x: word) -> word { +3 | function id(x: word) returns (word) { | -- `id` defined here 4 | return x; | = note: expected 1 argument = note: found 0 arguments - = note: `id` has signature `id(x: word) -> word` + = note: `id` has signature `id(x: word) returns (word)` diff --git a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.sol b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.sol index 052e7b55..28a558b3 100644 --- a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.sol +++ b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/lib.sol @@ -1,5 +1,5 @@ export { id }; -function id(x: word) -> word { +function id(x: word) returns (word) { return x; } diff --git a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol index 8db73d4b..208079b6 100644 --- a/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol +++ b/crates/uitest/tests/fixtures/typeck/call_arity_defined_here/main.sol @@ -1,5 +1,5 @@ -import lib as L; +import * as L from lib; -function go() -> word { +function go() returns (word) { return L.id(); } diff --git a/crates/uitest/tests/fixtures/typeck/call_wrong_arity/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/call_wrong_arity/diagnostics.snap index b5a40312..1a3aeb2c 100644 --- a/crates/uitest/tests/fixtures/typeck/call_wrong_arity/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/call_wrong_arity/diagnostics.snap @@ -1,21 +1,21 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.solc +input_file: crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol --- error[SC0203]: call expects 1 argument, but 0 were provided - --> /main/main.solc:6:10 + --> /main/main.sol:6:10 | -1 | function f(x: word) -> word { +1 | function f(x: word) returns (word) { | - `f` defined here 2 | return x; 3 | } 4 | -5 | function g() -> word { +5 | function g() returns (word) { 6 | return f(); | ^^^ wrong number of arguments 7 | } | = note: expected 1 argument = note: found 0 arguments - = note: `f` has signature `f(x: word) -> word` + = note: `f` has signature `f(x: word) returns (word)` diff --git a/crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol b/crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol index 2d86a90a..a257e1c5 100644 --- a/crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol +++ b/crates/uitest/tests/fixtures/typeck/call_wrong_arity/main.sol @@ -1,7 +1,7 @@ -function f(x: word) -> word { +function f(x: word) returns (word) { return x; } -function g() -> word { +function g() returns (word) { return f(); } diff --git a/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/diagnostics.snap index 8ba01b50..80993b22 100644 --- a/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/diagnostics.snap @@ -1,35 +1,35 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.solc +input_file: crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol --- -error[SC0207]: cannot satisfy class constraint: Contract(Method(DispatchNameTy_C_roundtrip, NonPayable, memory(Point), word, (memory(Point)) -> word), Fallback(NonPayable, (), (), () -> ())) : RunContract - --> /main/main.solc:6:10 +error[SC0207]: cannot satisfy trait constraint: Contract, word, function(memory) returns (word)>, Fallback>: RunContract + --> /main/main.sol:6:10 | 5 | 6 | contract C { | ^ constraint originates here -7 | public function roundtrip(value: memory(Point)) -> word { return 0; } +7 | function roundtrip(value: memory) public returns (word) { return 0; } | - = note: no visible instance matches `Contract(Method(DispatchNameTy_C_roundtrip, NonPayable, memory(Point), word, (memory(Point)) -> word), Fallback(NonPayable, (), (), () -> ())) : RunContract` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `Contract, word, function(memory) returns (word)>, Fallback>: RunContract` + = help: add a matching impl or strengthen the surrounding type context --- -error[SC0231]: ABI parameter cannot be represented in the ABI: adt:Point (only memory(string) and memory(bytes) have canonical ABI evidence) - --> /main/main.solc:7:3 +error[SC0231]: ABI parameter cannot be represented in the ABI: adt:Point (only memory and memory have canonical ABI evidence) + --> /main/main.sol:7:3 | 6 | contract C { -7 | public function roundtrip(value: memory(Point)) -> word { return 0; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +7 | function roundtrip(value: memory) public returns (word) { return 0; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 8 | } | --- -error[SC0231]: roundtrip cannot be represented in the ABI: adt:Point (only memory(string) and memory(bytes) have canonical ABI evidence) - --> /main/main.solc:7:3 +error[SC0231]: roundtrip cannot be represented in the ABI: adt:Point (only memory and memory have canonical ABI evidence) + --> /main/main.sol:7:3 | 6 | contract C { -7 | public function roundtrip(value: memory(Point)) -> word { return 0; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +7 | function roundtrip(value: memory) public returns (word) { return 0; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 8 | } | diff --git a/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol b/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol index 2b24766d..47278d9c 100644 --- a/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol +++ b/crates/uitest/tests/fixtures/typeck/canonical_location_wrapper_user_adt_payload/main.sol @@ -1,8 +1,8 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data Point = Point(word, bool); +enum Point { Point(word, bool) } contract C { - public function roundtrip(value: memory(Point)) -> word { return 0; } + function roundtrip(value: memory) public returns (word) { return 0; } } diff --git a/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/diagnostics.snap index 2fda645f..e20822ff 100644 --- a/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.solc +input_file: crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol --- -error[SC0221]: invalid instance member signature for `f`: expected (word) -> word, got (word) -> bool - --> /main/main.solc:6:3 +error[SC0221]: invalid impl member signature for `f`: expected function(word) returns (word), got function(word) returns (bool) + --> /main/main.sol:6:3 | -5 | instance word : C { -6 | function f(x : word) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid instance method signature +5 | impl C { +6 | function f(x: word) returns (bool) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid impl method signature 7 | return true; | - = note: the instance method must match the class method after substituting the instance head + = note: the impl method must match the trait method after substituting the impl head diff --git a/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol b/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol index 03d5bb0d..6257f5e6 100644 --- a/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol +++ b/crates/uitest/tests/fixtures/typeck/comptime_class_head_method_signature/main.sol @@ -1,9 +1,9 @@ -forall a. class comptime a : C { - function f(x : a) -> a; +trait C { + function f(x: a) returns (a) ; } -instance word : C { - function f(x : word) -> bool { +impl C { + function f(x: word) returns (bool) { return true; } } diff --git a/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/diagnostics.snap index 7f3450cf..1fe61711 100644 --- a/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.solc +input_file: crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol --- error[SC0240]: runtime value passed to comptime parameter 'x' of 'Wrap.unwrap' - --> /main/main.solc:25:20 + --> /main/main.sol:25:20 | -24 | public function main() -> word { +24 | function main() public returns (word) { 25 | return process(sloadWord()); | ^^^^^^^^^^^ runtime value passed here 26 | } diff --git a/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol b/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol index 0bb3931b..935d46c4 100644 --- a/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol +++ b/crates/uitest/tests/fixtures/typeck/comptime_class_method_runtime_arg/main.sol @@ -1,18 +1,18 @@ -forall t. class t : Wrap { - function unwrap(comptime x : t) -> comptime word; +trait Wrap { + function unwrap(comptime x: t) returns (comptime) ; } -instance word : Wrap { - function unwrap(comptime x : word) -> comptime word { +impl Wrap { + function unwrap(comptime x: word) returns (comptime) { return x; } } -forall t. t:Wrap => function process(z : t) -> word { +function process(z: t) returns (word) where t: Wrap { return Wrap.unwrap(z); } -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -21,7 +21,7 @@ function sloadWord() -> word { } contract C { - public function main() -> word { + function main() public returns (word) { return process(sloadWord()); } } diff --git a/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/diagnostics.snap index 8e29e97d..7e961b14 100644 --- a/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:2:13 + --> /main/main.sol:2:13 | 1 | contract C { 2 | x: word = true; | ^^^^ expression has mismatched type -3 | function main() -> () { return (); } +3 | function main() { return (); } | = note: expected type: word = note: found type: bool diff --git a/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol index f8d6ebdc..790f3163 100644 --- a/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/contract_field_initializer_mismatch/main.sol @@ -1,4 +1,4 @@ contract C { x: word = true; - function main() -> () { return (); } + function main() { return (); } } diff --git a/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/diagnostics.snap index 9cc5ae10..ba7c327c 100644 --- a/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.solc +input_file: crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:2:29 + --> /main/main.sol:2:26 | -1 | contract C { function main() -> word { return 0; } -2 | seed: word = if true then false else 1; - | ^^^^^ expression has mismatched type +1 | contract C { function main() returns (word) { return 0; } +2 | seed: word = true ? false : 1; + | ^^^^^ expression has mismatched type 3 | } | = note: expected type: word @@ -16,36 +16,36 @@ error[SC0201]: type mismatch: expected word, found bool --- error[SC0203]: tuple pattern expects 2 arguments, but 3 were provided - --> /main/main.solc:7:5 + --> /main/main.sol:7:6 | -6 | match p { -7 | | (a, b, c) => return a; - | ^^^^^^^^^ wrong number of arguments -8 | } +6 | match (p) { +7 | case (a, b, c) { + | ^^^^^^^^^ wrong number of arguments +8 | return a; | = note: expected 2 arguments = note: found 3 arguments --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:12:27 + --> /main/main.sol:14:23 | -11 | function if_source(b: bool) -> word { -12 | return if b then 1 else false; - | ^^^^^ expression has mismatched type -13 | } +13 | function if_source(b: bool) returns (word) { +14 | return b ? 1 : false; + | ^^^^^ expression has mismatched type +15 | } | = note: expected type: word = note: found type: bool --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:16:10 + --> /main/main.sol:18:10 | -15 | function bool_source() -> word { -16 | return true; +17 | function bool_source() returns (word) { +18 | return true; | ^^^^ expression has mismatched type -17 | } +19 | } | = note: expected type: word = note: found type: bool diff --git a/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol b/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol index 55fbacc7..32b742ca 100644 --- a/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol +++ b/crates/uitest/tests/fixtures/typeck/desugar_origin_spans/main.sol @@ -1,17 +1,19 @@ -contract C { function main() -> word { return 0; } - seed: word = if true then false else 1; +contract C { function main() returns (word) { return 0; } + seed: word = true ? false : 1; } -function pat_source(p: (word, word)) -> word { - match p { - | (a, b, c) => return a; - } +function pat_source(p: (word, word)) returns (word) { + match (p) { +case (a, b, c) { +return a; +} +} } -function if_source(b: bool) -> word { - return if b then 1 else false; +function if_source(b: bool) returns (word) { + return b ? 1 : false; } -function bool_source() -> word { +function bool_source() returns (word) { return true; } diff --git a/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/diagnostics.snap index 14ab52e4..39b808d1 100644 --- a/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/diagnostics.snap @@ -1,18 +1,18 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.solc +input_file: crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol --- error[SC0229]: duplicate type definition: DispatchNameTy_C_ping - --> /main/main.solc:4:6 + --> /main/main.sol:4:6 | 3 | -4 | data DispatchNameTy_C_ping = Collision; +4 | enum DispatchNameTy_C_ping { Collision } | ^^^^^^^^^^^^^^^^^^^^^ duplicate type 5 | 6 | contract C { -7 | public function ping() -> uint256 { - | ---- existing definition +7 | function ping() public returns (uint256) { + | ---- existing definition 8 | return uint256(0); | = note: rename or remove the duplicate type definition diff --git a/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol b/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol index 97da477d..075c36f9 100644 --- a/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol +++ b/crates/uitest/tests/fixtures/typeck/dispatch_name_collision_full/main.sol @@ -1,10 +1,10 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -data DispatchNameTy_C_ping = Collision; +enum DispatchNameTy_C_ping { Collision } contract C { - public function ping() -> uint256 { + function ping() public returns (uint256) { return uint256(0); } } diff --git a/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/diagnostics.snap index 8c6f8b5c..7afc005b 100644 --- a/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/diagnostics.snap @@ -1,14 +1,16 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.solc +input_file: crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol --- warning[SC0303]: unreachable match arm - --> /main/main.solc:4:3 + --> /main/main.sol:6:1 | -3 | | 0 => return 0; -4 | | 0 => return 1; - | ^^^^^^^^^^^^^^^^ this arm is unreachable -5 | | _ => return 2; +5 | } +6 | / case 0 { +7 | | return 1; +8 | | } + | |_^ this arm is unreachable +9 | default { | = note: this arm is covered by previous match arms diff --git a/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol b/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol index 25ac1933..52700733 100644 --- a/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol +++ b/crates/uitest/tests/fixtures/typeck/duplicate_literal_unreachable/main.sol @@ -1,7 +1,13 @@ -function pick(x : word) -> word { - match x { - | 0 => return 0; - | 0 => return 1; - | _ => return 2; - } +function pick(x: word) returns (word) { + match (x) { +case 0 { +return 0; +} +case 0 { +return 1; +} +default { +return 2; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/diagnostics.snap index 9cf7654b..219137ca 100644 --- a/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/diagnostics.snap @@ -1,25 +1,29 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.solc +input_file: crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol --- warning[SC0303]: unreachable match arm - --> /main/main.solc:4:3 + --> /main/main.sol:6:1 | -3 | | 0x0A => return 0; -4 | | 10 => return 1; - | ^^^^^^^^^^^^^^^^^ this arm is unreachable -5 | | _ => return 2; +5 | } +6 | / case 10 { +7 | | return 1; +8 | | } + | |_^ this arm is unreachable +9 | default { | = note: this arm is covered by previous match arms --- warning[SC0303]: unreachable match arm - --> /main/main.solc:12:3 + --> /main/main.sol:20:1 | -11 | | 0 => return 0; -12 | | 115792089237316195423570985008687907853269984665640564039457584007913129639936 => return 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this arm is unreachable -13 | | _ => return 2; +19 | } +20 | / case 115792089237316195423570985008687907853269984665640564039457584007913129639936 { +21 | | return 1; +22 | | } + | |_^ this arm is unreachable +23 | default { | = note: this arm is covered by previous match arms diff --git a/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol b/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol index 008e89bb..2d481932 100644 --- a/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol +++ b/crates/uitest/tests/fixtures/typeck/equivalent_numeric_literal_unreachable/main.sol @@ -1,23 +1,41 @@ -function pick(x : word) -> word { - match x { - | 0x0A => return 0; - | 10 => return 1; - | _ => return 2; - } +function pick(x: word) returns (word) { + match (x) { +case 0x0A { +return 0; +} +case 10 { +return 1; +} +default { +return 2; +} +} } -function wrapped(x : word) -> word { - match x { - | 0 => return 0; - | 115792089237316195423570985008687907853269984665640564039457584007913129639936 => return 1; - | _ => return 2; - } +function wrapped(x: word) returns (word) { + match (x) { +case 0 { +return 0; +} +case 115792089237316195423570985008687907853269984665640564039457584007913129639936 { +return 1; +} +default { +return 2; +} +} } -function exact(x : integer) -> word { - match x { - | 0 => return 0; - | 115792089237316195423570985008687907853269984665640564039457584007913129639936 => return 1; - | _ => return 2; - } +function exact(x: integer) returns (word) { + match (x) { +case 0 { +return 0; +} +case 115792089237316195423570985008687907853269984665640564039457584007913129639936 { +return 1; +} +default { +return 2; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/diagnostics.snap index 06f241ff..b39584c3 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/diagnostics.snap @@ -1,21 +1,21 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol --- error[SC0201]: argument type mismatch in call to `paint` - --> /main/main.solc:8:19 + --> /main/main.sol:8:19 | 2 | -3 | function paint(name: word, c: Color) -> Color { +3 | function paint(name: word, c: Color) returns (Color) { | - parameter `c` defined here 4 | return c; ... -7 | function go() -> Color { +7 | function go() returns (Color) { 8 | return paint(1, true); | ^^^^ argument has mismatched type 9 | } | = note: expected `Color` because parameter `c` of `paint` has type `Color` = note: found type: bool - = note: `paint` has signature `paint(name: word, c: Color) -> Color` + = note: `paint` has signature `paint(name: word, c: Color) returns (Color)` diff --git a/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol index 3b6f6aa1..289fb05a 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_arg_type_mismatch/main.sol @@ -1,9 +1,9 @@ -data Color = Red | Green; +enum Color { Red, Green } -function paint(name: word, c: Color) -> Color { +function paint(name: word, c: Color) returns (Color) { return c; } -function go() -> Color { +function go() returns (Color) { return paint(1, true); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/diagnostics.snap index 86ab1212..3a1b4a08 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:3:7 + --> /main/main.sol:3:7 | 2 | let x : word = 1; 3 | x = true; diff --git a/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol index 640b0e9e..2e3ed65c 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_assign_mismatch/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let x : word = 1; x = true; return x; diff --git a/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/diagnostics.snap index a88c92ef..feceab3e 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/diagnostics.snap @@ -1,21 +1,21 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol --- error[SC0203]: call expects 3 arguments, but 1 was provided - --> /main/main.solc:6:10 + --> /main/main.sol:6:10 | -1 | function clamp(lo: word, hi: word, v: word) -> word { +1 | function clamp(lo: word, hi: word, v: word) returns (word) { | ----- `clamp` defined here 2 | return v; 3 | } 4 | -5 | function g() -> word { +5 | function g() returns (word) { 6 | return clamp(1); | ^^^^^^^^ wrong number of arguments 7 | } | = note: expected 3 arguments = note: found 1 argument - = note: `clamp` has signature `clamp(lo: word, hi: word, v: word) -> word` + = note: `clamp` has signature `clamp(lo: word, hi: word, v: word) returns (word)` diff --git a/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol index 4ac82b3b..d26bc65d 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_call_too_few_args/main.sol @@ -1,7 +1,7 @@ -function clamp(lo: word, hi: word, v: word) -> word { +function clamp(lo: word, hi: word, v: word) returns (word) { return v; } -function g() -> word { +function g() returns (word) { return clamp(1); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/diagnostics.snap index 1901e7a9..cb9d79e5 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/diagnostics.snap @@ -1,21 +1,21 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol --- error[SC0203]: call expects 1 argument, but 3 were provided - --> /main/main.solc:6:10 + --> /main/main.sol:6:10 | -1 | function double(x: word) -> word { +1 | function double(x: word) returns (word) { | ------ `double` defined here 2 | return x; 3 | } 4 | -5 | function g() -> word { +5 | function g() returns (word) { 6 | return double(1, 2, 3); | ^^^^^^^^^^^^^^^ wrong number of arguments 7 | } | = note: expected 1 argument = note: found 3 arguments - = note: `double` has signature `double(x: word) -> word` + = note: `double` has signature `double(x: word) returns (word)` diff --git a/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol index a11a51e8..f4933dc5 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_call_too_many_args/main.sol @@ -1,7 +1,7 @@ -function double(x: word) -> word { +function double(x: word) returns (word) { return x; } -function g() -> word { +function g() returns (word) { return double(1, 2, 3); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/diagnostics.snap deleted file mode 100644 index 2c2ec171..00000000 --- a/crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/diagnostics.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/main.solc ---- -error[SC0102]: undefined type variables: a - --> /main/main.solc:1:7 - | -1 | class a : C {} - | ^ undefined type variable diff --git a/crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/main.solc deleted file mode 100644 index aa10816a..00000000 --- a/crates/uitest/tests/fixtures/typeck/ergo_class_head_no_forall/main.solc +++ /dev/null @@ -1 +0,0 @@ -class a : C {} diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/diagnostics.snap index 7d1c42e6..c382faba 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/diagnostics.snap @@ -1,24 +1,24 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol --- -error[SC0207]: cannot satisfy class constraint: operator Add.add - --> /main/main.solc:17:12 +error[SC0207]: cannot satisfy trait constraint: operator Add.add + --> /main/main.sol:17:12 | -16 | function double(comptime x : word) -> comptime word { +16 | function double(comptime x: word) returns (comptime) { 17 | return x + x; | ^^^^^ constraint originates here 18 | } | - = note: no visible instance matches `operator Add.add` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `operator Add.add` + = help: add a matching impl or strengthen the surrounding type context --- error[SC0240]: runtime value passed to comptime parameter 'x' of 'double' - --> /main/main.solc:20:44 + --> /main/main.sol:20:44 | -19 | function main() -> word { +19 | function main() returns (word) { 20 | let g = lam (y : word) { return double(y); }; | ^ runtime value passed here 21 | return g(sloadWord()); diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol index 1dd4c171..79097b57 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_ct_indirect_escape/main.sol @@ -4,7 +4,7 @@ // calls, this silently defeats the comptime contract (accept-bug). import std; -function sloadWord() -> word { +function sloadWord() returns (word) { let v : word; assembly { v := sload(0) @@ -13,10 +13,10 @@ function sloadWord() -> word { } contract CtIndirectEscape { - function double(comptime x : word) -> comptime word { + function double(comptime x: word) returns (comptime) { return x + x; } - function main() -> word { + function main() returns (word) { let g = lam (y : word) { return double(y); }; return g(sloadWord()); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/diagnostics.snap index 43b6d91d..cb87aacb 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/diagnostics.snap @@ -1,19 +1,19 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol --- error[SC0203]: constructor expects 2 arguments, but 1 was provided - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -1 | data Pair(a, b) = Mk(a, b); +1 | enum Pair { Mk(a, b) } | -- `Mk` defined here 2 | -3 | function f() -> Pair(word, word) { +3 | function f() returns (Pair) { 4 | return Pair.Mk(1); | ^^^^^^^^^^ wrong number of arguments 5 | } | = note: expected 2 arguments = note: found 1 argument - = note: `Mk` has signature `Mk(a, b) -> Pair(a, b)` + = note: `Mk` has signature `Mk(a, b) returns (Pair)` diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol index ff1ed568..1c00e4fe 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_expr/main.sol @@ -1,5 +1,5 @@ -data Pair(a, b) = Mk(a, b); +enum Pair { Mk(a, b) } -function f() -> Pair(word, word) { +function f() returns (Pair) { return Pair.Mk(1); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/diagnostics.snap index 6b5ca58f..7c8baf09 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol --- error[SC0203]: constructor pattern expects 2 arguments, but 1 was provided - --> /main/main.solc:5:5 + --> /main/main.sol:5:6 | -4 | match p { -5 | | Pair.Mk(x) => return x; - | ^^^^^^^^^^ wrong number of arguments -6 | } +4 | match (p) { +5 | case Pair.Mk(x) { + | ^^^^^^^^^^ wrong number of arguments +6 | return x; | = note: expected 2 arguments = note: found 1 argument diff --git a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol index de09ff0e..209f37ba 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_ctor_arity_pattern/main.sol @@ -1,7 +1,9 @@ -data Pair(a, b) = Mk(a, b); +enum Pair { Mk(a, b) } -function f(p: Pair(word, word)) -> word { - match p { - | Pair.Mk(x) => return x; - } +function f(p: Pair) returns (word) { + match (p) { +case Pair.Mk(x) { +return x; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/diagnostics.snap index dd4588d9..2f88dab2 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol --- error[SC0201]: argument type mismatch in call to `add3` - --> /main/main.solc:7:34 + --> /main/main.sol:7:34 | -1 | function add3(a: word, b: word, c: word) -> word { +1 | function add3(a: word, b: word, c: word) returns (word) { | - parameter `b` defined here 2 | return a; 3 | } @@ -18,4 +18,4 @@ error[SC0201]: argument type mismatch in call to `add3` | = note: expected `word` because parameter `b` of `add3` has type `word` = note: found type: bool - = note: `add3` has signature `add3(a: word, b: word, c: word) -> word` + = note: `add3` has signature `add3(a: word, b: word, c: word) returns (word)` diff --git a/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol index 217dee14..0e503f28 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_deep_nested_mismatch/main.sol @@ -1,8 +1,8 @@ -function add3(a: word, b: word, c: word) -> word { +function add3(a: word, b: word, c: word) returns (word) { return a; } -function f(x: word) -> word { +function f(x: word) returns (word) { return add3(add3(x, x, add3(x, add3(x, x, x), x)), add3(x, x, add3(x, true, x)), x); diff --git a/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/diagnostics.snap index 0cff5b05..79d04538 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol --- error[SC0205]: cannot resolve field `red` - --> /main/main.solc:4:12 + --> /main/main.sol:4:12 | -3 | function f(c: Color) -> word { +3 | function f(c: Color) returns (word) { 4 | return c.red; | ^^^ unknown field 5 | } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol index 04fe2b4c..3eabe9bf 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_field_access_non_struct/main.sol @@ -1,5 +1,5 @@ -data Color = Red | Green; +enum Color { Red, Green } -function f(c: Color) -> word { +function f(c: Color) returns (word) { return c.red; } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/diagnostics.snap index f4e129dc..ed455949 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol --- -error[SC0207]: cannot satisfy class constraint: a : Int - --> /main/main.solc:1:8 +error[SC0207]: cannot satisfy trait constraint: a: Int + --> /main/main.sol:1:16 | -1 | forall a . function ident(x: a) -> a { - | ^ constraint originates here +1 | function ident(x: a) returns (a) { + | ^ constraint originates here 2 | return 1; 3 | } | - = note: no visible instance matches `a : Int` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `a: Int` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol index 56faa7a1..0e598ee8 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_forall_tyvar_mismatch/main.sol @@ -1,3 +1,3 @@ -forall a . function ident(x: a) -> a { +function ident(x: a) returns (a) { return 1; } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/diagnostics.snap index 7ab227ac..5a285596 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol --- error[SC0203]: Yul call `dbl` expects 1 argument, but 2 were provided - --> /main/main.solc:8:12 + --> /main/main.sol:8:12 | 7 | } 8 | x := dbl(1, 2) diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol index 0c657464..76d13330 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_call_arity/main.sol @@ -1,5 +1,5 @@ contract C { - public function main() -> word { + function main() public returns (word) { let x : word; assembly { function dbl(a) -> r { diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/diagnostics.snap index 0caaef49..28802d6a 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol --- error[SC0211]: unknown Yul identifier or function: someUndefinedThing - --> /main/main.solc:5:12 + --> /main/main.sol:5:12 | 4 | assembly { 5 | x := someUndefinedThing diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol index 91140972..78a0c8e4 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_hull_asm_undefined_var/main.sol @@ -1,5 +1,5 @@ contract C { - public function main() -> word { + function main() public returns (word) { let x : word; assembly { x := someUndefinedThing diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/diagnostics.snap deleted file mode 100644 index 107d5b01..00000000 --- a/crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/diagnostics.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/main.solc ---- -error[SC0203]: match arm expects 2 arguments, but 1 was provided - --> /main/main.solc:5:3 - | -4 | match x, y { -5 | | Nat.Zero => return 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ wrong number of arguments -6 | | Nat.Succ(a), Nat.Zero => return 1; - | - = note: expected 2 arguments - = note: found 1 argument diff --git a/crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/main.solc deleted file mode 100644 index e9a677dd..00000000 --- a/crates/uitest/tests/fixtures/typeck/ergo_hull_match_arm_arity/main.solc +++ /dev/null @@ -1,15 +0,0 @@ -data Nat = Zero | Succ(Nat); - -function pick(x : Nat, y : Nat) -> word { - match x, y { - | Nat.Zero => return 0; - | Nat.Succ(a), Nat.Zero => return 1; - | Nat.Succ(a), Nat.Succ(b) => return 2; - } -} - -contract T { - public function main() -> word { - return pick(Nat.Zero, Nat.Zero); - } -} diff --git a/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/diagnostics.snap index 782592ec..6be87762 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol --- error[SC0201]: type mismatch: expected numeric, found bool - --> /main/main.solc:2:28 + --> /main/main.sol:2:24 | -1 | function f(b: bool) -> word { -2 | let x = if b then 1 else false; - | ^^^^^ expression has mismatched type +1 | function f(b: bool) returns (word) { +2 | let x = b ? 1 : false; + | ^^^^^ expression has mismatched type 3 | return x; | = note: expected type: numeric diff --git a/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol index 5fd1191f..06bd57b3 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_if_expr_branch_mismatch/main.sol @@ -1,4 +1,4 @@ -function f(b: bool) -> word { - let x = if b then 1 else false; +function f(b: bool) returns (word) { + let x = b ? 1 : false; return x; } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/diagnostics.snap deleted file mode 100644 index d52f7162..00000000 --- a/crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/diagnostics.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/main.solc ---- -error[SC0220]: top-level function must have complete type annotations - --> /main/main.solc:2:19 - | -1 | contract C { -2 | public function id(x) { - | ^^ incomplete signature -3 | return x; - | - = note: signature: public function id(x) - = note: annotate every parameter (name : Type) and provide a return type (-> Type) diff --git a/crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/main.solc b/crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/main.solc deleted file mode 100644 index f1ea7766..00000000 --- a/crates/uitest/tests/fixtures/typeck/ergo_incomplete_sig_accepted/main.solc +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - public function id(x) { - return x; - } - - function main() -> word { - return 0; - } -} diff --git a/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/diagnostics.snap index 4c709be6..5ddbaac9 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:6:39 + --> /main/main.sol:6:39 | -5 | function g() -> word { +5 | function g() returns (word) { 6 | return apply(lam (y: word) { return true; }, 1); | ^^^^ expression has mismatched type 7 | } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol index 9f2c770f..54943cdf 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_lambda_body_mismatch/main.sol @@ -1,7 +1,7 @@ -function apply(f: (word) -> word, x: word) -> word { +function apply(f: function(word) returns (word), x: word) returns (word) { return f(x); } -function g() -> word { +function g() returns (word) { return apply(lam (y: word) { return true; }, 1); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/diagnostics.snap index a09c33ba..d9195fe7 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:6:31 - | -5 | | Shape.Circle(r) => return r; -6 | | Shape.Square(w) => return true; - | ^^^^ expression has mismatched type -7 | } - | - = note: expected type: word - = note: found type: bool + --> /main/main.sol:9:8 + | + 8 | case Shape.Square(w) { + 9 | return true; + | ^^^^ expression has mismatched type +10 | } + | + = note: expected type: word + = note: found type: bool diff --git a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol index 51ec788b..2c8ed65a 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol @@ -1,4 +1,4 @@ -data Shape = Circle(word) | Square(word); +enum Shape { Circle(word), Square(word) } function area(s: Shape) -> word { match s { From 3d0f296a02cc7130703b6f999de73c593affa806 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 100/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures Co-authored-by: Codex --- .../ergo_match_branch_divergence/main.sol | 14 +-- .../diagnostics.snap | 14 +-- .../ergo_multi_independent_errors/main.sol | 6 +- .../ergo_occurs_lambda_msg/diagnostics.snap | 6 +- .../typeck/ergo_occurs_lambda_msg/main.sol | 2 +- .../ergo_pattern_wrong_type/diagnostics.snap | 12 +-- .../typeck/ergo_pattern_wrong_type/main.sol | 14 +-- .../ergo_recovery_no_cascade/diagnostics.snap | 38 ++++---- .../typeck/ergo_recovery_no_cascade/main.sol | 14 +-- .../diagnostics.snap | 6 +- .../ergo_return_type_mismatch_data/main.sol | 4 +- .../diagnostics.snap | 6 +- .../typeck/ergo_tuple_arity_mismatch/main.sol | 2 +- .../ergo_type_as_value/diagnostics.snap | 6 +- .../typeck/ergo_type_as_value/main.sol | 4 +- .../final_if_branch_mismatch/diagnostics.snap | 10 +-- .../typeck/final_if_branch_mismatch/main.sol | 4 +- .../diagnostics.snap | 90 +++++++++---------- .../main.sol | 2 +- .../inferred_poly_compose/diagnostics.snap | 15 ---- .../typeck/inferred_poly_compose/main.solc | 16 ---- .../let_unannotated_literal/diagnostics.snap | 12 +-- .../typeck/let_unannotated_literal/main.sol | 2 +- .../diagnostics.snap | 30 +++---- .../manual_generic_adt_external_abi/main.sol | 8 +- .../match_branch_mismatch/diagnostics.snap | 12 +-- .../typeck/match_branch_mismatch/main.sol | 14 +-- .../diagnostics.snap | 12 +-- .../typeck/missing_word_abi_evidence/main.sol | 6 +- .../mutual_recursive_data/diagnostics.snap | 8 +- .../typeck/mutual_recursive_data/main.sol | 6 +- .../diagnostics.snap | 12 +-- .../nested_constructor_nonexhaustive/main.sol | 18 ++-- .../diagnostics.snap | 20 +++-- .../nested_constructor_unreachable/main.sol | 22 +++-- .../nonexhaustive_contract/diagnostics.snap | 12 +-- .../typeck/nonexhaustive_contract/main.sol | 14 +-- .../nonexhaustive_free_fn/diagnostics.snap | 12 +-- .../typeck/nonexhaustive_free_fn/main.sol | 12 +-- .../typeck/nonfinal_return/diagnostics.snap | 6 +- .../fixtures/typeck/nonfinal_return/main.sol | 2 +- .../nullary_type_applied_let/diagnostics.snap | 10 +-- .../typeck/nullary_type_applied_let/main.sol | 6 +- .../diagnostics.snap | 8 +- .../nullary_type_applied_signature/main.sol | 4 +- .../typeck/occurs_check/diagnostics.snap | 8 +- .../fixtures/typeck/occurs_check/main.sol | 2 +- .../diagnostics.snap | 6 ++ .../typeck/ok_enum_without_semicolon/main.sol | 1 + .../ok_trailing_import_comma/diagnostics.snap | 6 ++ .../typeck/ok_trailing_import_comma/m.sol | 4 + .../typeck/ok_trailing_import_comma/main.sol | 1 + .../ok_trait_head_generic/diagnostics.snap | 6 ++ .../typeck/ok_trait_head_generic/main.sol | 1 + .../diagnostics.snap | 2 +- .../ok_uint256_binops_class_methods/main.sol | 16 ++-- .../omitted_forall_poly/diagnostics.snap | 15 ---- .../typeck/omitted_forall_poly/main.solc | 9 -- .../return_bool_mismatch/diagnostics.snap | 6 +- .../typeck/return_bool_mismatch/main.sol | 2 +- .../diagnostics.snap | 14 +-- .../shorthand_constructor_ambiguous/main.sol | 4 +- .../diagnostics.snap | 12 +-- .../main.sol | 4 +- .../diagnostics.snap | 6 +- .../shorthand_constructor_no_context/main.sol | 4 +- .../diagnostics.snap | 6 +- .../shorthand_constructor_no_match/main.sol | 4 +- .../diagnostics.snap | 16 ++-- .../main.sol | 6 +- .../diagnostics.snap | 18 ++-- .../main.sol | 30 +++---- .../diagnostics.snap | 18 ++-- .../main.sol | 30 +++---- .../diagnostics.snap | 4 +- .../type_alias_expansion_limit/main.sol | 2 +- .../diagnostics.snap | 8 +- .../type_annotation_kind_mismatch/main.sol | 4 +- .../diagnostics.snap | 6 +- .../unary_type_unapplied_signature/main.sol | 4 +- .../typeck/unknown_field/diagnostics.snap | 6 +- .../fixtures/typeck/unknown_field/main.sol | 2 +- .../unreachable_match_arm/diagnostics.snap | 20 +++-- .../typeck/unreachable_match_arm/main.sol | 16 ++-- .../diagnostics.snap | 18 ++-- 85 files changed, 452 insertions(+), 448 deletions(-) delete mode 100644 crates/uitest/tests/fixtures/typeck/inferred_poly_compose/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/typeck/inferred_poly_compose/main.solc create mode 100644 crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/main.sol create mode 100644 crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/m.sol create mode 100644 crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/main.sol create mode 100644 crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/diagnostics.snap create mode 100644 crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/main.sol delete mode 100644 crates/uitest/tests/fixtures/typeck/omitted_forall_poly/diagnostics.snap delete mode 100644 crates/uitest/tests/fixtures/typeck/omitted_forall_poly/main.solc diff --git a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol index 2c8ed65a..f123e94c 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_match_branch_divergence/main.sol @@ -1,8 +1,12 @@ enum Shape { Circle(word), Square(word) } -function area(s: Shape) -> word { - match s { - | Shape.Circle(r) => return r; - | Shape.Square(w) => return true; - } +function area(s: Shape) returns (word) { + match (s) { +case Shape.Circle(r) { +return r; +} +case Shape.Square(w) { +return true; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/diagnostics.snap index fd90829f..0d54998c 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:2:10 + --> /main/main.sol:2:10 | -1 | function a() -> word { +1 | function a() returns (word) { 2 | return true; | ^^^^ expression has mismatched type 3 | } @@ -16,9 +16,9 @@ error[SC0201]: type mismatch: expected word, found bool --- error[SC0201]: type mismatch: expected numeric, found bool - --> /main/main.solc:6:10 + --> /main/main.sol:6:10 | -5 | function b() -> bool { +5 | function b() returns (bool) { 6 | return 1; | ^ expression has mismatched type 7 | } @@ -28,9 +28,9 @@ error[SC0201]: type mismatch: expected numeric, found bool --- error[SC0206]: non-callable value of type word - --> /main/main.solc:10:10 + --> /main/main.sol:10:10 | - 9 | function c(x: word) -> word { + 9 | function c(x: word) returns (word) { 10 | return x(1); | ^ callee is not callable 11 | } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol index 9eb19488..9d2e8642 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_multi_independent_errors/main.sol @@ -1,11 +1,11 @@ -function a() -> word { +function a() returns (word) { return true; } -function b() -> bool { +function b() returns (bool) { return 1; } -function c(x: word) -> word { +function c(x: word) returns (word) { return x(1); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/diagnostics.snap index 49325339..555e8f97 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol --- error[SC0202]: recursive type would be required - --> /main/main.solc:4:12 + --> /main/main.sol:4:12 | 3 | let g = x(y); 4 | return g(x); @@ -12,5 +12,5 @@ error[SC0202]: recursive type would be required 5 | }; | = note: an inferred type would need to contain itself - = note: recursive shape: ((_) -> _) -> _ + = note: recursive shape: function(function(_) returns (_)) returns (_) = help: add an explicit type annotation or split the recursive call diff --git a/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol index 8d4d8640..e81eea79 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_occurs_lambda_msg/main.sol @@ -1,4 +1,4 @@ -function f() -> () { +function f() { let s = lam (x, y) { let g = x(y); return g(x); diff --git a/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/diagnostics.snap index 75359cc7..f735cc71 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol --- error[SC0201]: type mismatch: expected Shape, found Color - --> /main/main.solc:6:5 + --> /main/main.sol:6:6 | -5 | match c { -6 | | Shape.Circle(r) => return r; - | ^^^^^^^^^^^^^^^ expression has mismatched type -7 | } +5 | match (c) { +6 | case Shape.Circle(r) { + | ^^^^^^^^^^^^^^^ expression has mismatched type +7 | return r; | = note: expected type: Shape = note: found type: Color diff --git a/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol index b8aa7553..9f1ac5d8 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_pattern_wrong_type/main.sol @@ -1,8 +1,10 @@ -data Color = Red | Green; -data Shape = Circle(word); +enum Color { Red, Green } +enum Shape { Circle(word) } -function f(c: Color) -> word { - match c { - | Shape.Circle(r) => return r; - } +function f(c: Color) returns (word) { + match (c) { +case Shape.Circle(r) { +return r; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/diagnostics.snap index 8abbc598..5f35dc04 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/diagnostics.snap @@ -1,33 +1,33 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol --- error[SC0201]: argument type mismatch in call to `first` - --> /main/main.solc:8:17 - | -1 | function first(p: (word, word)) -> word { - | - parameter `p` defined here -2 | match p { -3 | | (a, b) => return a; + --> /main/main.sol:10:17 + | + 1 | function first(p: (word, word)) returns (word) { + | - parameter `p` defined here + 2 | match (p) { + 3 | case (a, b) { ... -7 | function f() -> word { -8 | let x = first(true); - | ^^^^ argument has mismatched type -9 | return x; - | - = note: expected `(word, word)` because parameter `p` of `first` has type `(word, word)` - = note: found type: bool - = note: `first` has signature `first(p: (word, word)) -> word` + 9 | function f() returns (word) { +10 | let x = first(true); + | ^^^^ argument has mismatched type +11 | return x; + | + = note: expected `(word, word)` because parameter `p` of `first` has type `(word, word)` + = note: found type: bool + = note: `first` has signature `first(p: (word, word)) returns (word)` --- error[SC0201]: type mismatch: expected numeric, found bool - --> /main/main.solc:13:10 + --> /main/main.sol:15:10 | -12 | function g() -> bool { -13 | return 42; +14 | function g() returns (bool) { +15 | return 42; | ^^ expression has mismatched type -14 | } +16 | } | = note: expected type: numeric = note: found type: bool diff --git a/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol index d5063df6..8d5ceb8d 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_recovery_no_cascade/main.sol @@ -1,14 +1,16 @@ -function first(p: (word, word)) -> word { - match p { - | (a, b) => return a; - } +function first(p: (word, word)) returns (word) { + match (p) { +case (a, b) { +return a; +} +} } -function f() -> word { +function f() returns (word) { let x = first(true); return x; } -function g() -> bool { +function g() returns (bool) { return 42; } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/diagnostics.snap index c58d3871..7bf7c453 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol --- error[SC0201]: type mismatch: expected word, found Color - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function pick() -> word { +3 | function pick() returns (word) { 4 | return Color.Red; | ^^^^^^^^^ expression has mismatched type 5 | } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol index ee8697b3..cb11e971 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_return_type_mismatch_data/main.sol @@ -1,5 +1,5 @@ -data Color = Red | Green; +enum Color { Red, Green } -function pick() -> word { +function pick() returns (word) { return Color.Red; } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/diagnostics.snap index 4142d3d1..9daf8f0e 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol --- error[SC0203]: tuple expects 3 arguments, but 2 were provided - --> /main/main.solc:2:10 + --> /main/main.sol:2:10 | -1 | function f() -> (word, word, word) { +1 | function f() returns (word, word, word) { 2 | return (1, 2); | ^^^^^^ wrong number of arguments 3 | } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol index a7884503..7a8d1d94 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_tuple_arity_mismatch/main.sol @@ -1,3 +1,3 @@ -function f() -> (word, word, word) { +function f() returns (word, word, word) { return (1, 2); } diff --git a/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/diagnostics.snap index 59e5e8c7..1f06b330 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol --- error[SC0228]: type name used as value: `Pair` - --> /main/main.solc:4:11 + --> /main/main.sol:4:11 | -3 | function main() -> word { +3 | function main() returns (word) { 4 | let p = Pair; | ^^^^ not a value 5 | return 0; diff --git a/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol b/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol index d50d184d..f4804731 100644 --- a/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ergo_type_as_value/main.sol @@ -1,6 +1,6 @@ -data Pair = MkPair(word, word); +enum Pair { MkPair(word, word) } -function main() -> word { +function main() returns (word) { let p = Pair; return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/diagnostics.snap index c4c8f945..65115518 100644 --- a/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/diagnostics.snap @@ -1,14 +1,14 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol --- error[SC0201]: type mismatch: expected word, found () - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | -1 | function f(x : bool) -> word { -2 | if x { 1; } else { true; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expression has mismatched type +1 | function f(x: bool) returns (word) { +2 | if ( x ) { 1; } else { true; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expression has mismatched type 3 | } | = note: expected type: word diff --git a/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol index 4b1c6f21..e1f4609a 100644 --- a/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/final_if_branch_mismatch/main.sol @@ -1,3 +1,3 @@ -function f(x : bool) -> word { - if x { 1; } else { true; } +function f(x: bool) returns (word) { + if ( x ) { 1; } else { true; } } diff --git a/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/diagnostics.snap index 5d671bc4..9fcd7117 100644 --- a/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/diagnostics.snap @@ -1,174 +1,174 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.solc +input_file: crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol --- error[SC0101]: undefined name: Contract - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ unknown name -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0101]: undefined name: Fallback - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ unknown name -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0101]: undefined name: Method - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ unknown name -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | = help: did you mean `echo`? --- error[SC0101]: undefined name: Proxy - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ unknown name -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0101]: undefined name: RunContract - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ unknown name -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0101]: undefined name: fallback_default_implementation - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ unknown name -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0103]: undefined type constructor: NonPayable - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ undefined type constructor -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0103]: undefined type constructor: Proxy - --> /main/main.solc:1:10 + --> /main/main.sol:1:10 | 1 | contract C { | ^ undefined type constructor -2 | public function echo(value: uint256) -> uint256 { return value; } +2 | function echo(value: uint256) public returns (uint256) { return value; } 3 | } | --- error[SC0103]: undefined type constructor: NonPayable - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined type constructor +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined type constructor 3 | } | --- error[SC0103]: undefined type constructor: Proxy - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined type constructor +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined type constructor 3 | } | --- error[SC0103]: undefined type constructor: string - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined type constructor +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined type constructor 3 | } | --- -error[SC0105]: undefined class: SigString - --> /main/main.solc:2:3 +error[SC0105]: undefined trait: SigString + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined class +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ undefined trait 3 | } | --- error[SC0231]: ABI output cannot be represented in the ABI: - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 3 | } | --- error[SC0231]: ABI parameter cannot be represented in the ABI: - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 3 | } | --- error[SC0231]: echo cannot be represented in the ABI: - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 3 | } | --- error[SC0103]: undefined type constructor: uint256 - --> /main/main.solc:2:31 + --> /main/main.sol:2:24 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^ undefined type constructor +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^ undefined type constructor 3 | } | --- error[SC0103]: undefined type constructor: uint256 - --> /main/main.solc:2:43 + --> /main/main.sol:2:49 | 1 | contract C { -2 | public function echo(value: uint256) -> uint256 { return value; } - | ^^^^^^^ undefined type constructor +2 | function echo(value: uint256) public returns (uint256) { return value; } + | ^^^^^^^ undefined type constructor 3 | } | diff --git a/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol b/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol index 237106ac..6b78753c 100644 --- a/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol +++ b/crates/uitest/tests/fixtures/typeck/generated_dispatch_requires_explicit_imports/main.sol @@ -1,3 +1,3 @@ contract C { - public function echo(value: uint256) -> uint256 { return value; } + function echo(value: uint256) public returns (uint256) { return value; } } diff --git a/crates/uitest/tests/fixtures/typeck/inferred_poly_compose/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/inferred_poly_compose/diagnostics.snap deleted file mode 100644 index e883fe09..00000000 --- a/crates/uitest/tests/fixtures/typeck/inferred_poly_compose/diagnostics.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/inferred_poly_compose/main.solc ---- -error[SC0220]: top-level function must have complete type annotations - --> /main/main.solc:2:19 - | -1 | contract C { -2 | public function compose(f, g) { - | ^^^^^^^ incomplete signature -3 | return lam (x) { - | - = note: signature: public function compose(f, g) - = note: annotate every parameter (name : Type) and provide a return type (-> Type) diff --git a/crates/uitest/tests/fixtures/typeck/inferred_poly_compose/main.solc b/crates/uitest/tests/fixtures/typeck/inferred_poly_compose/main.solc deleted file mode 100644 index 27fbb023..00000000 --- a/crates/uitest/tests/fixtures/typeck/inferred_poly_compose/main.solc +++ /dev/null @@ -1,16 +0,0 @@ -contract C { - public function compose(f, g) { - return lam (x) { - return f(g(x)); - }; - } - - public function id(x : word) -> word { - return x; - } - - public function main() -> word { - let f = compose(id, id); - return f(42); - } -} diff --git a/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/diagnostics.snap index 2a9cb335..83fa3dd1 100644 --- a/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/diagnostics.snap @@ -1,17 +1,17 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.solc +input_file: crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol --- error[SC0299]: ambiguous inferred type - --> /main/main.solc:1:22 + --> /main/main.sol:1:29 | -1 | function f() -> word { - | ______________________^ +1 | function f() returns (word) { + | _____________________________^ 2 | | let y = 7; 3 | | return 0; 4 | | } | |_^ ambiguous inferred type | - = note: forall _ . _ : Int => () -> word - = help: add a type annotation or a matching instance to fix the ambiguous type variable + = note: <_> function() returns (word) where _: Int + = help: add a type annotation or a matching impl to fix the ambiguous type variable diff --git a/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol b/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol index 15d56e87..6b91a3a2 100644 --- a/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol +++ b/crates/uitest/tests/fixtures/typeck/let_unannotated_literal/main.sol @@ -1,4 +1,4 @@ -function f() -> word { +function f() returns (word) { let y = 7; return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/diagnostics.snap index 1f9a9116..d91b64bf 100644 --- a/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/diagnostics.snap @@ -1,45 +1,45 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.solc +input_file: crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol --- -error[SC0207]: cannot satisfy class constraint: Contract(Method(DispatchNameTy_Shapes_roundtrip, NonPayable, Point, Point, (Point) -> Point), Fallback(NonPayable, (), (), () -> ())) : RunContract - --> /main/main.solc:7:10 +error[SC0207]: cannot satisfy trait constraint: Contract, Fallback>: RunContract + --> /main/main.sol:7:10 | 6 | 7 | contract Shapes { | ^^^^^^ constraint originates here -8 | public function roundtrip(p: Point) -> Point { return p; } +8 | function roundtrip(p: Point) public returns (Point) { return p; } | - = note: no visible instance matches `Contract(Method(DispatchNameTy_Shapes_roundtrip, NonPayable, Point, Point, (Point) -> Point), Fallback(NonPayable, (), (), () -> ())) : RunContract` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `Contract, Fallback>: RunContract` + = help: add a matching impl or strengthen the surrounding type context --- error[SC0231]: ABI output cannot be represented in the ABI: Point (manual or excluded Generic representations are not canonical ABI layouts) - --> /main/main.solc:8:3 + --> /main/main.sol:8:3 | 7 | contract Shapes { -8 | public function roundtrip(p: Point) -> Point { return p; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +8 | function roundtrip(p: Point) public returns (Point) { return p; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 9 | } | --- error[SC0231]: ABI parameter cannot be represented in the ABI: Point (manual or excluded Generic representations are not canonical ABI layouts) - --> /main/main.solc:8:3 + --> /main/main.sol:8:3 | 7 | contract Shapes { -8 | public function roundtrip(p: Point) -> Point { return p; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +8 | function roundtrip(p: Point) public returns (Point) { return p; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 9 | } | --- error[SC0231]: roundtrip cannot be represented in the ABI: Point (manual or excluded Generic representations are not canonical ABI layouts) - --> /main/main.solc:8:3 + --> /main/main.sol:8:3 | 7 | contract Shapes { -8 | public function roundtrip(p: Point) -> Point { return p; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type +8 | function roundtrip(p: Point) public returns (Point) { return p; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type 9 | } | diff --git a/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol b/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol index 3faa48e9..06ba30f8 100644 --- a/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol +++ b/crates/uitest/tests/fixtures/typeck/manual_generic_adt_external_abi/main.sol @@ -1,9 +1,9 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; pragma no-generic-instance-for Point; -data Point = Point(word, word); +enum Point { Point(word, word) } contract Shapes { - public function roundtrip(p: Point) -> Point { return p; } + function roundtrip(p: Point) public returns (Point) { return p; } } diff --git a/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/diagnostics.snap index ff18876c..8cf71fca 100644 --- a/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:4:21 + --> /main/main.sol:7:8 | -3 | | true => return 1; -4 | | false => return true; - | ^^^^ expression has mismatched type -5 | } +6 | case false { +7 | return true; + | ^^^^ expression has mismatched type +8 | } | = note: expected type: word = note: found type: bool diff --git a/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol index 787982dd..7ce17c13 100644 --- a/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/match_branch_mismatch/main.sol @@ -1,6 +1,10 @@ -function h(x : bool) -> word { - match x { - | true => return 1; - | false => return true; - } +function h(x: bool) returns (word) { + match (x) { +case true { +return 1; +} +case false { +return true; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/diagnostics.snap index cba6e5b9..36807a0a 100644 --- a/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.solc +input_file: crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol --- -error[SC0207]: cannot satisfy class constraint: Contract(Method(DispatchNameTy_WordAbiProbe_echo, NonPayable, word, word, (word) -> word), Fallback(NonPayable, (), (), () -> ())) : RunContract - --> /main/main.solc:7:10 +error[SC0207]: cannot satisfy trait constraint: Contract, Fallback>: RunContract + --> /main/main.sol:7:10 | 6 | // with a bounded solver diagnostic while that evidence is missing. 7 | contract WordAbiProbe { | ^^^^^^^^^^^^ constraint originates here -8 | public function echo(value: word) -> word { +8 | function echo(value: word) public returns (word) { | - = note: no visible instance matches `Contract(Method(DispatchNameTy_WordAbiProbe_echo, NonPayable, word, word, (word) -> word), Fallback(NonPayable, (), (), () -> ())) : RunContract` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `Contract, Fallback>: RunContract` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol b/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol index 3d060bdc..3d1252d7 100644 --- a/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol +++ b/crates/uitest/tests/fixtures/typeck/missing_word_abi_evidence/main.sol @@ -1,11 +1,11 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; // `word` has ABI metadata (`uint256`) but the pinned shared std does not yet // provide its selector/decode/encode evidence. The frontend must terminate // with a bounded solver diagnostic while that evidence is missing. contract WordAbiProbe { - public function echo(value: word) -> word { + function echo(value: word) public returns (word) { return value; } } diff --git a/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/diagnostics.snap index 9b0cd6e8..768bf69f 100644 --- a/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.solc +input_file: crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol --- error[SC0203]: undefined type: A - --> /main/main.solc:2:12 + --> /main/main.sol:2:12 | -1 | data A = A(B); -2 | data B = B(A); +1 | enum A { A(B) } +2 | enum B { B(A) } | ^ undefined type 3 | | diff --git a/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol b/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol index f3d03ddb..c7cf965d 100644 --- a/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol +++ b/crates/uitest/tests/fixtures/typeck/mutual_recursive_data/main.sol @@ -1,6 +1,6 @@ -data A = A(B); -data B = B(A); +enum A { A(B) } +enum B { B(A) } -function f(x: A) -> word { +function f(x: A) returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/diagnostics.snap index adc65a9d..a9c84a43 100644 --- a/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol --- error[SC0302]: non-exhaustive pattern match - --> /main/main.solc:5:9 + --> /main/main.sol:5:10 | -4 | function pick(x : Outer) -> word { -5 | match x { - | ^ non-exhaustive match -6 | | Outer.Other => return 0; +4 | function pick(x: Outer) returns (word) { +5 | match (x) { + | ^ non-exhaustive match +6 | case Outer.Other { | = note: missing case: Outer.Wrap(Inner.B) = note: help: add a clause that covers the missing case diff --git a/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol b/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol index e7585c81..7bb7e9db 100644 --- a/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nested_constructor_nonexhaustive/main.sol @@ -1,9 +1,13 @@ -data Inner = A | B; -data Outer = Other | Wrap(Inner); +enum Inner { A, B } +enum Outer { Other, Wrap(Inner) } -function pick(x : Outer) -> word { - match x { - | Outer.Other => return 0; - | Outer.Wrap(Inner.A) => return 1; - } +function pick(x: Outer) returns (word) { + match (x) { +case Outer.Other { +return 0; +} +case Outer.Wrap(Inner.A) { +return 1; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/diagnostics.snap index e2bbd80e..e589f977 100644 --- a/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/diagnostics.snap @@ -1,14 +1,16 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol --- warning[SC0303]: unreachable match arm - --> /main/main.solc:7:3 - | -6 | | Outer.Wrap(_) => return 0; -7 | | Outer.Wrap(Inner.A) => return 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this arm is unreachable -8 | | Outer.Other => return 2; - | - = note: this arm is covered by previous match arms + --> /main/main.sol:9:1 + | + 8 | } + 9 | / case Outer.Wrap(Inner.A) { +10 | | return 1; +11 | | } + | |_^ this arm is unreachable +12 | case Outer.Other { + | + = note: this arm is covered by previous match arms diff --git a/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol b/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol index 2ca82cce..8c803b5f 100644 --- a/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nested_constructor_unreachable/main.sol @@ -1,10 +1,16 @@ -data Inner = A | B; -data Outer = Other | Wrap(Inner); +enum Inner { A, B } +enum Outer { Other, Wrap(Inner) } -function pick(x : Outer) -> word { - match x { - | Outer.Wrap(_) => return 0; - | Outer.Wrap(Inner.A) => return 1; - | Outer.Other => return 2; - } +function pick(x: Outer) returns (word) { + match (x) { +case Outer.Wrap(_) { +return 0; +} +case Outer.Wrap(Inner.A) { +return 1; +} +case Outer.Other { +return 2; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/diagnostics.snap index 03207c60..de513b53 100644 --- a/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol --- error[SC0302]: non-exhaustive pattern match - --> /main/main.solc:5:11 + --> /main/main.sol:5:12 | -4 | public function pick(x : Flag) -> word { -5 | match x { - | ^ non-exhaustive match -6 | | Flag.Off => return 0; +4 | function pick(x: Flag) public returns (word) { +5 | match (x) { + | ^ non-exhaustive match +6 | case Flag.Off { | = note: missing case: Flag.On = note: help: add a clause that covers the missing case diff --git a/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol b/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol index a721e785..41f3d391 100644 --- a/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nonexhaustive_contract/main.sol @@ -1,13 +1,15 @@ contract C { - data Flag = Off | On; + enum Flag { Off, On } - public function pick(x : Flag) -> word { - match x { - | Flag.Off => return 0; - } + function pick(x: Flag) public returns (word) { + match (x) { +case Flag.Off { +return 0; +} +} } - function main() -> word { + function main() returns (word) { return 0; } } diff --git a/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/diagnostics.snap index 75ca3d01..ff302011 100644 --- a/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol --- error[SC0302]: non-exhaustive pattern match - --> /main/main.solc:4:9 + --> /main/main.sol:4:10 | -3 | function pick(x : Flag) -> word { -4 | match x { - | ^ non-exhaustive match -5 | | Flag.Off => return 0; +3 | function pick(x: Flag) returns (word) { +4 | match (x) { + | ^ non-exhaustive match +5 | case Flag.Off { | = note: missing case: Flag.On = note: help: add a clause that covers the missing case diff --git a/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol b/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol index 5498afc9..67635787 100644 --- a/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nonexhaustive_free_fn/main.sol @@ -1,7 +1,9 @@ -data Flag = Off | On; +enum Flag { Off, On } -function pick(x : Flag) -> word { - match x { - | Flag.Off => return 0; - } +function pick(x: Flag) returns (word) { + match (x) { +case Flag.Off { +return 0; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/nonfinal_return/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nonfinal_return/diagnostics.snap index 03865a0d..e437a42b 100644 --- a/crates/uitest/tests/fixtures/typeck/nonfinal_return/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nonfinal_return/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nonfinal_return/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol --- error[SC0222]: illegal return statement - --> /main/main.solc:2:3 + --> /main/main.sol:2:3 | -1 | function g() -> word { +1 | function g() returns (word) { 2 | return 1; | ^^^^^^^^^ return before end of block 3 | return 2; diff --git a/crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol b/crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol index ba6c25bb..3ef4fe10 100644 --- a/crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nonfinal_return/main.sol @@ -1,4 +1,4 @@ -function g() -> word { +function g() returns (word) { return 1; return 2; } diff --git a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/diagnostics.snap index c863da97..b3e34509 100644 --- a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol --- error[SC0299]: Invalid number of type arguments! - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function f() -> word { -4 | let x: M(word) = M.Mk; +3 | function f() returns (word) { +4 | let x: M = M.Mk; | ^^^^^^^ diagnostic reported here 5 | return 0; | = note: Type M is expected to have 0 type arguments - = note: but, type M(word) has 1 arguments + = note: but, type M has 1 arguments diff --git a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol index ef437697..fdd1397d 100644 --- a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_let/main.sol @@ -1,6 +1,6 @@ -data M = Mk; +enum M { Mk } -function f() -> word { - let x: M(word) = M.Mk; +function f() returns (word) { + let x: M = M.Mk; return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/diagnostics.snap index add658ba..5fefce41 100644 --- a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.solc +input_file: crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol --- error[SC0299]: Invalid number of type arguments! - --> /main/main.solc:3:15 + --> /main/main.sol:3:15 | 2 | -3 | function f(x: M(word)) -> word { +3 | function f(x: M) returns (word) { | ^^^^^^^ diagnostic reported here 4 | return 0; | = note: Type M is expected to have 0 type arguments - = note: but, type M(word) has 1 arguments + = note: but, type M has 1 arguments diff --git a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol index f7272704..f0cc7d05 100644 --- a/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol +++ b/crates/uitest/tests/fixtures/typeck/nullary_type_applied_signature/main.sol @@ -1,5 +1,5 @@ -data M = Mk; +enum M { Mk } -function f(x: M(word)) -> word { +function f(x: M) returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/occurs_check/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/occurs_check/diagnostics.snap index 26777c44..7914f07a 100644 --- a/crates/uitest/tests/fixtures/typeck/occurs_check/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/occurs_check/diagnostics.snap @@ -1,16 +1,16 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/occurs_check/main.solc +input_file: crates/uitest/tests/fixtures/typeck/occurs_check/main.sol --- error[SC0202]: recursive type would be required - --> /main/main.solc:2:30 + --> /main/main.sol:2:30 | -1 | function f() -> () { +1 | function f() { 2 | let self = lam(x) { return x(x); }; | ^^^^ recursive type required here 3 | return (); | = note: an inferred type would need to contain itself - = note: recursive shape: (_) -> _ + = note: recursive shape: function(_) returns (_) = help: add an explicit type annotation or split the recursive call diff --git a/crates/uitest/tests/fixtures/typeck/occurs_check/main.sol b/crates/uitest/tests/fixtures/typeck/occurs_check/main.sol index da2e54f8..9f1546e6 100644 --- a/crates/uitest/tests/fixtures/typeck/occurs_check/main.sol +++ b/crates/uitest/tests/fixtures/typeck/occurs_check/main.sol @@ -1,4 +1,4 @@ -function f() -> () { +function f() { let self = lam(x) { return x(x); }; return (); } diff --git a/crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/diagnostics.snap new file mode 100644 index 00000000..dfea30b3 --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/diagnostics.snap @@ -0,0 +1,6 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/main.sol +--- +no diagnostics diff --git a/crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/main.sol b/crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/main.sol new file mode 100644 index 00000000..8f391975 --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_enum_without_semicolon/main.sol @@ -0,0 +1 @@ +enum D { C } diff --git a/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/diagnostics.snap new file mode 100644 index 00000000..f48d1c95 --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/diagnostics.snap @@ -0,0 +1,6 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/main.sol +--- +no diagnostics diff --git a/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/m.sol b/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/m.sol new file mode 100644 index 00000000..c800724e --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/m.sol @@ -0,0 +1,4 @@ +function a() {} +function b() {} + +export { a, b }; diff --git a/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/main.sol b/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/main.sol new file mode 100644 index 00000000..58d5056b --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_trailing_import_comma/main.sol @@ -0,0 +1 @@ +import {a, b,} from m; diff --git a/crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/diagnostics.snap new file mode 100644 index 00000000..303da73d --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/diagnostics.snap @@ -0,0 +1,6 @@ +--- +source: crates/test-utils/src/lib.rs +expression: rendered +input_file: crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/main.sol +--- +no diagnostics diff --git a/crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/main.sol b/crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/main.sol new file mode 100644 index 00000000..2c4726e0 --- /dev/null +++ b/crates/uitest/tests/fixtures/typeck/ok_trait_head_generic/main.sol @@ -0,0 +1 @@ +trait C {} diff --git a/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/diagnostics.snap index b567edf5..dd91192e 100644 --- a/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/diagnostics.snap @@ -1,6 +1,6 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.solc +input_file: crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol --- no diagnostics diff --git a/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol b/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol index 3baa837e..15f218b0 100644 --- a/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol +++ b/crates/uitest/tests/fixtures/typeck/ok_uint256_binops_class_methods/main.sol @@ -1,28 +1,28 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract Uint256Binops { - public function mul_u256(x : uint256, y : uint256) -> uint256 { + function mul_u256(x: uint256, y: uint256) public returns (uint256) { return x * y; } - public function div_u256(x : uint256, y : uint256) -> uint256 { + function div_u256(x: uint256, y: uint256) public returns (uint256) { return x / y; } - public function mod_u256(x : uint256, y : uint256) -> uint256 { + function mod_u256(x: uint256, y: uint256) public returns (uint256) { return x % y; } - public function band_u256(x : uint256, y : uint256) -> uint256 { + function band_u256(x: uint256, y: uint256) public returns (uint256) { return x & y; } - public function bxor_u256(x : uint256, y : uint256) -> uint256 { + function bxor_u256(x: uint256, y: uint256) public returns (uint256) { return x ^ y; } - public function bor_u256(x : uint256, y : uint256) -> uint256 { + function bor_u256(x: uint256, y: uint256) public returns (uint256) { return x | y; } } diff --git a/crates/uitest/tests/fixtures/typeck/omitted_forall_poly/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/omitted_forall_poly/diagnostics.snap deleted file mode 100644 index 48e100f1..00000000 --- a/crates/uitest/tests/fixtures/typeck/omitted_forall_poly/diagnostics.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: crates/test-utils/src/lib.rs -expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/omitted_forall_poly/main.solc ---- -error[SC0220]: top-level function must have complete type annotations - --> /main/main.solc:1:10 - | -1 | function id(x) { - | ^^ incomplete signature -2 | return x; -3 | } - | - = note: signature: function id(x) - = note: annotate every parameter (name : Type) and provide a return type (-> Type) diff --git a/crates/uitest/tests/fixtures/typeck/omitted_forall_poly/main.solc b/crates/uitest/tests/fixtures/typeck/omitted_forall_poly/main.solc deleted file mode 100644 index 1cd02c73..00000000 --- a/crates/uitest/tests/fixtures/typeck/omitted_forall_poly/main.solc +++ /dev/null @@ -1,9 +0,0 @@ -function id(x) { - return x; -} - -contract C { - public function main() -> word { - return id(42); - } -} diff --git a/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/diagnostics.snap index 47986aad..1c4464ce 100644 --- a/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol --- error[SC0201]: type mismatch: expected word, found bool - --> /main/main.solc:2:10 + --> /main/main.sol:2:10 | -1 | function f() -> word { +1 | function f() returns (word) { 2 | return true; | ^^^^ expression has mismatched type 3 | } diff --git a/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol index 35053f21..1925917c 100644 --- a/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/return_bool_mismatch/main.sol @@ -1,3 +1,3 @@ -function f() -> word { +function f() returns (word) { return true; } diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/diagnostics.snap index 5713f249..8fdb6afd 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/diagnostics.snap @@ -1,24 +1,24 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.solc +input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol --- error[SC0108]: duplicate declaration `Choice.Same` in term namespace - --> /main/main.solc:1:28 + --> /main/main.sol:1:27 | -1 | data Choice = Same(word) | Same(bool); - | ---- ^^^^ duplicate declaration +1 | enum Choice { Same(word), Same(bool) } + | ---- ^^^^ duplicate declaration | | | previous declaration 2 | -3 | function ambiguous() -> Choice { +3 | function ambiguous() returns (Choice) { | --- error[SC0224]: cannot resolve shorthand constructor `.Same`: ambiguous candidates: Same, Same - --> /main/main.solc:4:10 + --> /main/main.sol:4:10 | -3 | function ambiguous() -> Choice { +3 | function ambiguous() returns (Choice) { 4 | return .Same(1); | ^^^^^^^^ shorthand constructor 5 | } diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol index f43cac3f..b32d27ce 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_ambiguous/main.sol @@ -1,5 +1,5 @@ -data Choice = Same(word) | Same(bool); +enum Choice { Same(word), Same(bool) } -function ambiguous() -> Choice { +function ambiguous() returns (Choice) { return .Same(1); } diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/diagnostics.snap index 265fc387..3892964b 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol --- error[SC0201]: argument type mismatch in call to `Some` - --> /main/main.solc:5:13 + --> /main/main.sol:5:13 | -1 | data Option = None | Some(word); - | ---- parameter 1 defined here +1 | enum Option { None, Some(word) } + | ---- parameter 1 defined here 2 | -3 | function bad() -> word { +3 | function bad() returns (word) { 4 | let x : Option; 5 | x = .Some(true); | ^^^^ argument has mismatched type @@ -17,4 +17,4 @@ error[SC0201]: argument type mismatch in call to `Some` | = note: expected `word` because parameter 1 of `Some` has type `word` = note: found type: bool - = note: `Some` has signature `Some(word) -> Option` + = note: `Some` has signature `Some(word) returns (Option)` diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol index 32337e7a..f896e9df 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_assignment_mismatch/main.sol @@ -1,6 +1,6 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function bad() -> word { +function bad() returns (word) { let x : Option; x = .Some(true); return 0; diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/diagnostics.snap index 074e970c..da066943 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.solc +input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol --- error[SC0224]: cannot resolve shorthand constructor `.Some`: cannot resolve without expected constructor type - --> /main/main.solc:4:11 + --> /main/main.sol:4:11 | -3 | function noContext() -> word { +3 | function noContext() returns (word) { 4 | let x = .Some(1); | ^^^^^^^^ shorthand constructor 5 | return 0; diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol index 2939a370..c27b4b85 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_context/main.sol @@ -1,6 +1,6 @@ -data Option = None | Some(word); +enum Option { None, Some(word) } -function noContext() -> word { +function noContext() returns (word) { let x = .Some(1); return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/diagnostics.snap index 24c901db..17d85201 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.solc +input_file: crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol --- error[SC0101]: undefined name: Some - --> /main/main.solc:4:11 + --> /main/main.sol:4:11 | -3 | function noMatch() -> Other { +3 | function noMatch() returns (Other) { 4 | return .Some(1); | ^^^^ unknown name 5 | } diff --git a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol index 12e7362c..77800cd2 100644 --- a/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol +++ b/crates/uitest/tests/fixtures/typeck/shorthand_constructor_no_match/main.sol @@ -1,5 +1,5 @@ -data Other = Other; +enum Other { Other } -function noMatch() -> Other { +function noMatch() returns (Other) { return .Some(1); } diff --git a/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/diagnostics.snap index 99d46b6f..44a9353f 100644 --- a/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/diagnostics.snap @@ -1,25 +1,25 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.solc +input_file: crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol --- -error[SC0207]: cannot satisfy class constraint: ABIDecoder(Choice, MemoryWordReader) : ABIDecode(Choice) - --> /main/main.solc:6:3 +error[SC0207]: cannot satisfy trait constraint: ABIDecoder: ABIDecode + --> /main/main.sol:6:3 | 5 | contract C { 6 | constructor(value: Choice) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constraint originates here -7 | function main() -> () { return (); } +7 | function main() { return (); } | - = note: no visible instance matches `ABIDecoder(Choice, MemoryWordReader) : ABIDecode(Choice)` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `ABIDecoder: ABIDecode` + = help: add a matching impl or strengthen the surrounding type context --- error[SC0231]: ABI parameter cannot be represented in the ABI: Choice (user-defined ADTs are not supported by the canonical external ABI) - --> /main/main.solc:6:3 + --> /main/main.sol:6:3 | 5 | contract C { 6 | constructor(value: Choice) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported ABI type -7 | function main() -> () { return (); } +7 | function main() { return (); } | diff --git a/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol b/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol index 93cb5f64..da789021 100644 --- a/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol +++ b/crates/uitest/tests/fixtures/typeck/source_runtime_main_constructor_abi_error/main.sol @@ -1,8 +1,8 @@ -import std.{*}; +import * from std; -data Choice = Left(word) | Right(word); +enum Choice { Left(word), Right(word) } contract C { constructor(value: Choice) {} - function main() -> () { return (); } + function main() { return (); } } diff --git a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/diagnostics.snap index c43ef022..c4d63125 100644 --- a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.solc +input_file: crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol --- -error[SC0207]: cannot satisfy class constraint: bool : Add - --> /main/main.solc:22:31 +error[SC0207]: cannot satisfy trait constraint: bool: Add + --> /main/main.sol:22:25 | -21 | m: mapping(word, bool); -22 | function f(k: word) -> () { m[k] += true; } - | ^^^^^^^^^^^^ constraint originates here -23 | function main() -> () { return (); } +21 | m: mapping(word => bool); +22 | function f(k: word) { m[k] += true; } + | ^^^^^^^^^^^^ constraint originates here +23 | function main() { return (); } | - = note: no visible instance matches `bool : Add` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `bool: Add` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol index d191a415..10cb00f8 100644 --- a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol +++ b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_add_bool/main.sol @@ -1,24 +1,24 @@ -data mapping(key, value) = mapping(word); -data uint256 = uint256(word); +enum mapping { mapping(word) } +enum uint256 { uint256(word) } -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Sub { - function sub(l: t, r: t) -> t; +trait Sub { + function sub(l: t, r: t) returns (t) ; } -instance word:Add { - function add(l: word, r: word) -> word { return l; } +impl Add { + function add(l: word, r: word) returns (word) { return l; } } -instance word:Sub { - function sub(l: word, r: word) -> word { return l; } +impl Sub { + function sub(l: word, r: word) returns (word) { return l; } } -instance uint256:Add { - function add(l: uint256, r: uint256) -> uint256 { return l; } +impl Add { + function add(l: uint256, r: uint256) returns (uint256) { return l; } } contract C { - m: mapping(word, bool); - function f(k: word) -> () { m[k] += true; } - function main() -> () { return (); } + m: mapping(word => bool); + function f(k: word) { m[k] += true; } + function main() { return (); } } diff --git a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/diagnostics.snap index cce7a139..ecc2c7a5 100644 --- a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.solc +input_file: crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol --- -error[SC0207]: cannot satisfy class constraint: bool : Sub - --> /main/main.solc:22:31 +error[SC0207]: cannot satisfy trait constraint: bool: Sub + --> /main/main.sol:22:25 | -21 | m: mapping(word, bool); -22 | function f(k: word) -> () { m[k] -= true; } - | ^^^^^^^^^^^^ constraint originates here -23 | function main() -> () { return (); } +21 | m: mapping(word => bool); +22 | function f(k: word) { m[k] -= true; } + | ^^^^^^^^^^^^ constraint originates here +23 | function main() { return (); } | - = note: no visible instance matches `bool : Sub` - = help: add a matching instance or strengthen the surrounding type context + = note: no visible impl matches `bool: Sub` + = help: add a matching impl or strengthen the surrounding type context diff --git a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol index d7eb0176..8e249b72 100644 --- a/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol +++ b/crates/uitest/tests/fixtures/typeck/storage_mapping_compound_sub_bool/main.sol @@ -1,24 +1,24 @@ -data mapping(key, value) = mapping(word); -data uint256 = uint256(word); +enum mapping { mapping(word) } +enum uint256 { uint256(word) } -forall t . class t:Add { - function add(l: t, r: t) -> t; +trait Add { + function add(l: t, r: t) returns (t) ; } -forall t . class t:Sub { - function sub(l: t, r: t) -> t; +trait Sub { + function sub(l: t, r: t) returns (t) ; } -instance word:Add { - function add(l: word, r: word) -> word { return l; } +impl Add { + function add(l: word, r: word) returns (word) { return l; } } -instance word:Sub { - function sub(l: word, r: word) -> word { return l; } +impl Sub { + function sub(l: word, r: word) returns (word) { return l; } } -instance uint256:Add { - function add(l: uint256, r: uint256) -> uint256 { return l; } +impl Add { + function add(l: uint256, r: uint256) returns (uint256) { return l; } } contract C { - m: mapping(word, bool); - function f(k: word) -> () { m[k] -= true; } - function main() -> () { return (); } + m: mapping(word => bool); + function f(k: word) { m[k] -= true; } + function main() { return (); } } diff --git a/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/diagnostics.snap index df6c2e8f..98c6bec3 100644 --- a/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.solc +input_file: crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol --- error[SC0243]: type synonym expansion exceeded 16384 type nodes - --> /main/main.solc:14:6 + --> /main/main.sol:14:6 | 13 | type T12 = (T11, T11); 14 | type T13 = (T12, T12); diff --git a/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol b/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol index 7c329a74..de1099ae 100644 --- a/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol +++ b/crates/uitest/tests/fixtures/typeck/type_alias_expansion_limit/main.sol @@ -13,6 +13,6 @@ type T11 = (T10, T10); type T12 = (T11, T11); type T13 = (T12, T12); -function use_bomb(x: T13) -> T13 { +function use_bomb(x: T13) returns (T13) { return x; } diff --git a/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/diagnostics.snap index a12716f7..4e0e2018 100644 --- a/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.solc +input_file: crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol --- error[SC0299]: Invalid number of type arguments! - --> /main/main.solc:3:17 + --> /main/main.sol:3:17 | 2 | -3 | function f(x: P(word(word))) -> word { +3 | function f(x: P>) returns (word) { | ^^^^^^^^^^ diagnostic reported here 4 | return 0; | = note: Type word is expected to have 0 type arguments - = note: but, type word(word) has 1 arguments + = note: but, type word has 1 arguments diff --git a/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol b/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol index 212fe581..4a23952e 100644 --- a/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol +++ b/crates/uitest/tests/fixtures/typeck/type_annotation_kind_mismatch/main.sol @@ -1,5 +1,5 @@ -data P(a) = Mk(a); +enum P { Mk(a) } -function f(x: P(word(word))) -> word { +function f(x: P>) returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/diagnostics.snap index 23725549..c88c4626 100644 --- a/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.solc +input_file: crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol --- error[SC0299]: Invalid number of type arguments! - --> /main/main.solc:3:15 + --> /main/main.sol:3:15 | 2 | -3 | function f(x: P) -> word { +3 | function f(x: P) returns (word) { | ^ diagnostic reported here 4 | return 0; | diff --git a/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol b/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol index 264483d2..f0e74d08 100644 --- a/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol +++ b/crates/uitest/tests/fixtures/typeck/unary_type_unapplied_signature/main.sol @@ -1,5 +1,5 @@ -data P(a) = Mk(a); +enum P { Mk(a) } -function f(x: P) -> word { +function f(x: P) returns (word) { return 0; } diff --git a/crates/uitest/tests/fixtures/typeck/unknown_field/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/unknown_field/diagnostics.snap index 5aeee6ea..7b878c8c 100644 --- a/crates/uitest/tests/fixtures/typeck/unknown_field/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/unknown_field/diagnostics.snap @@ -1,12 +1,12 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/unknown_field/main.solc +input_file: crates/uitest/tests/fixtures/typeck/unknown_field/main.sol --- error[SC0205]: cannot resolve field `foo` - --> /main/main.solc:2:12 + --> /main/main.sol:2:12 | -1 | function f(x: word) -> word { +1 | function f(x: word) returns (word) { 2 | return x.foo; | ^^^ unknown field 3 | } diff --git a/crates/uitest/tests/fixtures/typeck/unknown_field/main.sol b/crates/uitest/tests/fixtures/typeck/unknown_field/main.sol index 6ef4228f..6e85e9ef 100644 --- a/crates/uitest/tests/fixtures/typeck/unknown_field/main.sol +++ b/crates/uitest/tests/fixtures/typeck/unknown_field/main.sol @@ -1,3 +1,3 @@ -function f(x: word) -> word { +function f(x: word) returns (word) { return x.foo; } diff --git a/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/diagnostics.snap index aa4cc818..189ddab6 100644 --- a/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/diagnostics.snap @@ -1,14 +1,16 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.solc +input_file: crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol --- warning[SC0303]: unreachable match arm - --> /main/main.solc:6:3 - | -5 | | _ => return 0; -6 | | Flag.Off => return 1; - | ^^^^^^^^^^^^^^^^^^^^^^^ this arm is unreachable -7 | } - | - = note: this arm is covered by previous match arms + --> /main/main.sol:8:1 + | + 7 | } + 8 | / case Flag.Off { + 9 | | return 1; +10 | | } + | |_^ this arm is unreachable +11 | } + | + = note: this arm is covered by previous match arms diff --git a/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol b/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol index 2fa579e4..86a0edc9 100644 --- a/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol +++ b/crates/uitest/tests/fixtures/typeck/unreachable_match_arm/main.sol @@ -1,8 +1,12 @@ -data Flag = Off | On; +enum Flag { Off, On } -function pick(x : Flag) -> word { - match x { - | _ => return 0; - | Flag.Off => return 1; - } +function pick(x: Flag) returns (word) { + match (x) { +case _ { +return 0; +} +case Flag.Off { +return 1; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap index ea141ea1..355a319e 100644 --- a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap @@ -1,26 +1,26 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.solc +input_file: crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol --- error[SC0231]: public function `echo` ABI for contract `C` cannot use visible manual `ABIAttribs` evidence - --> /main/main.solc:22:3 + --> /main/main.sol:22:3 | 21 | contract C { -22 | public function echo(value: word) -> word { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical +22 | function echo(value: word) public returns (word) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical 23 | } | - = note: instance `ABIAttribs` can override canonical `ABIAttribs` behavior - = help: remove the visible manual ABI instance or keep this declaration out of the external ABI + = note: impl `ABIAttribs` can override canonical `ABIAttribs` behavior + = help: remove the visible manual ABI impl or keep this declaration out of the external ABI --- error[SC0231]: public function `echo` ABI for contract `C` cannot use visible manual `ABIDecode` evidence - --> /main/main.solc:22:3 + --> /main/main.sol:22:3 | 21 | contract C { -22 | public function echo(value: word) -> word { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical +22 | function echo(value: word) public returns (word) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical 23 | } | = note: instance `ABIDecode` can override canonical `ABIDecode` behavior From f874b33004017f55cb655ee72c1536b3b86f260a Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 101/110] Switch the compiler and fixtures to canonical syntax: uitest fixtures Co-authored-by: Codex --- .../diagnostics.snap | 24 +++++++++---------- .../visible_manual_std_abi_instances/main.sol | 24 +++++++++---------- .../diagnostics.snap | 12 +++++----- .../whole_mapping_private_full/main.sol | 14 +++++------ .../diagnostics.snap | 12 +++++----- .../word_literals_nonexhaustive/main.sol | 14 +++++++---- .../yul_multi_return_arity/diagnostics.snap | 4 ++-- .../typeck/yul_multi_return_arity/main.sol | 2 +- .../diagnostics.snap | 6 ++--- .../yul_non_word_sail_variable/main.sol | 4 ++-- .../typeck/yul_opcode_errors/diagnostics.snap | 10 ++++---- .../typeck/yul_opcode_errors/main.sol | 2 +- 12 files changed, 66 insertions(+), 62 deletions(-) diff --git a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap index 355a319e..07f3505c 100644 --- a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/diagnostics.snap @@ -23,29 +23,29 @@ error[SC0231]: public function `echo` ABI for contract `C` cannot use visible ma | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical 23 | } | - = note: instance `ABIDecode` can override canonical `ABIDecode` behavior - = help: remove the visible manual ABI instance or keep this declaration out of the external ABI + = note: impl `ABIDecode` can override canonical `ABIDecode` behavior + = help: remove the visible manual ABI impl or keep this declaration out of the external ABI --- error[SC0231]: public function `echo` ABI for contract `C` cannot use visible manual `ABIEncode` evidence - --> /main/main.solc:22:3 + --> /main/main.sol:22:3 | 21 | contract C { -22 | public function echo(value: word) -> word { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical +22 | function echo(value: word) public returns (word) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical 23 | } | - = note: instance `ABIEncode` can override canonical `ABIEncode` behavior - = help: remove the visible manual ABI instance or keep this declaration out of the external ABI + = note: impl `ABIEncode` can override canonical `ABIEncode` behavior + = help: remove the visible manual ABI impl or keep this declaration out of the external ABI --- error[SC0231]: public function `echo` ABI for contract `C` cannot use visible manual `SigString` evidence - --> /main/main.solc:22:3 + --> /main/main.sol:22:3 | 21 | contract C { -22 | public function echo(value: word) -> word { return value; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical +22 | function echo(value: word) public returns (word) { return value; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ external ABI evidence must be compiler-owned and canonical 23 | } | - = note: instance `SigString` can override canonical `SigString` behavior - = help: remove the visible manual ABI instance or keep this declaration out of the external ABI + = note: impl `SigString` can override canonical `SigString` behavior + = help: remove the visible manual ABI impl or keep this declaration out of the external ABI diff --git a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol index 042d32d8..0c9d6149 100644 --- a/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol +++ b/crates/uitest/tests/fixtures/typeck/visible_manual_std_abi_instances/main.sol @@ -1,23 +1,23 @@ -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; -instance word:ABIAttribs { - function headSize(p: Proxy(word)) -> word { return 32; } - function isStatic(p: Proxy(word)) -> bool { return true; } +impl ABIAttribs { + function headSize(p: Proxy) returns (word) { return 32; } + function isStatic(p: Proxy) returns (bool) { return true; } } -instance word:ABIEncode { - function encodeInto(x: word, base: word, offset: word, tail: word) -> word { return tail; } +impl ABIEncode { + function encodeInto(x: word, base: word, offset: word, tail: word) returns (word) { return tail; } } -instance ABIDecoder(word, CalldataWordReader):ABIDecode(word) { - function decode(d: ABIDecoder(word, CalldataWordReader), offset: word) -> word { return 0; } +impl ABIDecode, word> { + function decode(d: ABIDecoder, offset: word) returns (word) { return 0; } } -instance word:SigString { - function sigStr(p: Proxy(word)) -> string { return "uint256"; } +impl SigString { + function sigStr(p: Proxy) returns (string) { return "uint256"; } } contract C { - public function echo(value: word) -> word { return value; } + function echo(value: word) public returns (word) { return value; } } diff --git a/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/diagnostics.snap index cbc8a5f9..fc80f787 100644 --- a/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.solc +input_file: crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol --- -error[SC0201]: type mismatch: expected mapping(address, uint256), found storage(mapping(address, uint256)) - --> /main/main.solc:10:12 +error[SC0201]: type mismatch: expected mapping(address => uint256), found storage uint256)> + --> /main/main.sol:10:12 | - 9 | function leak() -> mapping(address, uint256) { + 9 | function leak() returns (mapping(address => uint256)) { 10 | return balances; | ^^^^^^^^ expression has mismatched type 11 | } | - = note: expected type: mapping(address, uint256) - = note: found type: storage(mapping(address, uint256)) + = note: expected type: mapping(address => uint256) + = note: found type: storage uint256)> diff --git a/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol b/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol index d5fb42a8..888e173c 100644 --- a/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol +++ b/crates/uitest/tests/fixtures/typeck/whole_mapping_private_full/main.sol @@ -1,16 +1,16 @@ -data address = address(word); -data uint256 = uint256(word); -data mapping(index, member) = mapping(word); -data storage(t) = storage(word); +enum address { address(word) } +enum uint256 { uint256(word) } +enum mapping { mapping(word) } +enum storage { storage(word) } contract C { - balances : mapping(address, uint256); + balances : mapping(address => uint256); - function leak() -> mapping(address, uint256) { + function leak() returns (mapping(address => uint256)) { return balances; } - function main() -> word { + function main() returns (word) { return 0; } } diff --git a/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/diagnostics.snap index c4a7e7d7..531a5f67 100644 --- a/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/diagnostics.snap @@ -1,15 +1,15 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.solc +input_file: crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol --- error[SC0302]: non-exhaustive pattern match - --> /main/main.solc:2:9 + --> /main/main.sol:2:10 | -1 | function pick(x : word) -> word { -2 | match x { - | ^ non-exhaustive match -3 | | 0 => return 0; +1 | function pick(x: word) returns (word) { +2 | match (x) { + | ^ non-exhaustive match +3 | case 0 { | = note: missing case: _ = note: help: add a clause that covers the missing case diff --git a/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol b/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol index 970e27f0..8aaa2479 100644 --- a/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol +++ b/crates/uitest/tests/fixtures/typeck/word_literals_nonexhaustive/main.sol @@ -1,6 +1,10 @@ -function pick(x : word) -> word { - match x { - | 0 => return 0; - | 1 => return 1; - } +function pick(x: word) returns (word) { + match (x) { +case 0 { +return 0; +} +case 1 { +return 1; +} +} } diff --git a/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/diagnostics.snap index 42a48bd7..1ef5bdff 100644 --- a/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.solc +input_file: crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol --- error[SC0203]: Yul assignment expects 3 arguments, but 2 were provided - --> /main/main.solc:11:7 + --> /main/main.sol:11:7 | 10 | } 11 | x, y, z := pair() diff --git a/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol b/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol index 02263c08..c83ab153 100644 --- a/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol +++ b/crates/uitest/tests/fixtures/typeck/yul_multi_return_arity/main.sol @@ -1,5 +1,5 @@ contract YulMultiRetBad { - public function main() -> word { + function main() public returns (word) { let x : word; let y : word; let z : word; diff --git a/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/diagnostics.snap index 0e1e81d0..a6ac73e7 100644 --- a/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/diagnostics.snap @@ -1,13 +1,13 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.solc +input_file: crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol --- error[SC0204]: Yul reference `b` requires word type, got bool - --> /main/main.solc:3:14 + --> /main/main.sol:3:14 | 2 | let b : bool = false; 3 | assembly { b := add(1, 1) } | ^ Yul reference has non-word type -4 | if b { return 1; } else { return 0; } +4 | if ( b ) { return 1; } else { return 0; } | diff --git a/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol b/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol index 0c5dfe65..69c8cc39 100644 --- a/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol +++ b/crates/uitest/tests/fixtures/typeck/yul_non_word_sail_variable/main.sol @@ -1,5 +1,5 @@ -function main() -> word { +function main() returns (word) { let b : bool = false; assembly { b := add(1, 1) } - if b { return 1; } else { return 0; } + if ( b ) { return 1; } else { return 0; } } diff --git a/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/diagnostics.snap b/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/diagnostics.snap index 2f3efaf3..aa668d2a 100644 --- a/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/diagnostics.snap +++ b/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/diagnostics.snap @@ -1,10 +1,10 @@ --- source: crates/test-utils/src/lib.rs expression: rendered -input_file: crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.solc +input_file: crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol --- error[SC0203]: Yul call `add` expects 2 arguments, but 1 was provided - --> /main/main.solc:4:16 + --> /main/main.sol:4:16 | 3 | assembly { 4 | let one := add(1) @@ -16,7 +16,7 @@ error[SC0203]: Yul call `add` expects 2 arguments, but 1 was provided --- error[SC0201]: type mismatch: expected word, found string - --> /main/main.solc:5:20 + --> /main/main.sol:5:20 | 4 | let one := add(1) 5 | let two := add("bad", 1) @@ -28,7 +28,7 @@ error[SC0201]: type mismatch: expected word, found string --- error[SC0203]: Yul assignment expects 1 argument, but 0 were provided - --> /main/main.solc:6:5 + --> /main/main.sol:6:5 | 5 | let two := add("bad", 1) 6 | x := mstore(1, 1) @@ -40,7 +40,7 @@ error[SC0203]: Yul assignment expects 1 argument, but 0 were provided --- error[SC0211]: unknown Yul identifier or function: missing - --> /main/main.solc:7:14 + --> /main/main.sol:7:14 | 6 | x := mstore(1, 1) 7 | x := add(missing, 1) diff --git a/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol b/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol index 3a081449..23a7840a 100644 --- a/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol +++ b/crates/uitest/tests/fixtures/typeck/yul_opcode_errors/main.sol @@ -1,4 +1,4 @@ -function badYul() -> word { +function badYul() returns (word) { let x : word; assembly { let one := add(1) From eefe525aceccf27daf06564e018d49dc8e766394 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 102/110] Switch the compiler and fixtures to canonical syntax: vfs Co-authored-by: Codex --- crates/vfs/src/lib.rs | 220 +++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 100 deletions(-) diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index f865111a..59d325e9 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs @@ -33,56 +33,53 @@ pub const EXT_ROOT: &str = "/ext"; /// Embedded standard-library files, mounted under [`STD_ROOT`]. pub const STD_FILES: &[(&str, &str)] = &[ ( - "std.solc", - include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../std/std.solc")), + "std.sol", + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../std/std.sol")), ), ( - "dispatch.solc", + "dispatch.sol", include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../std/dispatch.solc" + "/../../std/dispatch.sol" )), ), ( - "opcodes.solc", + "opcodes.sol", include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../std/opcodes.solc" + "/../../std/opcodes.sol" )), ), ( - "Generic.solc", + "Generic.sol", include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../std/Generic.solc" + "/../../std/Generic.sol" )), ), ( - "ABIGeneric.solc", + "ABIGeneric.sol", include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../std/ABIGeneric.solc" + "/../../std/ABIGeneric.sol" )), ), ( - "StorageGeneric.solc", + "StorageGeneric.sol", include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../std/StorageGeneric.solc" + "/../../std/StorageGeneric.sol" )), ), ( - "eip712.solc", - include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../../std/eip712.solc" - )), + "eip712.sol", + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../std/eip712.sol")), ), ( - "eip7951.solc", + "eip7951.sol", include_str!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../../std/eip7951.solc" + "/../../std/eip7951.sol" )), ), ]; @@ -401,7 +398,7 @@ impl Workspace { /// Adds or replaces a user file under `/main`. /// - /// Both `main.solc` and `/main/main.solc` refer to `/main/main.solc`. + /// Both `main.sol` and `/main/main.sol` refer to `/main/main.sol`. pub fn set_file(&mut self, path: &str, contents: String) { self.apply_file_changes([WorkspaceFileChange::Set { path: path.to_owned(), @@ -556,10 +553,16 @@ impl Workspace { fn entry_key(&self) -> Option { let path = self.entry_path.as_ref()?; + if !is_solcore_module_path(path) { + return None; + } self.main_key_for_path(path) } fn main_key_for_path(&self, path: &Path) -> Option { + if !is_solcore_module_path(path) { + return None; + } let tree = self .host .module_tree @@ -836,7 +839,7 @@ fn module_fs_snapshot_from_paths<'a>( let mut existing_files = BTreeSet::new(); let mut sibling_stems = BTreeMap::>::new(); for path in paths { - if path.extension().and_then(|extension| extension.to_str()) != Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) != Some("sol") { continue; } existing_files.insert(path.clone()); @@ -858,7 +861,7 @@ fn module_fs_snapshot_from_paths<'a>( } fn is_solcore_module_path(path: &Path) -> bool { - path.extension().and_then(|extension| extension.to_str()) == Some("solc") + path.extension().and_then(|extension| extension.to_str()) == Some("sol") } fn normalize_absolute_path(path: PathBuf) -> PathBuf { @@ -927,8 +930,8 @@ mod tests { fn workspace_with_main(source: &str) -> Workspace { let mut workspace = Workspace::new(); - workspace.set_file("main.solc", source.to_owned()); - workspace.set_entry("main.solc"); + workspace.set_file("main.sol", source.to_owned()); + workspace.set_entry("main.sol"); workspace } @@ -950,7 +953,7 @@ mod tests { fn driver_style_messages(source: &str) -> Vec { let mut host = AnalysisHost::new(); - let path = main_path("main.solc"); + let path = main_path("main.sol"); host.set_virtual_file(path.clone(), source.to_owned()); let tree = host .module_tree @@ -990,7 +993,7 @@ mod tests { #[test] fn main_only_clean_program_has_driver_ordered_diagnostics() { - let source = "function main() -> word {\n return 1;\n}\n"; + let source = "function main() returns (word) {\n return 1;\n}\n"; let workspace = workspace_with_main(source); assert_eq!(messages(&workspace), driver_style_messages(source)); @@ -999,8 +1002,7 @@ mod tests { #[test] fn owned_diagnostics_preserve_heuristic_suggestion_applicability() { - let source = - "function value() -> word { return 1; }\nfunction main() -> word { return vaue(); }\n"; + let source = "function value() returns (word) { return 1; }\nfunction main() returns (word) { return vaue(); }\n"; let workspace = workspace_with_main(source); let diagnostic = workspace .diagnostics() @@ -1025,7 +1027,7 @@ mod tests { suggestion.edits, vec![DiagnosticTextEdit { range: DiagRange { - file_url: "file:///main/main.solc".to_owned(), + file_url: "file:///main/main.sol".to_owned(), start: typo, end: typo + "vaue".len() as u32, }, @@ -1036,7 +1038,7 @@ mod tests { #[test] fn owned_diagnostics_preserve_exact_suggestion_applicability() { - let source = "data Option = None | Some(word);\nfunction main(x: word) -> Option { return Some(x); }\n"; + let source = "enum Option {None , Some(word)}\nfunction main(x: word) returns (Option) { return Some(x); }\n"; let workspace = workspace_with_main(source); let diagnostic = workspace .diagnostics() @@ -1061,7 +1063,7 @@ mod tests { suggestion.edits, vec![DiagnosticTextEdit { range: DiagRange { - file_url: "file:///main/main.solc".to_owned(), + file_url: "file:///main/main.sol".to_owned(), start: constructor, end: constructor + "Some".len() as u32, }, @@ -1072,7 +1074,7 @@ mod tests { #[test] fn main_only_type_error_matches_lowered_driver_messages() { - let source = "function f() -> word {\n return true;\n}\n"; + let source = "function f() returns (word) {\n return true;\n}\n"; let workspace = workspace_with_main(source); let diagnostics = workspace.diagnostics(); @@ -1087,7 +1089,7 @@ mod tests { #[test] fn main_only_name_resolution_error_matches_lowered_driver_messages() { - let source = "function addOne(x: word) -> word {\n return x + missingVar;\n}\n"; + let source = "function addOne(x: word) returns (word) {\n return x + missingVar;\n}\n"; let workspace = workspace_with_main(source); let diagnostics = workspace.diagnostics(); @@ -1113,7 +1115,7 @@ mod tests { // for whole-frontend analysis of the embedded standard library. solcore_test_utils::run_in_large_stack(|| { let workspace = workspace_with_main( - "import std.{addWord};\n\nfunction main() -> word {\n return addWord(1, 2);\n}\n", + "import {addWord} from std;\n\nfunction main() returns (word) {\n return addWord(1, 2);\n}\n", ); assert!(workspace.diagnostics().is_empty()); @@ -1126,14 +1128,15 @@ mod tests { fn non_solcore_twin_never_replaces_or_unregisters_a_module() { let mut workspace = Workspace::new(); workspace.set_file( - "foo.solc", - "function value() -> word { return 1; }\nexport { value };\n".to_owned(), + "foo.sol", + "function value() returns (word) { return 1; }\nexport { value };\n".to_owned(), ); workspace.set_file( - "main.solc", - "import foo.{value};\nfunction main() -> word { return value(); }\n".to_owned(), + "main.sol", + "import {value} from foo;\nfunction main() returns (word) { return value(); }\n" + .to_owned(), ); - workspace.set_entry("main.solc"); + workspace.set_entry("main.sol"); assert!(workspace.diagnostics().is_empty()); workspace.set_file("foo.txt", "not solcore source".to_owned()); @@ -1143,23 +1146,39 @@ mod tests { assert!(workspace.diagnostics().is_empty()); } + #[test] + fn non_sol_entry_is_not_a_module_even_when_the_file_exists() { + let mut workspace = Workspace::new(); + workspace.set_file("main.solc", "function main() {}\n".to_owned()); + workspace.set_entry("main.solc"); + + assert!(workspace.entry_module().is_none()); + assert!(workspace.raw_diagnostics().is_empty()); + + workspace.set_file("main.sol", "function main() {}\n".to_owned()); + workspace.set_entry("main.sol"); + assert!(workspace.entry_module().is_some()); + assert!(workspace.raw_diagnostics().is_empty()); + } + #[test] fn loading_reachable_module_invalidates_cached_not_loaded_import() { let mut workspace = Workspace::new(); workspace.set_file( - "main.solc", - "import math.{double};\n\nfunction main() -> word {\n return double(21);\n}\n" + "main.sol", + "import {double} from math;\n\nfunction main() returns (word) {\n return double(21);\n}\n" .to_owned(), ); workspace.set_file( - "math.solc", - "function double(x: word) -> word { return x; }\n\nexport { double };\n".to_owned(), + "math.sol", + "function double(x: word) returns (word) { return x; }\n\nexport { double };\n" + .to_owned(), ); - workspace.set_entry("main.solc"); + workspace.set_entry("main.sol"); let math_key = workspace .host - .module_key_for_virtual_path(&main_path("math.solc")) + .module_key_for_virtual_path(&main_path("math.sol")) .expect("math module key"); assert!(workspace.host.module_files.remove(&math_key).is_some()); workspace.host.sync_module_file_snapshot(); @@ -1186,29 +1205,29 @@ mod tests { #[test] fn incremental_file_updates_reanalyze_existing_source_file() { - let clean = "function main() -> word {\n return 1;\n}\n"; + let clean = "function main() returns (word) {\n return 1;\n}\n"; let mut workspace = workspace_with_main(clean); assert!(workspace.diagnostics().is_empty()); let before_file = workspace .db() - .source_file(main_path("main.solc")) + .source_file(main_path("main.sol")) .expect("main source file"); workspace.set_file( - "main.solc", - "function addOne(x: word) -> word {\n return x + missingVar;\n}\n".to_owned(), + "main.sol", + "function addOne(x: word) returns (word) {\n return x + missingVar;\n}\n".to_owned(), ); let after_file = workspace .db() - .source_file(main_path("main.solc")) + .source_file(main_path("main.sol")) .expect("main source file"); assert_eq!(before_file, after_file); assert_eq!(workspace.diagnostics().len(), 1); - workspace.set_file("main.solc", clean.to_owned()); + workspace.set_file("main.sol", clean.to_owned()); let restored_file = workspace .db() - .source_file(main_path("main.solc")) + .source_file(main_path("main.sol")) .expect("main source file"); assert_eq!(before_file, restored_file); assert!(workspace.diagnostics().is_empty()); @@ -1216,9 +1235,9 @@ mod tests { #[test] fn removed_virtual_file_is_revived_with_the_same_salsa_identity() { - let source = "function main() -> word { return 1; }\n"; + let source = "function main() returns (word) { return 1; }\n"; let mut host = AnalysisHost::new(); - let path = main_path("main.solc"); + let path = main_path("main.sol"); let original = host.set_virtual_file(path.clone(), source.to_owned()); let _ = parser::parse_file_to_hir(&host, original); @@ -1234,13 +1253,13 @@ mod tests { #[test] fn identical_virtual_and_workspace_updates_do_not_reexecute_queries() { - let source = "function main() -> word { return 1; }\n"; + let source = "function main() returns (word) { return 1; }\n"; let (mut host, executed) = host_with_execution_log(); - let file = host.set_virtual_file(main_path("main.solc"), source.to_owned()); + let file = host.set_virtual_file(main_path("main.sol"), source.to_owned()); let _ = parser::parse_file_to_hir(&host, file); let _ = take_executed(&executed); - let same_file = host.set_virtual_file(main_path("main.solc"), source.to_owned()); + let same_file = host.set_virtual_file(main_path("main.sol"), source.to_owned()); assert_eq!(same_file, file); let _ = parser::parse_file_to_hir(&host, same_file); let events = take_executed(&executed); @@ -1255,11 +1274,11 @@ mod tests { host, entry_path: None, }; - workspace.set_entry("main.solc"); + workspace.set_entry("main.sol"); assert!(workspace.diagnostics().is_empty()); let _ = take_executed(&executed); - workspace.set_file("main.solc", source.to_owned()); + workspace.set_file("main.sol", source.to_owned()); assert!(workspace.diagnostics().is_empty()); let events = take_executed(&executed); assert_eq!( @@ -1271,52 +1290,53 @@ mod tests { #[test] fn incremental_diagnostics_match_a_fresh_workspace_across_batch_changes() { - let initial_main = "import util.{value};\nfunction main() -> word { return value(); }\n"; - let initial_util = "function value() -> word { return 1; }\nexport { value };\n"; + let initial_main = + "import {value} from util;\nfunction main() returns (word) { return value(); }\n"; + let initial_util = "function value() returns (word) { return 1; }\nexport { value };\n"; let mut incremental = workspace_from_files( - &[("main.solc", initial_main), ("util.solc", initial_util)], - "main.solc", + &[("main.sol", initial_main), ("util.sol", initial_util)], + "main.sol", ); assert!(incremental.diagnostics().is_empty()); - let broken_main = - "import helper.{answer};\nfunction main() -> word { return answer(missing); }\n"; - let broken_helper = "function answer(x: bool) -> word { return x; }\nexport { answer };\n"; + let broken_main = "import {answer} from helper;\nfunction main() returns (word) { return answer(missing); }\n"; + let broken_helper = + "function answer(x: bool) returns (word) { return x; }\nexport { answer };\n"; incremental.apply_file_changes([ WorkspaceFileChange::Set { - path: "main.solc".to_owned(), + path: "main.sol".to_owned(), contents: broken_main.to_owned(), }, WorkspaceFileChange::Remove { - path: "util.solc".to_owned(), + path: "util.sol".to_owned(), }, WorkspaceFileChange::Set { - path: "helper.solc".to_owned(), + path: "helper.sol".to_owned(), contents: broken_helper.to_owned(), }, ]); let fresh = workspace_from_files( - &[("main.solc", broken_main), ("helper.solc", broken_helper)], - "main.solc", + &[("main.sol", broken_main), ("helper.sol", broken_helper)], + "main.sol", ); assert_eq!(incremental.diagnostics(), fresh.diagnostics()); - let fixed_main = - "import helper.{answer};\nfunction main() -> word { return answer(true); }\n"; - let fixed_helper = "function answer(x: bool) -> word { return 1; }\nexport { answer };\n"; + let fixed_main = "import {answer} from helper;\nfunction main() returns (word) { return answer(true); }\n"; + let fixed_helper = + "function answer(x: bool) returns (word) { return 1; }\nexport { answer };\n"; incremental.apply_file_changes([ WorkspaceFileChange::Set { - path: "main.solc".to_owned(), + path: "main.sol".to_owned(), contents: fixed_main.to_owned(), }, WorkspaceFileChange::Set { - path: "helper.solc".to_owned(), + path: "helper.sol".to_owned(), contents: fixed_helper.to_owned(), }, ]); let fresh = workspace_from_files( - &[("main.solc", fixed_main), ("helper.solc", fixed_helper)], - "main.solc", + &[("main.sol", fixed_main), ("helper.sol", fixed_helper)], + "main.sol", ); assert_eq!(incremental.diagnostics(), fresh.diagnostics()); assert!(incremental.diagnostics().is_empty()); @@ -1327,19 +1347,19 @@ mod tests { let workspace = workspace_from_files( &[ ( - "main.solc", - "import a.{fromA};\nfunction main() -> word { return fromA(); }\n", + "main.sol", + "import {fromA} from a;\nfunction main() returns (word) { return fromA(); }\n", ), ( - "a.solc", - "import b.{value};\nfunction fromA() -> word { return value(); }\nexport { fromA };\n", + "a.sol", + "import {value} from b;\nfunction fromA() returns (word) { return value(); }\nexport { fromA };\n", ), ( - "b.solc", - "function value() -> word { return 42; }\nexport { value };\n", + "b.sol", + "function value() returns (word) { return 42; }\nexport { value };\n", ), ], - "main.solc", + "main.sol", ); assert!(workspace.diagnostics().is_empty()); } @@ -1353,14 +1373,14 @@ mod tests { assert_eq!( names, BTreeSet::from([ - "ABIGeneric.solc", - "Generic.solc", - "StorageGeneric.solc", - "dispatch.solc", - "eip712.solc", - "eip7951.solc", - "opcodes.solc", - "std.solc", + "ABIGeneric.sol", + "Generic.sol", + "StorageGeneric.sol", + "dispatch.sol", + "eip712.sol", + "eip7951.sol", + "opcodes.sol", + "std.sol", ]) ); assert!(STD_FILES.iter().all(|(_, contents)| !contents.is_empty())); @@ -1370,18 +1390,18 @@ mod tests { fn virtual_file_urls_encode_special_path_characters() { let mut workspace = Workspace::new(); workspace.set_file( - "nested/数 学#1.solc", - "function value() -> word { return 1; }\n".to_owned(), + "nested/数 学#1.sol", + "function value() returns (word) { return 1; }\n".to_owned(), ); let file = workspace .db() - .source_file("/main/nested/数 学#1.solc") + .source_file("/main/nested/数 学#1.sol") .expect("virtual source file"); assert_eq!( file.url(workspace.db()).as_str(), - "file:///main/nested/%E6%95%B0%20%E5%AD%A6%231.solc" + "file:///main/nested/%E6%95%B0%20%E5%AD%A6%231.sol" ); } @@ -1392,11 +1412,11 @@ mod tests { let mut source = String::new(); for index in 0..256 { source.push_str(&format!( - "function value{index}(x: word) -> word {{ return x; }}\n" + "function value{index}(x: word) returns (word) {{ return x; }}\n" )); } source.push_str(&format!( - "function main() -> word {{ return value255({revision}); }}\n" + "function main() returns (word) {{ return value255({revision}); }}\n" )); source } @@ -1404,7 +1424,7 @@ mod tests { let mut workspace = workspace_with_main(&source(0)); assert!(workspace.diagnostics().is_empty()); for revision in 1..=64 { - workspace.set_file("main.solc", source(revision)); + workspace.set_file("main.sol", source(revision)); assert!(workspace.diagnostics().is_empty(), "revision {revision}"); } } From 20f1c0a0374504cf1558b2ee0e4c228d20e03298 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 103/110] Switch the compiler and fixtures to canonical syntax: wasm Co-authored-by: Codex --- crates/wasm/src/lib.rs | 107 +++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/crates/wasm/src/lib.rs b/crates/wasm/src/lib.rs index 062bd9fd..2c4ab9ba 100644 --- a/crates/wasm/src/lib.rs +++ b/crates/wasm/src/lib.rs @@ -116,8 +116,8 @@ pub(crate) struct Label { #[derive(Clone, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct Pos { - /// UI-facing source path. `/main/foo.solc` is `foo.solc`, `/std/std.solc` - /// is `std:std.solc`, and `/ext/lib/foo.solc` is `ext:lib/foo.solc`. + /// UI-facing source path. `/main/foo.sol` is `foo.sol`, `/std/std.sol` + /// is `std:std.sol`, and `/ext/lib/foo.sol` is `ext:lib/foo.sol`. pub(crate) file: String, pub(crate) start_byte: u32, pub(crate) end_byte: u32, @@ -136,6 +136,27 @@ struct FileOutput { /// Compiles already-deserialized input. Tests use this native helper directly. pub(crate) fn compile_impl(input: CompileInput) -> CompileResult { + if Path::new(&input.entry) + .extension() + .and_then(|extension| extension.to_str()) + != Some("sol") + { + return CompileResult { + success: false, + diagnostics: vec![message_diag( + DiagnosticSeverity::Error, + format!( + "entry file `{}` must use the `.sol` source extension", + input.entry + ), + )], + hull: None, + yul: None, + sonatina: None, + abi: None, + }; + } + let mut workspace = Workspace::new(); workspace.apply_file_changes( input @@ -508,22 +529,45 @@ mod tests { fn input(source: &str, options: Options) -> CompileInput { CompileInput { files: vec![FileInput { - path: "main.solc".to_owned(), + path: "main.sol".to_owned(), content: source.to_owned(), }], - entry: "main.solc".to_owned(), + entry: "main.sol".to_owned(), options, } } + #[test] + fn compile_accepts_only_sol_entry_files() { + let valid = compile_impl(input("function main() {}\n", Options::default())); + assert!(valid.success); + assert!(valid.diagnostics.is_empty()); + + let invalid = compile_impl(CompileInput { + files: vec![FileInput { + path: "main.solc".to_owned(), + content: "function main() {}\n".to_owned(), + }], + entry: "main.solc".to_owned(), + options: Options::default(), + }); + assert!(!invalid.success); + assert!(invalid.diagnostics.iter().any(|diagnostic| { + diagnostic.is_error() + && diagnostic + .message + .contains("entry file `main.solc` must use the `.sol` source extension") + })); + } + #[test] fn clean_program_emits_all_playground_outputs() { let result = compile_impl(input( concat!( - "import std.{*};\n", - "import std.dispatch.{*};\n", + "import * from std;\n", + "import * from std.dispatch;\n", "contract Main {\n", - " public function answer() -> uint256 {\n", + " function answer() public returns (uint256) {\n", " return uint256(42);\n", " }\n", "}\n", @@ -557,7 +601,7 @@ mod tests { #[test] fn sonatina_only_runs_the_shared_hull_pipeline() { let result = compile_impl(input( - "contract Main {\n public function main() -> word {\n return 1;\n }\n}\n", + "contract Main {\n function main() public returns (word) {\n return 1;\n }\n}\n", Options { emit_hull: false, emit_yul: false, @@ -581,8 +625,8 @@ mod tests { fn combined_artifacts_follow_cli_fail_fast_order() { let result = compile_impl(input( concat!( - "contract A { public function main() -> word { return 1; } }\n", - "contract B { public function main() -> word { return 2; } }\n", + "contract A { function main() public returns (word) { return 1; } }\n", + "contract B { function main() public returns (word) { return 2; } }\n", ), Options { emit_hull: false, @@ -613,10 +657,10 @@ mod tests { fn abi_only_emits_contract_json() { let result = compile_impl(input( concat!( - "import std.{*};\n", - "import std.dispatch.{*};\n", + "import * from std;\n", + "import * from std.dispatch;\n", "contract Main {\n", - " public function answer() -> uint256 {\n", + " function answer() public returns (uint256) {\n", " return uint256(42);\n", " }\n", "}\n", @@ -644,22 +688,24 @@ mod tests { let result = compile_impl(CompileInput { files: vec![ FileInput { - path: "main.solc".to_owned(), - content: "import a; import b; function main() -> word { return 0; }\n" + path: "main.sol".to_owned(), + content: "import a; import b; function main() returns (word) { return 0; }\n" .to_owned(), }, FileInput { - path: "a.solc".to_owned(), - content: "contract Token { public function main() -> word { return 1; } }\n" - .to_owned(), + path: "a.sol".to_owned(), + content: + "contract Token { function main() public returns (word) { return 1; } }\n" + .to_owned(), }, FileInput { - path: "b.solc".to_owned(), - content: "contract Token { public function main() -> word { return 2; } }\n" - .to_owned(), + path: "b.sol".to_owned(), + content: + "contract Token { function main() public returns (word) { return 2; } }\n" + .to_owned(), }, ], - entry: "main.solc".to_owned(), + entry: "main.sol".to_owned(), options: Options { emit_hull: false, emit_yul: false, @@ -686,15 +732,16 @@ mod tests { let mut workspace = Workspace::new(); workspace.set_external_file( "pkg", - "token.solc", - "contract ExternalToken { public function main() -> word { return 7; } }\n".to_owned(), + "token.sol", + "contract ExternalToken { function main() public returns (word) { return 7; } }\n" + .to_owned(), ); workspace.set_file( - "main.solc", - "import @pkg.token; contract Local { public function main() -> word { return 1; } }\n" + "main.sol", + "import @pkg.token; contract Local { function main() public returns (word) { return 1; } }\n" .to_owned(), ); - workspace.set_entry("main.solc"); + workspace.set_entry("main.sol"); assert!(workspace.diagnostics().is_empty()); let entry = workspace.entry_module().expect("entry module"); @@ -722,9 +769,9 @@ mod tests { fn backend_diagnostic_uses_shared_vfs_conversion() { let result = compile_impl(input( concat!( - "import std.{string};\n", + "import {string} from std;\n", "contract Main {\n", - " public function main() -> string { return \"nope\"; }\n", + " function main() public returns (string) { return \"nope\"; }\n", "}\n", ), Options { @@ -752,7 +799,7 @@ mod tests { #[test] fn bad_program_reports_position_and_skips_backend() { let result = compile_impl(input( - "function f() -> word {\n return true;\n}\n", + "function f() returns (word) {\n return true;\n}\n", Options { emit_hull: true, emit_yul: true, From e1cedb9381d12be9337fecab75756e5a138a49a6 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 104/110] Switch the compiler and fixtures to canonical syntax: yul Co-authored-by: Codex --- crates/yul/tests/e2e.rs | 4 +- crates/yul/tests/snapshots.rs | 133 +++++++++--------- .../snapshots__dispatch_basic_shape.snap | 1 - .../tests/snapshots/snapshots__doc_id.snap | 1 - 4 files changed, 66 insertions(+), 73 deletions(-) diff --git a/crates/yul/tests/e2e.rs b/crates/yul/tests/e2e.rs index 6ad3bf42..47bb217e 100644 --- a/crates/yul/tests/e2e.rs +++ b/crates/yul/tests/e2e.rs @@ -35,7 +35,7 @@ static SOLC_FOR_E2E: OnceLock, E2eFailure>> = OnceLock::n #[dir_test( dir: "$CARGO_MANIFEST_DIR/../../tests/e2e", - glob: "**/main.solc" + glob: "**/main.sol" )] fn yul_evm_e2e_fixture(fixture: Fixture<&str>) { if !e2e_enabled() { @@ -165,7 +165,7 @@ fn resolve_fixture_directives( } Item::InstanceDef(instance) => { for function in instance.methods(db) { - reject_non_dispatch_directives(db, *function, "instance method")?; + reject_non_dispatch_directives(db, *function, "impl method")?; } } Item::ContractDef(contract) => { diff --git a/crates/yul/tests/snapshots.rs b/crates/yul/tests/snapshots.rs index 44254c68..e720bf85 100644 --- a/crates/yul/tests/snapshots.rs +++ b/crates/yul/tests/snapshots.rs @@ -109,11 +109,11 @@ fn doc_id_yul_snapshot() { render_source( "doc_id", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract IdDoc { - public function id(x : uint256) -> uint256 { + function id(x : uint256) public returns (uint256) { return x; } } @@ -130,16 +130,15 @@ fn doc_option_maybe_yul_snapshot() { "doc_option_maybe", r#" contract OptionDoc { - data Option(a) = None | Some(a); + enum Option {None , Some(a)} - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n : word, o : Option) returns (word) { + match (o) { + case Option.None { return n; } +case Option.Some(x) { return x; }} } - public function main() -> word { + function main() public returns (word) { return maybe(0, Option.Some(42)); } } @@ -151,14 +150,14 @@ contract OptionDoc { #[test] fn doc_color_yul_snapshot() { let fixture = - repo_root().join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.solc"); + repo_root().join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol"); insta::assert_snapshot!("doc_color_yul_snapshot", render_fixture(&fixture)); } #[test] fn doc_add1_yul_snapshot() { let fixture = - repo_root().join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.solc"); + repo_root().join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol"); insta::assert_snapshot!("doc_add1_yul_snapshot", render_fixture(&fixture)); } @@ -169,15 +168,15 @@ fn dispatch_basic_shape_yul_snapshot() { render_source( "dispatch_basic_shape", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract DispatchBasicShape { - public function id(x : uint256) -> uint256 { + function id(x : uint256) public returns (uint256) { return x; } - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } } @@ -188,7 +187,7 @@ contract DispatchBasicShape { #[test] fn data_type_storage_full_yul_snapshot() { - let fixture = repo_root().join("crates/yul/tests/fixtures/data_type_storage_full/main.solc"); + let fixture = repo_root().join("crates/yul/tests/fixtures/data_type_storage_full/main.sol"); insta::assert_snapshot!("data_type_storage_full", render_fixture(&fixture)); } @@ -549,7 +548,7 @@ fn assembly_let_shadowing_does_not_substitute_shadowed_name() { "assembly_let_shadowing", r#" contract AssemblyLetShadowing { - public function main() -> word { + function main() public returns (word) { let x : bool = false; let r : word = 0; assembly { @@ -585,7 +584,7 @@ fn assembly_nested_block_shadowing_is_block_local() { "assembly_nested_block_shadowing", r#" contract AssemblyNestedBlockShadowing { - public function main() -> word { + function main() public returns (word) { let x : bool = false; let r : word = 0; assembly { @@ -619,7 +618,7 @@ fn assembly_function_params_and_returns_shadow_hull_locals() { "assembly_function_shadowing", r#" contract AssemblyFunctionShadowing { - public function main() -> word { + function main() public returns (word) { let x : bool = false; let y : bool = true; let r : word = 0; @@ -666,7 +665,7 @@ fn assembly_function_names_are_hoisted_for_forward_and_mutual_calls() { "assembly_function_mutual_recursion", r#" contract AssemblyFunctionMutualRecursion { - public function main() -> word { + function main() public returns (word) { let result : word; assembly { result := even(6) @@ -710,7 +709,7 @@ contract AssemblyFunctionMutualRecursion { #[test] fn polymorphic_inline_yul_terminators_render_in_value_functions() { let fixture = - repo_root().join("crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.solc"); + repo_root().join("crates/hir-ty/tests/fixtures/ok/yul_polymorphic_terminators/main.sol"); let yul = render_fixture(&fixture); for terminator in ["stop()", "invalid()", "selfdestruct(", "revert("] { @@ -754,7 +753,7 @@ fn object_less_source_calls_its_mangled_main_before_returning() { let yul = render_source( "object_less_main", r#" -function main() -> word { return 42; } +function main() returns (word) { return 42; } "#, ); @@ -772,15 +771,14 @@ fn value_equal_literal_spellings_emit_one_yul_case() { "equal_literal_spellings", r#" contract C { - function pick(x : word) -> word { - match x { - | 0x2a => return 111; - | 0042 => return 222; - | _ => return 333; - } + function pick(x : word) returns (word) { + match (x) { + case 0x2a { return 111; } +case 0042 { return 222; } +default { return 333; }} } - function main() -> word { + function main() returns (word) { let x : word = 0; assembly { x := calldataload(0) } return pick(x); @@ -811,7 +809,7 @@ fn hygienic_names_canonical_literals_and_break_validation() { "reserved_add_name", r#" contract ReservedAddName { - public function main() -> word { + function main() public returns (word) { let add : word = 1; return add; } @@ -825,7 +823,7 @@ contract ReservedAddName { "asm_shadow", r#" contract AsmShadow { - public function main() -> word { + function main() public returns (word) { let x : bool = false; let r : word = 0; assembly { @@ -844,7 +842,7 @@ contract AsmShadow { "leading_zero_decimal", r#" contract LeadingZeroDecimal { - public function main() -> word { + function main() public returns (word) { return 01; } } @@ -871,7 +869,7 @@ contract LeadingZeroDecimal { "asm_break_outside_loop", r#" contract BadBreak { - public function main() -> word { + function main() public returns (word) { assembly { break } return 0; } @@ -887,7 +885,7 @@ contract BadBreak { "asm_continue_post", r#" contract BadContinuePost { - public function main() -> word { + function main() public returns (word) { assembly { for {} 1 { continue } {} } return 0; } @@ -904,11 +902,11 @@ contract BadContinuePost { fn strict_assembly_artifact_requires_one_top_level_object_or_selection() { let multi_contract = r#" contract A { - public function main() -> word { return 1; } + function main() public returns (word) { return 1; } } contract B { - public function main() -> word { return 2; } + function main() public returns (word) { return 2; } } "#; let error = render_source_error("multi_contract_yul", multi_contract); @@ -936,11 +934,11 @@ fn solc_strict_assembly_compiles_snapshots_and_repros_when_present() { let fixtures = repo_root().join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases"); cases.push(( "repro_for_body_shadow".to_owned(), - render_fixture(&fixtures.join("for-body-shadow.solc")), + render_fixture(&fixtures.join("for-body-shadow.sol")), )); cases.push(( "repro_for_init_shadow".to_owned(), - render_fixture(&fixtures.join("for-init-shadow.solc")), + render_fixture(&fixtures.join("for-init-shadow.sol")), )); cases.push(( "repro_reserved_add_name".to_owned(), @@ -948,7 +946,7 @@ fn solc_strict_assembly_compiles_snapshots_and_repros_when_present() { "repro_reserved_add_name", r#" contract C { - public function main() -> word { + function main() public returns (word) { let add : word = 1; return add; } @@ -962,7 +960,7 @@ contract C { "repro_decimal_leading_zero", r#" contract C { - public function main() -> word { + function main() public returns (word) { return 01; } } @@ -975,7 +973,7 @@ contract C { "repro_assembly_shadow_lvalue", r#" contract C { - public function main() -> word { + function main() public returns (word) { let x : bool = false; let r : word = 0; assembly { let x := 1 r := x } @@ -996,21 +994,19 @@ fn nested_pair_tail_binding_preserves_the_tail_product() { let yul = render_source( "nested_pair_tail_binding", r#" -forall a b . function nestedSnd(p: (a, b)) -> b { +function nestedSnd(p: (a, b)) returns (b) { assembly { mstore(0, 0) } - match p { - | (_, tail) => return tail; - } + match (p) { + case (_, tail) { return tail; }} } contract C { - public function main() -> word { + function main() public returns (word) { let x: word; assembly { x := sload(0) } let tail = nestedSnd((x, (x, x))); - match tail { - | (head, _) => return head; - } + match (tail) { + case (head, _) { return head; }} } } "#, @@ -1071,7 +1067,7 @@ fn specialize_src(name: &str, src: &str) -> (&'static TestDb, SpecializeOutput<' db.module_tree = Some(tree); db.module_fs_snapshot = Some(fs_snapshot); - let path = main_root.join(format!("{name}.solc")); + let path = main_root.join(format!("{name}.sol")); let key = module_key_for_path(LibraryId::Main, &main_root, &path) .expect("inline source under virtual main root"); let file = SourceFile::new( @@ -1103,7 +1099,7 @@ fn yul_function<'a>(yul: &'a str, name: &str) -> &'a str { fn test_span<'db>(db: &'db TestDb) -> Span<'db> { let file = SourceFile::new( db, - "memory:///yul_snapshots_hull.solc" + "memory:///yul_snapshots_hull.sol" .parse() .expect("valid URL"), Some(String::new()), @@ -1168,7 +1164,7 @@ fn collect_module_fs_snapshot( }; for entry in entries.flatten() { let path = entry.path(); - if path.extension().and_then(|extension| extension.to_str()) == Some("solc") { + if path.extension().and_then(|extension| extension.to_str()) == Some("sol") { if path.is_file() { existing_files.insert(path.clone()); } @@ -1298,11 +1294,11 @@ fn snapshot_yul_cases() -> Vec<(String, String)> { render_source( "doc_id", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract IdDoc { - public function id(x : uint256) -> uint256 { + function id(x : uint256) public returns (uint256) { return x; } } @@ -1315,16 +1311,15 @@ contract IdDoc { "doc_option_maybe", r#" contract OptionDoc { - data Option(a) = None | Some(a); + enum Option {None , Some(a)} - function maybe(n : word, o : Option(word)) -> word { - match o { - | Option.None => return n; - | Option.Some(x) => return x; - } + function maybe(n : word, o : Option) returns (word) { + match (o) { + case Option.None { return n; } +case Option.Some(x) { return x; }} } - public function main() -> word { + function main() public returns (word) { return maybe(0, Option.Some(42)); } } @@ -1334,13 +1329,13 @@ contract OptionDoc { ( "snapshot_doc_color".to_owned(), render_fixture( - &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.solc"), + &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/spec/047rgb.sol"), ), ), ( "snapshot_doc_add1".to_owned(), render_fixture( - &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.solc"), + &repo.join("crates/parser/tests/fixtures/corpus/ok/test/examples/cases/Add1.sol"), ), ), ( @@ -1348,15 +1343,15 @@ contract OptionDoc { render_source( "dispatch_basic_shape", r#" -import std.{*}; -import std.dispatch.{*}; +import * from std; +import * from std.dispatch; contract DispatchBasicShape { - public function id(x : uint256) -> uint256 { + function id(x : uint256) public returns (uint256) { return x; } - public function answer() -> uint256 { + function answer() public returns (uint256) { return uint256(42); } } diff --git a/crates/yul/tests/snapshots/snapshots__dispatch_basic_shape.snap b/crates/yul/tests/snapshots/snapshots__dispatch_basic_shape.snap index b8c63bc5..e0b22d43 100644 --- a/crates/yul/tests/snapshots/snapshots__dispatch_basic_shape.snap +++ b/crates/yul/tests/snapshots/snapshots__dispatch_basic_shape.snap @@ -485,7 +485,6 @@ object "DispatchBasicShapeDeploy" { } function usr$std_set_free_memory_d65c817cd(src$loc_103) { usr$opcodes_mstore_d7415bc7e(0x40, src$loc_103) - leave } usr$dispatch_basic_shape_DispatchBasicShape_main_d302fef00() } diff --git a/crates/yul/tests/snapshots/snapshots__doc_id.snap b/crates/yul/tests/snapshots/snapshots__doc_id.snap index d7d910f1..c0f2085a 100644 --- a/crates/yul/tests/snapshots/snapshots__doc_id.snap +++ b/crates/yul/tests/snapshots/snapshots__doc_id.snap @@ -422,7 +422,6 @@ object "IdDocDeploy" { } function usr$std_set_free_memory_d65c817cd(src$loc_98) { usr$opcodes_mstore_d7415bc7e(0x40, src$loc_98) - leave } usr$doc_id_IdDoc_main_d45c46589() } From bb020c18c4dcef2539de9ba1769149dc8e8d2e5f Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:17 +0900 Subject: [PATCH 105/110] Switch the compiler and fixtures to canonical syntax: yul fixtures Co-authored-by: Codex --- .../fixtures/data_type_storage_full/main.sol | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/crates/yul/tests/fixtures/data_type_storage_full/main.sol b/crates/yul/tests/fixtures/data_type_storage_full/main.sol index ec9e8492..f08e33e1 100644 --- a/crates/yul/tests/fixtures/data_type_storage_full/main.sol +++ b/crates/yul/tests/fixtures/data_type_storage_full/main.sol @@ -1,25 +1,27 @@ -import std.{*}; +import * from std; -data Box = Box(word); +enum Box { Box(word) } -instance Box : StorageType { - function load(ptr : word) -> Box { - return Box(StorageType.load(ptr):word); +impl StorageType { + function load(ptr: word) returns (Box) { + return Box(StorageType.load(ptr)); } - function store(ptr : word, value : Box) -> () { - match value { - | Box(inner) => StorageType.store(ptr, inner); - } + function store(ptr: word, value: Box) { + match (value) { +case Box(inner) { +StorageType.store(ptr, inner); +} +} } } -instance storage(Box) : CanStore(Box) { - function load(ptr : storage(Box)) -> Box { - return StorageType.load(Typedef.rep(ptr)):Box; +impl CanStore, Box> { + function load(ptr: storage) returns (Box) { + return StorageType.load(Typedef.rep(ptr)); } - function store(ptr : storage(Box), value : Box) -> () { + function store(ptr: storage, value: Box) { StorageType.store(Typedef.rep(ptr), value); } } @@ -27,9 +29,11 @@ instance storage(Box) : CanStore(Box) { contract DataTypeStorageFull { box : Box; - public function main() -> word { - match box { - | Box(inner) => return inner; - } + function main() public returns (word) { + match (box) { +case Box(inner) { +return inner; +} +} } } From 78cc952c0e8206d2e7969235e64c7807c4815647 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Thu, 13 Aug 2026 20:17:37 +0900 Subject: [PATCH 106/110] Update language tooling for canonical Core sources Co-authored-by: Codex --- benchmarks/README.md | 2 +- benchmarks/tofu/materialize.py | 14 +++--- editors/README.md | 4 +- editors/emacs-solcore/README.md | 12 ++--- editors/emacs-solcore/solcore-mode.el | 26 ++++++----- editors/vim-solcore/README.md | 6 +-- editors/vim-solcore/ftdetect/solcore.vim | 2 +- editors/vim-solcore/ftplugin/solcore.vim | 2 +- editors/vim-solcore/syntax/solcore.vim | 12 +++-- editors/vscode-solcore/README.md | 4 +- editors/vscode-solcore/extension.js | 2 +- editors/vscode-solcore/package.json | 6 +-- .../syntaxes/solcore.tmLanguage.json | 14 +++--- fuzz/README.md | 2 +- fuzz/src/lib.rs | 12 ++--- playground/README.md | 2 +- playground/src/components/FileExplorer.tsx | 2 +- playground/src/components/TopBar.tsx | 4 +- playground/src/examples/index.ts | 36 +++++++-------- playground/src/languageClient/README.md | 2 +- .../providers/hoverContent.test.mjs | 4 +- .../providers/workspaceEdit.test.mjs | 6 +-- playground/src/monaco/solc-language.ts | 45 ++++++++++++++----- playground/src/store/workspace.ts | 8 ++-- scripts/bench-compile.sh | 8 ++-- scripts/check-compile-performance.sh | 12 ++--- worker/README.md | 2 +- 27 files changed, 141 insertions(+), 110 deletions(-) diff --git a/benchmarks/README.md b/benchmarks/README.md index 16e468a6..79972180 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -10,7 +10,7 @@ The fixed cases cover distinct compiler workloads: | Case | Fixture | Purpose | | --- | --- | --- | -| `std-free` | `SingleFun.solc` | Small frontend run without reachable std/runtime | +| `std-free` | `SingleFun.sol` | Small frontend run without reachable std/runtime | | `dispatch-small` | `tests/e2e/022add` | Small contract with compiler-owned dispatch | | `erc20-large` | `tests/e2e/128minierc20` | Larger std- and storage-heavy contract | | `multi-file` | `tests/e2e/ltimp` | Main module plus a local import | diff --git a/benchmarks/tofu/materialize.py b/benchmarks/tofu/materialize.py index 0e16b18d..3aaf730b 100644 --- a/benchmarks/tofu/materialize.py +++ b/benchmarks/tofu/materialize.py @@ -11,18 +11,18 @@ REPOSITORY = HERE.parents[1] CASES = { "std-free": { - "main.solc": REPOSITORY - / "crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.solc", + "main.sol": REPOSITORY + / "crates/parser/tests/fixtures/corpus/ok/test/examples/cases/SingleFun.sol", }, "dispatch-small": { - "main.solc": REPOSITORY / "tests/e2e/022add/main.solc", + "main.sol": REPOSITORY / "tests/e2e/022add/main.sol", }, "erc20-large": { - "main.solc": REPOSITORY / "tests/e2e/128minierc20/main.solc", + "main.sol": REPOSITORY / "tests/e2e/128minierc20/main.sol", }, "multi-file": { - "main.solc": REPOSITORY / "tests/e2e/ltimp/main.solc", - "ltproxy.solc": REPOSITORY / "tests/e2e/ltimp/ltproxy.solc", + "main.sol": REPOSITORY / "tests/e2e/ltimp/main.sol", + "ltproxy.sol": REPOSITORY / "tests/e2e/ltimp/ltproxy.sol", }, } @@ -36,7 +36,7 @@ def standard_json(sources): }, "settings": { "solcore": { - "entrypoint": "main.solc", + "entrypoint": "main.sol", "stage": "hull", }, "outputSelection": {"*": {"*": []}}, diff --git a/editors/README.md b/editors/README.md index 32cf5920..cd2c303a 100644 --- a/editors/README.md +++ b/editors/README.md @@ -25,7 +25,7 @@ Every editor integration can start the same stdio server. By default they use `solcore-lsp` on `PATH`. VS Code and Neovim also expose editor-specific command overrides for local development. -On initialization, the native server indexes `.solc` files below every +On initialization, the native server indexes `.sol` files below every workspace folder. Each root has an isolated compiler namespace, and dynamic workspace-folder and watched-file changes keep unopened import targets and workspace symbols up to date. @@ -44,5 +44,5 @@ smart selection ranges, semantic tokens, and inlay hints. ## Packages - `vscode-solcore`: VS Code extension with TextMate highlighting and LSP client. -- `vim-solcore`: Vim/Neovim package with `.solc` highlighting and LSP setup. +- `vim-solcore`: Vim/Neovim package with `.sol` highlighting and LSP setup. - `emacs-solcore`: Emacs major mode plus eglot/lsp-mode setup. diff --git a/editors/emacs-solcore/README.md b/editors/emacs-solcore/README.md index f95fac70..a03c69b1 100644 --- a/editors/emacs-solcore/README.md +++ b/editors/emacs-solcore/README.md @@ -1,9 +1,9 @@ # Solcore Emacs mode -This directory contains Emacs support for Solcore `.solc` files: +This directory contains Emacs support for Solcore `.sol` files: - `solcore-mode.el` provides a `prog-mode`-derived major mode. -- `.solc` files are added to `auto-mode-alist`. +- `.sol` files are added to `auto-mode-alist`. - Syntax highlighting uses Emacs font-lock for Solcore keywords, declarations, primitive types, constants, numbers, operators, and function calls. - Optional LSP registration is provided for both `lsp-mode` and Eglot. @@ -22,7 +22,7 @@ With `use-package`: ```elisp (use-package solcore-mode :load-path "/path/to/solcore-rs/editors/emacs-solcore" - :mode ("\\.solc\\'" . solcore-mode)) + :mode ("\\.sol\\'" . solcore-mode)) ``` ## LSP server command @@ -63,7 +63,7 @@ Enable it with a hook: (use-package solcore-mode :load-path "/path/to/solcore-rs/editors/emacs-solcore" - :mode ("\\.solc\\'" . solcore-mode) + :mode ("\\.sol\\'" . solcore-mode) :hook (solcore-mode . lsp-deferred)) ``` @@ -78,7 +78,7 @@ with a hook: (use-package solcore-mode :load-path "/path/to/solcore-rs/editors/emacs-solcore" - :mode ("\\.solc\\'" . solcore-mode)) + :mode ("\\.sol\\'" . solcore-mode)) ``` For non-`use-package` setups: @@ -91,7 +91,7 @@ For non-`use-package` setups: ## Manual checks -Open any `.solc` file and run: +Open any `.sol` file and run: ```elisp M-x solcore-mode diff --git a/editors/emacs-solcore/solcore-mode.el b/editors/emacs-solcore/solcore-mode.el index 338369ba..e9ae1467 100644 --- a/editors/emacs-solcore/solcore-mode.el +++ b/editors/emacs-solcore/solcore-mode.el @@ -11,7 +11,7 @@ ;;; Commentary: ;; Major mode, font-lock highlighting, and optional LSP client registration for -;; Solcore `.solc' files. +;; Solcore `.sol' files. ;; ;; The LSP server command is resolved from SOLCORE_LSP_SERVER when that ;; environment variable is non-empty. Otherwise `solcore-lsp-server-command' @@ -55,19 +55,21 @@ program name followed by arguments." "Characters that keep a Solcore identifier or keyword going.") (defconst solcore--control-keywords - '("if" "else" "for" "switch" "case" "default" "match" "return" + '("if" "else" "for" "while" "switch" "case" "default" "match" "return" "leave" "continue" "break")) (defconst solcore--declaration-keywords - '("contract" "import" "export" "as" "let" "data" "class" "forall" - "instance" "type" "function" "constructor" "fallback" "assembly" - "pragma" "lam")) + '("contract" "import" "from" "hiding" "export" "as" "let" "enum" "trait" + "impl" "where" "type" "function" "returns" "constructor" "fallback" + "assembly" "pragma" "lam" "comptime" "derive")) (defconst solcore--modifier-keywords '("public" "payable")) (defconst solcore--primitive-types - '("word" "bool" "unit")) + '("word" "bool" "string" "integer" "pair" "sum" "uint256" "address" + "byte" "bytes" "bytes4" "bytes32" "memory" "storage" "calldata" + "returndata" "mapping" "array")) (defconst solcore--constants '("true" "false" "_")) @@ -95,7 +97,7 @@ left to the caller so declaration patterns can consume whitespace once." "\\s-+\\(" solcore--identifier-re "\\)") (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t)) - (,(concat (solcore--keyword-prefix-regexp '("data" "class" "type")) + (,(concat (solcore--keyword-prefix-regexp '("enum" "trait" "type")) "\\s-+\\(" solcore--identifier-re "\\)") (1 font-lock-keyword-face) (2 font-lock-type-face nil t)) @@ -128,9 +130,9 @@ left to the caller so declaration patterns can consume whitespace once." "\\(?:\\'\\|[^[:alpha:][:digit:]_]\\)") 1 font-lock-constant-face) (,(concat "\\(" - (regexp-opt '(":=" "+=" "-=" "^=" "&=" "|=" "%=" "->" "=>" + (regexp-opt '(":=" "+=" "-=" "*=" "/=" "^=" "&=" "|=" "%=" "~=" "->" "=>" "==" "!=" ">=" "<=" "&&" "||")) - "\\|[+*/%!?=<>|&^@-]\\)") + "\\|[+*/%!?=<>|&^@~-]\\)") 1 font-lock-builtin-face)) "Font-lock rules for `solcore-mode'.") @@ -148,7 +150,7 @@ left to the caller so declaration patterns can consume whitespace once." (defvar solcore-imenu-generic-expression `((nil ,(concat "^\\s-*function\\s-+\\(" solcore--identifier-re "\\)") 1) ("Contracts" ,(concat "^\\s-*contract\\s-+\\(" solcore--identifier-re "\\)") 1) - ("Types" ,(concat "^\\s-*\\(?:data\\|class\\|type\\)\\s-+\\(" + ("Types" ,(concat "^\\s-*\\(?:enum\\|trait\\|type\\)\\s-+\\(" solcore--identifier-re "\\)") 1)) "Imenu expressions for `solcore-mode'.") @@ -193,7 +195,7 @@ left to the caller so declaration patterns can consume whitespace once." ;;;###autoload (define-derived-mode solcore-mode prog-mode "Solcore" - "Major mode for editing Solcore `.solc' files." + "Major mode for editing Solcore `.sol' files." :syntax-table solcore-mode-syntax-table (setq-local font-lock-defaults '(solcore-font-lock-keywords)) (setq-local comment-start "// ") @@ -207,7 +209,7 @@ left to the caller so declaration patterns can consume whitespace once." (append "{}();," electric-indent-chars))) ;;;###autoload -(add-to-list 'auto-mode-alist '("\\.solc\\'" . solcore-mode)) +(add-to-list 'auto-mode-alist '("\\.sol\\'" . solcore-mode)) (defvar lsp-language-id-configuration) (declare-function lsp-activate-on "lsp-mode") diff --git a/editors/vim-solcore/README.md b/editors/vim-solcore/README.md index d6ddbe72..ac1fcc80 100644 --- a/editors/vim-solcore/README.md +++ b/editors/vim-solcore/README.md @@ -1,8 +1,8 @@ # Solcore Vim/Neovim support -This directory provides Vim runtime files for Solcore `.solc` files: +This directory provides Vim runtime files for Solcore `.sol` files: -- `ftdetect/solcore.vim` detects `*.solc` as the `solcore` filetype. +- `ftdetect/solcore.vim` detects `*.sol` as the `solcore` filetype. - `ftplugin/solcore.vim` configures comments, formatting, suffix lookup, and word movement for Solcore buffers. - `syntax/solcore.vim` provides Vim script syntax highlighting. @@ -21,7 +21,7 @@ Plugin managers can point at this directory as a local plugin. ## Syntax Highlighting -Open any `.solc` file after the runtime path is configured. Vim/Neovim will set +Open any `.sol` file after the runtime path is configured. Vim/Neovim will set `filetype=solcore` and load `syntax/solcore.vim` when syntax highlighting is enabled: diff --git a/editors/vim-solcore/ftdetect/solcore.vim b/editors/vim-solcore/ftdetect/solcore.vim index b09995ff..9f96626e 100644 --- a/editors/vim-solcore/ftdetect/solcore.vim +++ b/editors/vim-solcore/ftdetect/solcore.vim @@ -1,4 +1,4 @@ augroup solcore_filetype autocmd! - autocmd BufNewFile,BufRead *.solc setfiletype solcore + autocmd BufNewFile,BufRead *.sol setfiletype solcore augroup END diff --git a/editors/vim-solcore/ftplugin/solcore.vim b/editors/vim-solcore/ftplugin/solcore.vim index a2fbae01..ac48182d 100644 --- a/editors/vim-solcore/ftplugin/solcore.vim +++ b/editors/vim-solcore/ftplugin/solcore.vim @@ -8,7 +8,7 @@ let b:undo_ftplugin = 'setlocal commentstring< comments< formatoptions< include< setlocal commentstring=//\ %s setlocal comments=s1:/*,mb:*,ex:*/,:// let &l:include = '^\s*\%(import\|export\)\s\+' -setlocal suffixesadd=.solc +setlocal suffixesadd=.sol setlocal formatoptions-=t setlocal formatoptions+=croql diff --git a/editors/vim-solcore/syntax/solcore.vim b/editors/vim-solcore/syntax/solcore.vim index 3fc012f9..f5d63695 100644 --- a/editors/vim-solcore/syntax/solcore.vim +++ b/editors/vim-solcore/syntax/solcore.vim @@ -15,18 +15,18 @@ syntax region solcoreString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=solcoreE syntax match solcoreContractDeclaration #\v(^|[^[:alnum:]_-])contract\s+\zs[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# syntax match solcoreFunctionDeclaration #\v(^|[^[:alnum:]_-])function\s+\zs[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# -syntax match solcoreTypeDeclaration #\v(^|[^[:alnum:]_-])(data|class|type)\s+\zs[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# +syntax match solcoreTypeDeclaration #\v(^|[^[:alnum:]_-])(enum|trait|type)\s+\zs[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# syntax match solcoreVariableDeclaration #\v(^|[^[:alnum:]_-])let\s+\zs[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# syntax match solcorePragmaDeclaration #\v(^|[^[:alnum:]_-])pragma\s+\zs[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# -syntax match solcoreControlKeyword #\v(^|[^[:alnum:]_-])\zs(if|else|for|switch|case|default|match|return|leave|continue|break)\ze([^[:alnum:]_-]|$)# -syntax match solcoreDeclarationKeyword #\v(^|[^[:alnum:]_-])\zs(contract|import|export|as|let|data|class|forall|instance|type|function|constructor|fallback|assembly|pragma|lam)\ze([^[:alnum:]_-]|$)# +syntax match solcoreControlKeyword #\v(^|[^[:alnum:]_-])\zs(if|else|for|while|switch|case|default|match|return|leave|continue|break)\ze([^[:alnum:]_-]|$)# +syntax match solcoreDeclarationKeyword #\v(^|[^[:alnum:]_-])\zs(contract|import|from|hiding|export|as|let|enum|trait|impl|where|type|function|returns|constructor|fallback|assembly|pragma|lam|comptime|derive)\ze([^[:alnum:]_-]|$)# syntax match solcoreStorageModifier #\v(^|[^[:alnum:]_-])\zs(public|payable)\ze([^[:alnum:]_-]|$)# syntax match solcoreBoolean #\v(^|[^[:alnum:]_-])\zs(true|false)\ze([^[:alnum:]_-]|$)# syntax match solcoreWildcard #\v(^|[^[:alnum:]_-])\zs_\ze([^[:alnum:]_-]|$)# -syntax match solcorePrimitiveType #\v(^|[^[:alnum:]_-])\zs(word|bool|unit)\ze([^[:alnum:]_-]|$)# +syntax match solcorePrimitiveType #\v(^|[^[:alnum:]_-])\zs(word|bool|string|integer|pair|sum|uint256|address|byte|bytes|bytes4|bytes32|memory|storage|calldata|returndata|mapping|array)\ze([^[:alnum:]_-]|$)# syntax match solcoreTypeIdentifier #\v(^|[^[:alnum:]_-])\zs[A-Z][[:alnum:]_]*(-[[:alpha:]][[:alnum:]_]*)*# syntax match solcoreHexNumber #\v(^|[^[:alnum:]_])\zs0x[0-9a-fA-F]+\ze([^[:alnum:]_]|$)# @@ -37,10 +37,13 @@ syntax match solcoreFunctionCall #\v[[:alpha:]][[:alnum:]_]*(-[[:alpha:]][[:alnu syntax match solcoreOperator #:=# syntax match solcoreOperator #+=# syntax match solcoreOperator #-=# +syntax match solcoreOperator #\*=# +syntax match solcoreOperator #/=# syntax match solcoreOperator #\^=# syntax match solcoreOperator #&=# syntax match solcoreOperator #|=# syntax match solcoreOperator #%=# +syntax match solcoreOperator #\~=# syntax match solcoreOperator #-># syntax match solcoreOperator #=># syntax match solcoreOperator #==# @@ -60,6 +63,7 @@ syntax match solcoreOperator #%# syntax match solcoreOperator #|# syntax match solcoreOperator #&# syntax match solcoreOperator #\^# +syntax match solcoreOperator #\~# syntax match solcoreOperator #@# syntax match solcoreOperator #?# syntax match solcoreOperator #=# diff --git a/editors/vscode-solcore/README.md b/editors/vscode-solcore/README.md index f67170c4..a7c2c781 100644 --- a/editors/vscode-solcore/README.md +++ b/editors/vscode-solcore/README.md @@ -1,6 +1,6 @@ # Solcore editor grammar -This directory contains a VS Code extension for Solcore `.solc` files. It ships +This directory contains a VS Code extension for Solcore `.sol` files. It ships the reusable TextMate grammar used by the playground and starts the native `solcore-lsp` stdio server when a Solcore file opens. @@ -10,7 +10,7 @@ The package is shaped like a small VS Code extension: - `language-configuration.json` provides comments, brackets, auto-close pairs, indentation, folding markers, and the Solcore word pattern. - `extension.js` starts `solcore-lsp` through `vscode-languageclient`. -- `package.json` wires the `.solc` extension to the grammar, configuration, and +- `package.json` wires the `.sol` extension to the grammar, configuration, and language client. ## Language server diff --git a/editors/vscode-solcore/extension.js b/editors/vscode-solcore/extension.js index ada2707d..0f379739 100644 --- a/editors/vscode-solcore/extension.js +++ b/editors/vscode-solcore/extension.js @@ -104,7 +104,7 @@ function scheduleClientReplacement(outputChannel, fileWatcher) { function activate(context) { const outputChannel = vscode.window.createOutputChannel("Solcore Language Server"); - const fileWatcher = vscode.workspace.createFileSystemWatcher("**/*.solc"); + const fileWatcher = vscode.workspace.createFileSystemWatcher("**/*.sol"); context.subscriptions.push(outputChannel, fileWatcher); void scheduleClientReplacement(outputChannel, fileWatcher); diff --git a/editors/vscode-solcore/package.json b/editors/vscode-solcore/package.json index c62798ae..3f567ad2 100644 --- a/editors/vscode-solcore/package.json +++ b/editors/vscode-solcore/package.json @@ -1,7 +1,7 @@ { "name": "solcore-language", "displayName": "Solcore Language", - "description": "Syntax highlighting and editor configuration for Solcore .solc files.", + "description": "Syntax highlighting and editor configuration for Solcore .sol files.", "version": "0.0.0", "publisher": "solcore", "license": "Apache-2.0", @@ -19,8 +19,8 @@ "languages": [ { "id": "solcore", - "aliases": ["Solcore", "solc"], - "extensions": [".solc"], + "aliases": ["Solcore", "Core Solidity"], + "extensions": [".sol"], "configuration": "./language-configuration.json" } ], diff --git a/editors/vscode-solcore/syntaxes/solcore.tmLanguage.json b/editors/vscode-solcore/syntaxes/solcore.tmLanguage.json index 8ff6730c..28ea171e 100644 --- a/editors/vscode-solcore/syntaxes/solcore.tmLanguage.json +++ b/editors/vscode-solcore/syntaxes/solcore.tmLanguage.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", "name": "Solcore", "scopeName": "source.solcore", - "fileTypes": ["solc"], + "fileTypes": ["sol"], "patterns": [ { "include": "#comments" }, { "include": "#strings" }, @@ -83,7 +83,7 @@ }, { "name": "meta.declaration.type.solcore", - "match": "(? Workspace { let mut workspace = Workspace::new(); - workspace.set_file("main.solc", source.to_owned()); - workspace.set_entry("main.solc"); + workspace.set_file("main.sol", source.to_owned()); + workspace.set_entry("main.sol"); workspace } @@ -107,7 +107,7 @@ impl hir::Db for ParserDb { impl parser::Db for ParserDb {} fn source_file(db: &ParserDb, source: &str) -> SourceFile { - let url = url::Url::parse("memory:///fuzz/main.solc").expect("constant URL is valid"); + let url = url::Url::parse("memory:///fuzz/main.sol").expect("constant URL is valid"); SourceFile::new(db, url, Some(source.to_owned())) } @@ -115,8 +115,8 @@ fn source_file(db: &ParserDb, source: &str) -> SourceFile { mod tests { use super::*; - const ACCEPTED: &[u8] = b"function id(x: word) -> word { return x; }\n"; - const REJECTED: &[u8] = b"function main() -> word { return true; }\n"; + const ACCEPTED: &[u8] = b"function id(x: word) returns (word) { return x; }\n"; + const REJECTED: &[u8] = b"function main() returns (word) { return true; }\n"; #[test] fn every_target_accepts_compiler_diagnostics_normally() { diff --git a/playground/README.md b/playground/README.md index 6e0f95af..da94beb6 100644 --- a/playground/README.md +++ b/playground/README.md @@ -109,7 +109,7 @@ compilation stopped before that backend ran, or (for ABI) the workspace contains ## File key contract -The canonical file key is always a workspace-relative path string, for example `main.solc` or `sub/Foo.solc`. +The canonical file key is always a workspace-relative path string, for example `main.sol` or `sub/Foo.sol`. Use that exact key everywhere: diff --git a/playground/src/components/FileExplorer.tsx b/playground/src/components/FileExplorer.tsx index edbfde97..47203b73 100644 --- a/playground/src/components/FileExplorer.tsx +++ b/playground/src/components/FileExplorer.tsx @@ -16,7 +16,7 @@ export function FileExplorer(): JSX.Element { const problemsByFile = useMemo(() => fileProblemSummaries(result), [result]); const handleAdd = (): void => { - const path = window.prompt("New file path", "untitled.solc"); + const path = window.prompt("New file path", "untitled.sol"); if (path) { createFile(path); } diff --git a/playground/src/components/TopBar.tsx b/playground/src/components/TopBar.tsx index e6aba22f..bf7eb93a 100644 --- a/playground/src/components/TopBar.tsx +++ b/playground/src/components/TopBar.tsx @@ -36,7 +36,7 @@ export function TopBar({ sidebarOpen, onToggleSidebar }: TopBarProps): JSX.Eleme const loadExample = useWorkspaceStore((state) => state.loadExample); const [selectedExample, setSelectedExample] = useState(examples[0]?.id ?? "hello"); const [compilerVersion, setCompilerVersion] = useState(null); - const solcFiles = order.filter((path) => path.endsWith(".solc")); + const solFiles = order.filter((path) => path.endsWith(".sol")); const compileElapsedMs = useCompileElapsed(); const compileIsOutdated = lastCompiledVersion !== null && lastCompiledVersion !== workspaceVersion; @@ -114,7 +114,7 @@ export function TopBar({ sidebarOpen, onToggleSidebar }: TopBarProps): JSX.Eleme Entry