Commit Graph
3838 Commits
Author SHA1 Message Date
Jon Ross-PerkinsandDana Jansens 5da87f43da Split SemIR's formatter class into a more typical h+cpp (#5372)
Trying to make it easier to see the API at a glance. The class has
become really long, and this doesn't fundamentally change that, but
hopefully makes it easier to navigate. The entry structure also had some
cruft that I'm removing.

I'm trying to keep functions in the same order as they currently are.
The delta still looks unhappy because of the churn, but hopefully this
at least explains the ordering in formatter.h. You can try using the
"Add indent" commit on the PR to see a better before-after delta.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-04-29 18:00:07 +00:00
Boaz Brickner 8ba3da9730 Fix "is is" typo (#5382) 2025-04-29 15:32:17 +00:00
Dana Jansens e2984d9fc3 Avoid ToTokenOnly for the AddrSelfIsNonRef diagnostic (#5371)
The location of the diagnostic is an instruction id, not a parse node.
Converting to a parse node to call ToTokenOnly will drop the descendents
of the instruction being diagnosed, but the diagnostic is about the
whole instruction not just the root parse node of whatever instruction
it happens to be.
2025-04-29 15:25:27 +00:00
Geoff Romer 7c85397f8b Stop treating symbolic binding patterns as constants (#5361)
This was originally needed to support constant evaluation of name
expressions, but that's now done in a different way.

This is actually a step toward treating all patterns as constants. The
upcoming change will do so in a slightly different way, and so it will
simplify the review to start from a baseline where patterns are never
constant.
v0.0.0-0.nightly.2025.04.29
2025-04-28 23:45:15 +00:00
Ivan Duranandjosh11b 13a522f608 Document lambdas (#5300)
Moved everything from "Syntax Overview" through "Self and Recursion" in
https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3848.md
to docs/design and added the link to it in README.md

Still needs a short summary for the README

Closes #4898

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2025-04-28 20:13:27 +00:00
Dana JansensandJon Ross-Perkins 315e206ff1 Construct LocId from InstId directly (explicitly) instead of doing lookups when possible (#5355)
Remove calls to `InstStore::GetLocId()` to build a LocId from an InstId
now that they can be constructed directly from the InstId. Most uses of
LocId are just plumbing, so this does not affect them. However places
that want to look inside the LocId do not want to work with the InstId
form. In these places, introduce `InstStore::GetResolvedLocId()` which
converts a LocId (or an InstId as an optimization) into a LocId which is
not backed by an InstId. These locations can be printed (they have a
line and column when they are a NodeId), they can have flags added to
them (`ToImplicit`, `ToTokenOnly`), they can be converted to an
underlying ImportIRInstId, or they may be `None`.

`Dump()` is made to print a resolved location instead of printing the
InstId in the location, since (at least in my experience) the resolved
location is what is interesting in debugging, and this saves manual
`MakeInstId` steps in the debugger every time a location is of interest.

The LocId constructor from InstId is made `explicit` to add clarity to
function calls passing an `inst_id` now directly instead of calling
`context.insts().GetLocId(inst_id)`. To avoid needing to construct
`SemIR::LocId(...)` explicitly in all cases though, the diagnostics code
in Check uses `DiagnosticLocId` as its template parameter which accepts
InstId as well and does the construction of LocId from it.

Because LocId now requires an explicit construction from InstId, any
callers to `AddInst()` functions will have to explicitly convert to
LocId if they had an InstId, but not if they pass a NodeId. To make this
difference clear to callers, we `requires` that the input type can be
converted to LocId. This ensures that passing an InstId results in an
error at the callsite where the InstId is passed, instead of generating
a compiler error when trying to construct `LocIdAndInst` inside
`AddInst()`, which is less clear about what went wrong and doesn't seem
entirely intentional.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-04-28 19:06:24 +00:00
Geoff Romer fafb655d39 Separate pattern types from expression types (#5360)
This is a step toward treating patterns as compile-time constants, so
that we can import them more easily.
2025-04-28 16:54:37 +00:00
Boaz Brickner 84384cf126 Remove exceptions for performance-enum-size (#5370)
This is a followup of `performance-enum-size` disablement in
https://github.com/carbon-language/carbon-lang/pull/5368.
2025-04-28 15:45:54 +00:00
Jon Ross-Perkins 70659fe350 Default FileTest to brief output (#5364)
Trying to make it easier to skim test output for failures. Note this
excludes all the RUN and OK. Failing tests may still be verbose due to
the diff printed, but CHECK-fails should become short.

```
==================== Test output for //toolchain/testing:file_test:
Running tests with 128 thread(s)
...
Done!
[==========] 1272 tests from 1 test suite ran. (688 ms total)
[  PASSED  ] 1272 tests.
================================================================================
```
2025-04-28 15:16:47 +00:00
Boaz Brickner 0647d0e045 Properly link to the discussion in the TODO (#5369)
Followup of https://github.com/carbon-language/carbon-lang/pull/5262.

Part of #5245.
2025-04-28 14:25:45 +00:00
Boaz Brickner 63b14ee245 Disable clang-tidy performance-enum-size (#5368)
See discussion in
https://github.com/carbon-language/carbon-lang/pull/5352 and
https://discord.com/channels/655572317891461132/655578254970716160/1365319438198378577
2025-04-28 12:16:19 +00:00
josh11bandJosh L e52b51e66a Forbid virtual methods with compile-time parameters in the design (#5365)
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
v0.0.0-0.nightly.2025.04.28 v0.0.0-0.nightly.2025.04.27
2025-04-26 03:30:25 +00:00
Jon Ross-Perkins 7181a37997 Make it easier to see test performance (#5363)
Trying to make it easier to see possible bottlenecks.

Disabling hyperthreading seems like a significant reduction in
contention (15% improvement for me). Going down by half again reduces a
contention a little further, but not significantly from what I see. My
thought is that just flipping the flag is going to work best for people
cross-system versus a "divide by four", but welcome to other opinions
there. Note, I'm not digging into the source of the contention here,
just observing it.

Current default on my system (equivalent to `--threads=128`):

```
Running tests with 128 thread(s)
...
Ran 1272 tests in 3955 ms wall time, 397615 ms across threads
```

Disabling hyperthreads (equivalent to `--threads=64`):

```
Running tests with 64 thread(s)
...
Ran 1272 tests in 3520 ms wall time, 161957 ms across threads
```

`--threads=32`:
```
Running tests with 32 thread(s)
...
Ran 1272 tests in 3329 ms wall time, 69327 ms across threads
```

And for `./autoupdate_testdata.py --threads=64 --print_slowest_tests=5`:

```
Running tests with 64 thread(s)
...
Ran 1272 tests in 3417 ms wall time, 157946 ms across threads
  Slowest tests:
  - toolchain/lower/testdata/function/generic/call_recursive_basic.carbon: 1508 ms, 1484 ms in Run
  - toolchain/lower/testdata/builtins/print_read.carbon: 1506 ms, 1506 ms in Run
  - toolchain/lower/testdata/array/field.carbon: 1488 ms, 1487 ms in Run
  - toolchain/lower/testdata/builtins/int.carbon: 1482 ms, 1475 ms in Run
  - toolchain/lower/testdata/function/definition/params_one.carbon: 1472 ms, 1471 ms in Run
```

In test:

```
==================== Test output for //toolchain/testing:file_test:
Running tests with 64 thread(s)
...
Ran 1272 tests in 2968 ms wall time, 177732 ms across threads
  Slowest tests:
  - toolchain/lower/testdata/builtins/int.carbon: 1544 ms, 1533 ms in Run
  - toolchain/lower/testdata/array/function_param.carbon: 1539 ms, 1537 ms in Run
  - toolchain/lower/testdata/basics/zero.carbon: 1537 ms, 1536 ms in Run
  - toolchain/lower/testdata/function/call/params_one.carbon: 1535 ms, 1534 ms in Run
  - toolchain/lower/testdata/function/definition/params_zero.carbon: 1531 ms, 1531 ms in Run
[==========] Running 1272 tests from 1 test suite.
[----------] Global test environment set-up.
```
v0.0.0-0.nightly.2025.04.26
2025-04-25 22:06:18 +00:00
Jon Ross-PerkinsandRichard Smith d617cca530 Factor out GetCanonicalFileAndInstId for code sharing. (#5362)
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-25 20:04:49 +00:00
Jon Ross-PerkinsandRichard Smith 949cc21ccc Remove SemIR:: from most sem_ir files (#5358)
This is just cleanup, at least some from LocId replacements.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-25 16:06:10 +00:00
Boaz Brickner d2826ae841 Disable clang-tidy modernize-use-ranges (#5359)
See discussion in
https://github.com/carbon-language/carbon-lang/pull/5353
2025-04-25 13:31:08 +00:00
Boaz Brickner 609ccefd18 Introduce a Clang diagnostic instruction and use it to point to C++ source locations on Clang errors and warnings (#5262)
Introduce `ImportIRId::Cpp` and refer to clang source location in its
`ImportIRInst`.

Part of #5245.
2025-04-25 13:05:45 +00:00
David BlaikieandJon Ross-Perkins 1e2d4c3405 Reject generic virtual functions (#5356)
Not entirely sure what the SemIR representation for this should be - do
we put the bogus thing in the vtable, and just not lower it later? The
patch currently doesn't add the function to the SemIR vtable - which
then means you could find a virtual function that's not in the vtable,
which seems similarly confusing.

I guess we could make the function non-virtual?

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
v0.0.0-0.nightly.2025.04.25
2025-04-25 00:07:35 +00:00
Jon Ross-PerkinsandDavid Blaikie a342e5c117 Add lexing for dump-sem-ir-start and end (#5357)
Syntax rationale is on `DumpSemIRRange` to try and record this, since
I'm not sure this belongs in the language design. The intent of this is
to be able to subset SemIR, which will be done separately in the
formatter.

---------

Co-authored-by: David Blaikie <dblaikie@gmail.com>
2025-04-24 22:17:04 +00:00
Jon Ross-Perkins fb39e3c569 Adjust patch indent for buildifier (#5354)
Noticed from
https://github.com/carbon-language/carbon-lang/pull/5338/files/5bac558d8d9bd8adbfdd5e9e44bf7a24d75e1d8d..e0d2089c86df1fb2e97c58d727b7f531f952829b#diff-bab6d9fe4c98e775b8a74edf0079d3052a11faf16c133b69172181744e537d81R25
2025-04-24 17:03:19 +00:00
Boaz Brickner 23d92c05ca Fix clang-tidy: move assignment operators should be marked noexcept [performance-noexcept-move-constructor,-warnings-as-errors] (#5266) 2025-04-24 15:37:24 +00:00
Jon Ross-Perkins 8512e9198e Fix single-threaded runs for single test (#5350)
Typo fix.

```
$ bazel test :file_test_base_test --test_output=all
...
Running tests with 128 thread(s)
...
$ bazel test :file_test_base_test --test_output=all --test_arg=--gtest_filter=FileTestBaseTest.testing/file_test/testdata/two_files.carbon
...
Running tests with 1 thread(s)
...
```
v0.0.0-0.nightly.2025.04.24
2025-04-24 00:58:09 +00:00
David Blaikie 77c5f63be7 Skip upfront emission of vtables for generic classes (#5349)
These will need to be emitted lazily, as we do for functions - this
addresses the crash/removes the impossible (because we don't have a
specific) non-lazy path.
2025-04-23 22:55:07 +00:00
David Blaikie b00a037c52 Mangle impls even if they impl an interface with associated constants (#5348)
Fixes issue #5307
2025-04-23 22:08:54 +00:00
Jon Ross-Perkins 281e79e83b Prepare tests for adding a prelude dependency to destruction (#5346)
Adds an empty `min_prelude/destroy.carbon` in anticipation of turning it
into an interface. Update `no_prelude` tests to be `min_prelude` and
import it where needed; in some cases, modify the file to remove the
dependency (i.e., rewrite code to have nothing to destruct).
2025-04-23 21:41:59 +00:00
josh11bandJosh L 367c210871 Test clean up follow up to #5320 (#5344)
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-04-23 20:03:36 +00:00
Jon Ross-PerkinsandGeoff Romer 03e693873b Detect control flow in entities nested inside functions (#5336)
Right now, return_scope_stack is being used to determine whether logic
is in a function scope. However, we need to handle nested entities
inside function scopes. For example where this crashes right now:

```
base class C(B:! bool) {}

fn F() {
  class B {
    extend base: C(true or false);
  }
}
```

This is doing a few things to make this kind of code not crash:

- Split `scope_stack().Push` into `PushForDeclName`, `PushForEntity`,
`PushForExpr`, and `PushForFunction` so that better decisions can be
made about behaviors.
- Hide `return_scope_stack` in the API, instead using interfaces to get
at the underlying data.
- Also using `PushForFunction` to update it similar to the other stacks
that `ScopeStack` manages.
- Add `IsInFunctionScope` as the best way to determine presence in
function scope.
- Remove `PeekIsLexicalScope` since destruction really wants function
scope information anyways.
- Clean up `destroy_id_stack` handling to be for function scopes rather
than lexical scopes.
- Return after related `context.TODO`s in a couple more spots, so that
code doesn't proceed to add control flow in spite of the lack of
support.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-04-23 19:03:53 +00:00
51498547c9 Always use LookupImplWitness instructions for symbolic witnesses (#5321)
We eliminate the `FacetAccessWitness` instruction, which would sometimes
immediately evaluate to a concrete `ImplWitness`, and sometimes remain
symbolic. This instruction is now replaced by `LookupImplWitness` in all
cases. To support the same use cases, when it is evaluated,
`LookupImplWitness` will look in the self value if it's a facet value,
and attempt to return a concrete `ImplWitness` from it before looking
for an `impl` statement.

The `LookupImplWitness` instruction's value is now canonical, even when
it evaluates to a symbolic `LookupImplWitness` instruction, by
canonicalizing the self value of the lookup query. This canonicalization
unwraps `FacetAccessType` and `FacetValue` instructions to get to an
underlying canonical facet value. However we must preserve and use the
non-canonical query while evaluating the instruction in order to look
for a concrete `ImplWitness` if the query self value was a concrete
`FacetValue`. The canonicalization ensures that symbolic witnesses
obtained from a facet value are compatible with those obtained from an
impl statement, as long as the self types originate from the same
canonical facet value though they may have been narrowed.

Member access now unconditionally does a `LookupImplWitness()`
operation, instead of only sometimes doing the lookup for a final impl
declaration.

`EvalImplLookupResult` is marked `[[nodiscard]]` so that we don't
construct it and forget to return it. This was a mistake made at one
point during the creation of this PR. And the `has_concrete_value()`
method no longer has a precondition that `has_value()` is true, since we
want to look for a concrete result only in the new use of
`EvalImplLookupResult` returned from lookup into the query self facet
value.

The TODO from `FacetAccessWitness` evaluation is addressed by ensuring
the index of the witness in the `FacetValue` comes from the required
interfaces of the `FacetValue`'s type, and that the type (a `FacetType`)
is the same facet type used in the query to construct the `FacetValue`'s
witness block. This is made possible by eliminating the
`FacetAccessWitness` indirection. The lookup into a `FacetValue` happens
while evaluating `LookupImplWitness` and it does so directly on the self
value. This gives a consistent view of the witness set and the facet
type, as they both come from the same instruction.

All of this with 400 less lines of code. :)

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-23 16:39:09 +00:00
Dana Jansens 94dca7967b Allow extend final impl as for impl declarations (#5345)
In a class, an `impl as` can now be both `final` and `extend` instead of
only one or the other.

In https://github.com/carbon-language/carbon-lang/issues/5319 we decided
this is already allowed by the design but was an oversight in the
implementation.
2025-04-23 15:20:18 +00:00
Richard Smith ca8df34d0d Format the call parameters of a function, not the patterns. (#5342)
This makes the parameters printed in a SemIR `fn` declaration match the
arguments printed in a SemIR `call` instruction.
v0.0.0-0.nightly.2025.04.23
2025-04-22 18:52:21 +00:00
Geoff Romerandjosh11b f5b5731c76 Separate fields from other var decls in parse (#5320)
This enables us to decouple class fields from pattern matching.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2025-04-22 17:15:53 +00:00
josh11bandJosh L b477797239 Clarify generic design about the type before as (#5341)
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
v0.0.0-0.nightly.2025.04.22
2025-04-22 00:04:48 +00:00
Richard Smith 5501424524 Collect per-entity names when processing the entity, not each declaration. (#5340) 2025-04-21 23:36:57 +00:00
Richard Smith 64baa84e4d Stop substituting into MetaInstId operands. (#5328)
A `MetaInstId` is intended to represent a handle to an instruction in a
generic as an operand to a template action; substituting into the action
should not substitute into the referenced instruction.

Fixing this exposed a bug in `GetOrAddInst` where it would return an
`InstId` of an unattached symbolic constant in some cases, rather than
the `InstId` of an instruction that has the relevant (attached) constant
value. That's fixed for now by turning off the `GetOrAddInst`
optimization in that case, but in future we can refine this by adding
the instruction to the eval block for the generic only, and not to the
body of the generic.
2025-04-21 21:19:14 +00:00
Richard Smith b5ae988a08 Add builtins for compound assignment operators. (#5335)
Provide builtins for compound assignments instead of defining them in
the prelude as a use of a binary operator and an assignment. This allows
us to lower compound assignment directly to LLVM operations instead of
producing a function call. In the short term this also allows us to
define a type-generic compound assignment in the prelude.
2025-04-21 20:38:11 +00:00
Chandler Carruth 2bdea71c25 Simplify freeing with new LLVM (#5334)
We now have upstream support for a clean way to forcibly enable freeing
memory in a library context, so use that.
v0.0.0-0.nightly.2025.04.20 v0.0.0-0.nightly.2025.04.19 v0.0.0-0.nightly.2025.04.21
2025-04-18 22:05:25 +00:00
Richard Smith 89c9714825 Fix handling of member types of generic classes. (#5332)
Instead of evaluating a non-parameterized class or interface to a
constant with `SpecificId::None`, use the self specific for that class
or interface, which will not be `None` if there is an enclosing generic.
2025-04-18 15:09:50 +00:00
Dana Jansens 9a6c74f0cd Introduce FindIfOrNull() FindIfOrNone() and Contains() (#5322)
`FindIfOrNull` returns a pointer to the element in the range if it's
found, and nullptr otherwise. `FindIfOrNone` returns a copy of the
element in the range if it's found, and `T::None` (for a range of
elements of type `T`) otherwise. `Contains` returns a bool indicating
whether the element in the range is found.

These functions replace `llvm::find()` and `llvm::find_if()` when you
want a single answer back instead of an iterator. This avoids the need
to check against `end()`, allowing the return condition to be tested as
a standard bool.

We replace uses of `find()` and `find_if()` that did not require an
iterator with these new helpers.

Note that the return type of `FindIfOrNull` is a pointer since we can
not write `optional<T&>`, which must be tested for null. If the null
check is omitted, UB occurs and the resulting code may end up with an
incorrect pointer (https://crbug.com/40153300) into the range (or
elsewhere), rather than a null dereference. And this would be very
confusing to debug. Hopefully debug builds and sanitizers keep this from
being an issue we sink a bunch of time into debugging.
2025-04-18 14:17:48 +00:00
Chandler Carruth 55705aaef8 Update LLVM, picking up new -disable-free flag logic (#5333)
This requires fixing some uses of deprecated APIs.
2025-04-18 03:49:27 +00:00
josh11bandJosh L 034e374f0a Add TODOs re: pattern_block_id to inst_namer.cpp (#5331)
From
https://github.com/carbon-language/carbon-lang/pull/5310#discussion_r2045291737

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
v0.0.0-0.nightly.2025.04.18
2025-04-18 00:58:31 +00:00
josh11bandJosh L dfd5fe368d Fix comment typo in toolchain/sem_ir/inst_kind.h (#5330)
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-04-17 22:54:13 +00:00
josh11bandJosh L ecb99e55e7 definitions_required -> definitions_required_by_decl in toolchain/check/check_unit.cpp (#5329)
Updates message to reflect changes in #5090 .

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-04-17 22:48:37 +00:00
Richard Smith 19532967fa Stop pushing a fake generic for the duration of check. (#5326)
This fake generic was used for two reasons:

- The declaration name stack assumes that each declaration name is
processed within a generic scope. This is important if the name might
have generic parameters, which are always parsed even for declarations
that disallow them in check.
- Out-of-line redeclarations of generic entities produce instructions
with symbolic constant values in non-generic scopes.

The former case is addressed by pushing a generic each time we start a
declaration name, even if we will reject generic parameters later. The
latter case is worked around for now by not building a symbolic constant
type or value for instructions that appear outside of any generic, and
will be addressed more completely by #5310 and follow-ups.
2025-04-17 21:58:37 +00:00
Dana Jansens 886dc842f0 Make toolchain/check/testdata/facet/no_prelude/access.carbon into a min-prelude test (#5327) 2025-04-17 21:25:17 +00:00
Dana Jansens c3e112e664 Document and configure running lldb from the command line (#5324)
The docs explain that you must use `--local-lldbinit` in the command
line, and include an example of how to run a file_test under lldb from
the command line.

This PR includes `.lldbinit` file and `lldbinit.py` file which set up
our default options, copied from the VSCode launcher.

The instructions include settin the `max-string-summary-length`, and we
include this in the vscode launcher for lldb, as printing `Dump()`
output can easily get truncated otherwise when printing an InstBlockId.
2025-04-17 21:18:25 +00:00
Dana Jansens 84a0060447 Allow a struct/tuple type literal to implicitly convert into a facet value (#5325)
We already had conversion in place to implicitly convert these literals
to `type`. Now they can also convert to `FacetType`. This is done by
first doing a conversion to `type` and then converting that type value
to `FacetType`.
2025-04-17 20:56:36 +00:00
Dana Jansens c38e723dd8 Rename singleton InstId constants to TypeInstId (#5323)
These constant instructions are all TypeInstId already in their type,
and this makes their names match.

Change the name of MakeSingletonInstId as well and update its comment.
2025-04-17 18:57:20 +00:00
Thomas Köppe bf32da8dad Add missing standard library header inclusions (#5316)
Discovered by clang-tidy.
2025-04-17 15:37:57 +00:00
David Blaikie f45a632d77 Implement virtual call dispatch (#5308)
Adds a `virtual_index` to `SemIR::Function` used to determine which
vtable slot
to use when calling the given function.

Then use that to lower the function call to use the vtable and
specifically the
relative vtable ABI to match the vtable entries.
2025-04-17 14:42:30 +00:00
Richard SmithandJon Ross-Perkins 48dc411776 Stop using Add*InstInNoBlock during import. (#5317)
`Add*InstInNoBlock` adds an instruction in the current context,
including adding its type and constant to the current generic eval block
if necessary. This is inappropriate during import, because the current
generic is generally not related to the instructions we're importing.

Previously we worked around this by pushing a placeholder generic onto
the generics stack, but that workaround doesn't interact well with
building generics incrementally. Instead, change the import code to
create instructions directly instead of via `Add*InstInNoBlock`.

This also allows a little simplification, because all the import logic
created imported instruction locations in the same way.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
v0.0.0-0.nightly.2025.04.17
2025-04-16 23:56:08 +00:00