Addresses part of issue raised in
https://github.com/carbon-language/carbon-lang/issues/7159 by
implementing float.add & float.sub builtin for FloatLiteralValues
The following code now compiles:
```
let a: f64 = 1.0 + 1.0;
```
Code handles case where operands are both decadic (base 10) and dyadic
(base 2) real literals, with the result being whichever format results
in smaller mantisssa.
File tests assert equality by converting to f128, this can possibly be
improved once CompareWith is implemented for FloatLiteral too.
Assisted-By: Gemini
Found by fuzz testing, root caused to #7479 - fixing this issue for Var
in a similar way to how it was fixed for Let in that patch (by adding
`RuntimeBindingName` to the possible things in the name binding.
Not sure if this would be better fixed by adding `RuntimeBindingName` to
`AnyRuntimeBindingPatternName` or something else?
Assisted-By: Gemini with Antigravity
We currently provide UTF-8 positions, since our source representation is
UTF-8 and we use byte offsets as column numbers, but the LSP protocol
default is UTF-16 column positions. Negotiate UTF-8 positions where
possible; this is supported by essentially every LSP client other than
VS Code.
In the case where we select a UTF-16 position, we continue to not do any
actual conversions, so our column offsets in such cases will continue to
be wrong on non-ASCII source files in VS Code.
Assisted by: Claude Code
This adds most support for default and final methods. Missing components
include rejecting definitions for non-default/final methods, and
permitting out-of-line definitions.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Change '1)' and '2)' to '(1)' and '(2)' to prevent the reflow engine
from treating them as ordered list markers when the paragraph is
wrapped.
Assisted-by: Antigravity with Gemini
We already test this in `access_modifiers.carbon`.
This also fixes a typo in the name of `access_modifiers.carbon` and
removes the `--dump-sem-ir-ranges` flag.
- Enhance toolchain/parse/node_kind.def with category x-macros
(CARBON_PARSE_NODE_KIND_DECLARATION, CARBON_PARSE_NODE_KIND_EXPRESSION,
CARBON_PARSE_NODE_KIND_PATTERN, CARBON_PARSE_NODE_KIND_STATEMENT) that
default to CARBON_PARSE_NODE_KIND, keeping node_kind.def as the single
source of truth without manual expansion divergence.
- Decompose the monolithic toolchain/parse/extract.cpp translation unit
into separate compilation units for declarations, expressions, patterns,
and statements by expanding respective category x-macros.
- Forward-declare Tree and TokenizedBuffer in parse and lex dump headers
to reduce header inclusion depth.
Assisted-by: Antigravity with Gemini
Currently VSCode extension will try share diff views / scratch files
with Carbon language server. This results in following error:
> Request textDocument/semanticTokens/full failed.
Message: in call to `textDocument/semanticTokens/full`, JSON parse
failed: clangd only supports 'file' URI scheme for workspace files at
(root).textDocument.uri
Code: -32602
The change here updates vscode extension to filter for
`file://*/**.carbon` URIs, this matches how clangd extension does it:
https://github.com/clangd/vscode-clangd/blob/893dd905c2a6a7844fe32592796ef593e6f3bca6/src/clangd-context.ts#L18
Also updates tsconfig.json to node16 module resolution, this is done
since [automatic dependabot
PR](https://github.com/carbon-language/carbon-lang/pull/7575) seems to
have broken the build.
```
src/extension.ts:28:8 - error TS2307: Cannot find module 'vscode-languageclient/node' or its corresponding type declarations.
There are types at '/usr/local/google/home/davidloftus/carbon-lang/utils/vscode/node_modules/vscode-languageclient/lib/node/main.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'.
28 } from 'vscode-languageclient/node';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error in src/extension.ts:28
```
[vscode-languageserver-node](https://github.com/microsoft/vscode-languageserver-node/blame/93d5fe6f443dd6c8fe37f422c271d618edd121af/README.md#L159)
recomends updating to node16.
- Consolidate token kind test assertions into helper functions using
EXPECT_THAT(spelling.str(), MatchesRegex(...)) under a single test case
rather than generating ~130 separate TEST classes and redundant matcher
instantiations.
- Slashes individual translation unit compilation time from 59.1s to ~3s
while keeping EXPECT_THAT for clear diagnostic error output and full
token coverage.
Assisted-by: Antigravity with Gemini
This suppresses warnings for unhandled messages where we currently have
nothing to do. No functionality change, except for less spam in the VS
Code output tab.
Assisted-by: Claude Code
When computing the token range of a declaration, we were using the first
and last parse nodes to determine the first and last tokens. That's not
correct -- the parse tree nodes can be in a different order from the
tokens, so the first parse node need not be at the start of the
declaration. For a malformed declaration such as `fn f` (with no
terminator), the first and last parse nodes were both associated with
the `fn` token for error recovery, meaning that the function name wasn't
even within the symbol we handed back to the LSP client, in violation of
the LSP requirements. This led to VS Code producing an error and
discarding all symbols in the file.
Assisted-by: Claude Code
This is similar to the previously-added support for accessing generic
carbon classes from C++, but with the specific defined by Carbon, rather
than being derived from template args supplied by clang in
`LoadExternalSpecializations`.
Example:
```carbon
class C(T: type) {
var t: T;
}
alias A = C(i32);
inline Cpp '''
void F() {
Carbon::A a;
a.t = 123;
}
'''
```
Addresses part of issue raised in #7159 by implementing float.negate
builtin for FloatLiteralValues
The following code now compiles:
```
let a: f64 = -1.0;
```
To achieve this I switch the mantissa from being unsigned to signed.
Lexed literals within source file will still always be unsigned, however
it is now possible to create negative FloatLiteralValue constants. Main
non-local changes this causes is:
- All llvm::APInt parsing / printing calls flipped isSigned param
- Zero extension replaced with sign extension
- getActiveBits() replaced with getSignificantBits() for min bit width
calculation
The exported class was being inserted with a type inst ID as the key
(and looked up that way elsewhere), but when checking if the generic
class was already exported, the `first_decl_id` was being used. Make it
consistent, and opt for `first_decl_id` everywhere since it provides a
better location for diagnostics.
Implementing interface modifiers causes an infinite loop when generating
fingerprints because the witness value generates a fingerprint that's
dependent on something dependent on the witness value. We've debugged
this to the witness table's `elements_id` field.
This hack is a workaround for creating a new block type whose value is
not codependent with its identity.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This solves the problem where `interface` imports are incorrectly
diagnosed as duplicate names in impl files.
Follows the implementation logic used in `handle_class.cpp`.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
If we find an overload set containing mulitple methods, discard any
non-const methods and try again. This allows libc++'s `std::vector` to
be iterated with range-based for.
The toolchain crash is easily diagnosed, but looking at the log doesn't
offer immediate insight into why the program crashes. This provides us
with a graceful exit.
This adds the new restrictions introduced for `observe` declarations
inside `interface` definitions to the docs.
---------
Co-authored-by: Christopher Di Bella <cjdb.ns@gmail.com>
https://docs.carbon-lang.dev/docs/design/expressions/#operators
Escaping `|` is needed to prevent markdown table interpreting it as a
cell edge, however using `\|` in backticks shows the backslash too.
Solution: use `<code>` instead. This overflows the `|` table cell but it
seems to render correctly anyway.
Co-authored-by: David Blaikie <dblaikie@gmail.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
`String.size` is likely to be a signed word-sized integer in the future,
(per a Discord conversation). Changing to `i64` now allows us to iterate
over a string's contents using `IntRange`.
We can't rely on a `clang::CodeGenerator` existing when compiling C++
code; we don't build one unless we're actually emitting code for the
current file any more.
Add `Core.CppCompat.[U]Long64` to represent a 64-bit long that is not
`i64`. Treat it as being "just slightly smaller than" `i64`, like we
treat `Core.CppCompat.LongLong64` as being "just slightly larger than"
`i64`, so that we get implicit conversions `Cpp.long` -> `i64` ->
`Cpp.long_long` on all targets.
This follows the direction of proposal #5448, and seems like the obvious
extension of the `[U]Long32` and `[U]LongLong64` types added in #6275
for targets of this "shape".
Assisted-by: Gemini via Antigravity
Clang treats "file not found" as a fatal error and stops emitting more
diagnostics after reaching it, so these tests don't work in
`--share-cpp-ast` mode if they are all in the same file. So split them
into distinct test files.
Make multiple imports of the same header only parse it once per C++
domain. Reuse of the same header in `--share-cpp-ast` mode now reuses
the representation.
Importing a Carbon file with C++ dependencies now makes those transitive
C++ dependencies in the same C++ domain visible too.
Assisted-by: Gemini via Antigravity
This proposal restricts `observe` declarations in an `interface` to only
reference names dependent on `.Self`, generic parameters, and associated
constants that are part of the enclosing `interface`, with the following
exceptions:
- Allow at most one unrelated value in an equivalence (`==`) chain.
- Allow unrelated values that satisfy the `impls` constraint immediately
in an
`observe .. == .. impls`.
When a split file in a test unexpectedly succeeds or fails, include the
test filename in the error as well as the name of the split. This should
make it a bit easier to figure out which test failed from a failing test
log.
Move `--output-last-file-only` and output filename synthesis logic out
of the general-purpose compile driver and into the `carbon compile`
subcommand, which is the only thing that should be using them. Track on
CompilationUnit whether it is being lowered, or whether it exists only
to be imported into other units.
`carbon compile` now never lowers inputs that it discovered for itself,
only inputs that were specified on the command line. In particular, it
doesn't lower (and throw away the result of lowering) the prelude any
more. This makes the toolchain tests about 10% faster in my crude
measurements.
Also, we now do not create a clang `CodeGenerator` for input files that
we are not lowering, similarly saving compilation time for units that
exist only to be imported, not lowered.
One minor change: we use the same mechanism to determine whether an
input is being lowered and to determine what the output filename is.
This means that `--phase=lower` and `--phase=optimize`, which lower but
don't produce an output file, still need an output filename to be
specified now in some cases. Given those are just debugging tools, I
think that's fine.
Assisted-by: Gemini via Antigravity
Instead of creating a CodeGenerator per CppDomain, and then crashing in
lowering when we try to consume the same llvm Module multiple times,
create a CodeGenerator for each CppFile within the domain.
For now, we mulitplex all of Clang's ASTConsumer output to all code
generators, which means that any strong external definitions within a
Carbon file (for example, in an inline `Cpp` fragment) will be emitted
to all output files in the same `CppDomain`, resulting in link errors
due to symbol redefinitions. This will be addressed later. But this
should be sufficient for Carbon compilations in which such symbols are
not defined.
We also don't yet attempt to classify which compilations will need C++
code generation, and instead create a clang `CodeGenerator` for every
Carbon file that has C++ imports. For `carbom compile`, only one Carbon
file will need code generation, and yet we still build multiple
`CodeGenerator` objects in general. Fixing this requires more plumbing
from the driver, and this will also be handled in a follow-up.
Assisted-by: Gemini via Antigravity
We propose a principle that it's always possible to inline the import of
a library from within the same package without changing the meaning of
or diagnostics applied to the code. This is similar to the textual
inlining of an `#include` statement in C++, but is slightly less
general. Cross-package imports place the imported names inside the name
scope of the package, so inlining those necessarily changes the paths
for name lookup.
---------
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
This isolates the C++ imports in different Carbon files from each other
in `--share-cpp-ast` mode, so that a Carbon file can only see the
portions of the shared Clang `ASTContext` that it actually imported.
Assisted-by: Gemini via Antigravity
When implementing a named constraint, like `impl as N`, any accesses
through `Self` in the named constraint need to get the value of the
associated constant from the impl's witness table. This isn't possible
immediately, since the impl does not even exist until the declaration is
complete. We use the same model as for accesses found directly in the
impl declaration, but applied to the point where accesses in the named
constraint are substituted during identify to point at the impl's self
type. To get there, we need LookupImplWitness instructions in the named
constraint, when re-evaluated during construction of their enclosing
specific, to evaluate to ImplSelfWitness when they are a reference to
the type and interface being implemented.
This reduces object sizes which is desirable for linking speed.
zygoloid did some analysis to determine if any of our code requires RTTI
for `dynamic_cast` here:
https://github.com/carbon-language/carbon-lang/pull/7532#discussion_r3611196721:
> The only thing I found is that libc++ requires dynamic_cast in order
for std::print to correctly write Unicode to terminals on Windows
We use `llvm::print` functionality, not `std::print`, so this doesn't
affect our toolchain.
Note that libc++ and libc++abi are built with RTTI enabled. It is
explicitly allowed to use different compiler flags when building these
libraries even though they share some headers with users of the
libraries, so this does not cause ODR violations.
Inject the name of a macro rather than its contents when computing its
expansion. If the macro refers to itself, it will not expand within its
own body, rather than expanding once.
Switching from `EnterTokenStream` to `EnterToken` exposed that our Clang
preprocessing environment was a little broken -- we reached the end of
the primary source file and starting tearing stuff down before we
actually finished parsing, which we were mostly getting away with before
but aren't any more. Enabled Clang's incremental processing mode to fix
this. This causes Clang to remain in the main source file when it
reaches EOF instead of popping it. This also causes the diagnostics for
invalid `module;` declarations to change, but in a way that seems not
really any worse than before.
Also slightly changes the diagnostics produced from macro expansion
failures. The new diagnostics are a bit more precise -- they now capture
the outermost level of macro expansion -- but we don't do a good job of
rendering the Clang snippet attached to the "in macro expansion" context
note yet, so the context looks a bit weird: we get two different
snippets attached to the same diagnostic.
Start tracking the domain within `CppContext`s instead of having them
duplicate its fields. This allows us to remove the shared ownership of
the clang parser.
---------
Co-authored-by: Christopher Di Bella <cjdb.ns@gmail.com>
In Convert, we require the source value's type to be compete so that we
can look for `base` classes and `adapt` relationships. However these can
only be present in a `ClassType`, so we only need `ClassType`s to be
complete.
Reduce the requirement in Convert to not complete types that are not a
`ClassType`, and which can not contain a `ClassType` as part of their
class.
Ideally we would only _only_ require the `ClassType` itself to be
complete, and only if we're looking for a base or adapt. However lower
depends on us completing all Convert source types that contain a class.
This seems to suggest we're lacking checks for complete types somewhere
else and Convert is making up for it. A TODO has been added. The
`toolchain/driver/testdata/compile/optimize/optimize_debug.carbon` test
is an example that CHECKs due to failing to verify the LLVM module if we
do not compute the complete type of all class-containing types in
Convert.
The critical step this PR is doing is to stop trying to complete a
`FacetType` when converting from a facet. This avoids trying to complete
a named constraint when converting `Self` inside that named constraint.
Doing so causes a cycle when the conversion of `Self` is performed in
eval of an `extend require` decl, since requiring the named constraint
to be complete re-evaluates the `extend require` decl again. A test is
added that crashed in an infinite loop before this change.
It also depends on #7584, which was intended to be an optimization but
is now load bearing. Because converting `Self` leaves an impl lookup
inst behind, and if that inst is re-evaluated inside impl lookup (by
forming a specific of a `require` decl through identify) then we have a
similar cycle.
It's hard to track 2-space indent levels across large vertical gaps, and
it can be hard to suppress the instinct to read the dump as if it were
preorder. This change introduces a new dump mode that addresses both
problems by using box-drawing characters to explicitly represent the
parent-child edges of the tree. This new mode is the default, but the
old behavior remains available with
`--parse-dump-format=yaml-postorder`.
Add a `SpecificID` arg to `Class::GetStructTypeFields`, and use that in
`CalculateCppFieldOffsets`. Also include the specific in the
`clang_decls` lookup. This has no immediate effect since no specific
class fields are being exported yet, but will be useful for exporting
generic classes.
Since we started bootstrapping, our stage-1 toolchain binaries have been
inputs to stage-2 compilations, and to the compilation database logic,
they're indistinguishable from generated sources. This caused us to get
compilation command lines for them, which clangd would try to index by
parsing the binary, and would either run incredibly slowly or crash.
Filter out non-source files from the compilation database.
In passing, also emit the JSON dump without whitespace, which makes the
database a bit smaller and faster for clangd to parse.
Assisted-by: Gemini via Antigravity
---------
Co-authored-by: Geoff Romer <gromer@google.com>
Don't CHECK-fail if the file contains mismatched braces and generates an
unbalanced parse tree.
Properly balance the start and end of symbols. This previously caused
errors to be reported in clients such as VS Code.
Compute a correct range for definitions. Don't assume we can find the
matching `}` for an opening symbol, since some of our definitions are
delimited by a `;` instead.
Assisted-by: Gemini via Antigravity