As described in [the generics design](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#type-structure-of-an-impl-declaration), `impl` declarations are prioritized by type structure. Given two `impl` declarations that match a `type as interface` query, the one that describes the longest prefix of the query without using placeholders is preferred.
We implement this by putting all impls in a total order, first by type structure equivalence classes and then by lexical order. When matching an impl, we walk this total order, and stop once we find a match and reach the end of its equivalence class.
Equivalence classes are determined by finding the locations of the "holes" (the positions where deduced parameters appear) within the type structure, viewed as a tree. Two impls are in the same equivalence class if their holes are in the same place, and equivalence classes are ordered based on a reverse lexicographical ordering of their holes.
Explorer doesn't keep the `Bindings` list for a parameterized type in any particular order, but the type structure rule requires that we consider them in lexical order. In order to support this, we now track an index on the declared parameters of each generic. This is a simple numbering of enclosing generic parameters, both on that generic and on all lexically enclosing generics.
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This tries to make it clearer that user code is responsible for ignoring observable differences between the possible behaviors, and uses "alias" instead of "pointer" to describe the reference-like option. It also avoids taking a stance on how we address the possibility of the original value being mutated after it is aliased.
This was bugging me after I saw all the strings; it feels like this is why we have EnumBase on the toolchain side.
I've included the move of EnumBase to //common because I figured it's reasonable to evaluate together; if we don't want EnumBase in this case, it doesn't make sense to move.
Statements, declarations, and definitions will terminate with either a semicolon
(`;`) or a close curly brace (`}`). Semicolons are never optional.
For example, with a semicolon, `x = x + 2;`. With a close curly brace,
`for ( ... ) { ... }`, or `class C { ...}`.
This does not affect any approved proposal; rather, it makes an important
assumption explicit.
Based on lead decision #1924Fixes#2002
I've been heading this route with other parts of the parser because the overhead of adding enums and then switching on them felt tedious, and odd from a performance perspective to make calls when the caller knew the value to use. My leaning is towards this approach that makes it clearer what's actually different between the modes, and allows removing BraceExpressionKindToParserState. It's a mild code size decrease.
Also cleans up some comments about related parse nodes. Currently basic and not heavily validated.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This makes it possible to specify both deduced and regular parameters on types. It reorganizes the handling of parameter lists in order to allow more reuse of code in this approach. Both functions and types use the new DeclarationNameAndParams handling. Overall the goal here is to take advantage of commonality in structure.
Regarding destructors, the likely approach would be to use ParameterListAsDeduced directly because `destructor` is a keyword with no declaration name and no regular parameters.
Unused diagnostics were incorrectly always returning "false" regardless of whether there was an issue. It was still looking for registry file changes, not kind file changes. Also, this should only be run once per pre-commit run (pass_filenames=false).
Remove the one unused diagnostic.
Previous phrasing was unclear, because "language work" sounds like it means language _design_ work.
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This is just a mild simplification to address repeat macro use. I'm hoping it makes it clearer and easier in parser_state.def to write down the multiple variants.
I'm writing these macros in a simple form that I think is easy to read, versus some complex macro recursion which I think is _possible_ but would be harder to reason. And, we don't really need arbitrary arg counts -- this is probably going to stay fairly limited long-term, although I could easily see something like a half dozen in some cases so maybe I'll be wrong and it'll go higher. But, I feel like these macros still make it easier to focus on the _intent_ of cases, rather than visually comparing each line for differences.
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
We could similarly add others -- this is intended to make it easy to add more that parse essentially the same.
The functionality expected is that types will use GetDeclarationContext in order to error on certain functionality in the declaration scope loop. e.g., with how constraints and interfaces currently don't allow definitions.
I've only moved out `package` because it's only valid on the top line. It might still be good to parse it later, but with slightly different logic because it would always be an error, and the declaration context isn't quite the right framing for that.
Also unifies some errors with `fn`.
This resolves an issue I was seeing where none of the `lit` based test
executions could import the `lit` module. The `imports` attribute this
adds seems like the essential part, but I added both while there.
I'm not sure if this is the right fix though as no one else seems to
have been having trouble and worried this is actually something weird
with my setup that is broken. Ideas or suggestions welcome!
### Greater symbol issue in doc file of comparison_operators
In doc, symbol of greater or greater than equal is write but word is miswritten
so i just fix the word which is miswritten.
This is something we'd discussed. I added a TODO that we may want to eventually make this a map, but I remain uncertain and think it's not something that's going to really cost us if we end up switching back. In the meantime, I think this approach does offer simplicity. As discussed too, the performance overhead of a map may ultimately not be worthwhile here versus the relative memory costs.
Depends on #2646
Right now, deduced parameter handling is very narrow to `self` support. This folds it into pattern handling, which should eventually be a superset of deduced parameter support, so this will avoid more duplication of logic.
Note, this subtly adds handling of multiple deduced parameters, but not generic parameters (`:!`) so it's still not quite right.
I've been thinking about how to restructure block recursion in order to handle params better, but this PR doesn't encounter that issue, and I may be able to adjust SemanticsIR to avoid the issue (but I'm still not sure how to form complex types in LLVM IR).
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
The comments in parse_node_kind.def capture the change being made here.
Before:
```
// _external_: DeclaredName
// InterfaceBodyStart
// _external_: statements
// InterfaceBodyEnd
// InterfaceDefinition
```
After:
```
// InterfaceIntroducer
// DeclaredName
// InterfaceDefinitionStart
// _external_: declarations
// InterfaceDefinition
```
Really I just want to treat introduced things consistently. `var` defines my philosophy here: it doesn't always have a `DeclaredName`, so the `VarIntroducer` _must_ be the bounding node. By being consistent with that, I believe that overall the structure becomes easier to understand (that is, there are fewer inconsistencies to understand).
This also adds InterfaceDeclaration, since I think it can be predicted we'll have that, and it's helpful for making recover consistent with HandleDeclarationError.
Similarly, I'm also trying to standardize the loop processing a little with HandleDeclarationLoop. In the current approach, InterfaceDefinitionFinish isn't a necessary state, so I'm removing it.
These are used by the AST in lots of ways, and this resolves various layering issues.
This means that `AllocationId` also lives in ast/, but is managed by interpreter/. A better layering here would be desirable, but this seems good enough for the time being.
Per [discussion](https://discord.com/channels/655572317891461132/655578254970716160/1078427629427904563), there's a preference for having the support this enables in the parser. For example, that the parser should detect and error on a non-default interface function's definition.
However, we do need to handle nesting of declarations. We could do that by making this a stack. I think though that it'll be more efficient to keep using state_stack_, since it'll be called in places which are a limited number of steps from the actual state. That may already be in cache since we frequently look at state_stack_, so I'm uncertain that maintaining an additional stack would be a net benefit.
**### There is issue in conditionals.md readme file**
**In example of fruits conditionals**
**there are fruits.IsGreen() if it is False then continue.
if it is True then print "Apple" but in readme file there is "Orange"**
I replaced "Orange" with "Apple" because in example there is "Apple"
```carbon
if (fruit.IsYellow()) {
Print("Banana!");
} else if (fruit.IsOrange()) {
Print("Orange!");
} else if (fruit.IsGreen()) {
Print("Apple!");
} else {
Print("Vegetable!");
}
fruit.Eat();
```
These functions are dangerous, as they check whether conversions are possible without actually performing the conversions. In each case where they were used, explorer would crash in some cases if a user-defined conversion is required.
This change moves us more towards implicit conversions being handled by a regular function call on an interface and away from them being magical builtins. Unfortunately, this exposes a pre-existing bug that a call of the form `x.(ImplicitAs(T).Convert)()` compiles even if `x` only has an explicit conversion to `T`. That's worked around here for now, but will need a proper fix later.
google-readability-function-size and readability-function-size were _both_ triggering on TypeCheckExp. It looks like the Google version may be a subset of the general version, so I've disabled the Google version while keeping the general version and adding a NOLINT for it.
I manually removed the `const` in cases like `Nonnull<const VTable* const>` based on the readability-const-return-type warning. i.e., where a return type is a pointer, the `const` isn't meaningful and the tidy check was warning about that.
Added a NOLINT for misc-definitions-in-headers on IsRecursivelyTransformable. I think that's the right choice for the `constexpr`, the warning didn't feel accurate and may be getting confused by the templating.
I changed the structure of `carbon_files` in the fuzzer because the `new` was causing a warning about exceptions. However, also disabling bugprone-exception-escape because it's what was flagging this and it's not really a helpful warning.
Other changes were automated.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Right now //explorer/fuzzing:explorer_fuzzer takes my machine 80s to run, just because of the corpus size. The corpus is actually pretty small compared to the toolchain fuzzer, so reducing the corpus size doesn't feel quite right.
This adds support for sharding fuzz tests, and with 8 shards each is closer to 10s. This should put it closer to the noise of other explorer tests in terms of runtime.
Unfortunately I'm not seeing a sharding flag in the llvm library, which seems fair. However, that's why I'm working around it by creating separate test targets per shard, then a suite to merge them back together. The use of `shard_count` for this is idiomatic for bazel rules; I'm using it so that switching implementations should be low-impact if that's ever needed.
Co-authored-by: Adrien Leravat <Pixep@users.noreply.github.com>
These instructions have fallen out of sync with the note that we've stopped recommending brew for linux (due to build issues). Rather than having instructions that only work for MacOS, take the bare minimum and just point at contribution_tools.md.
chandlerc, I believe you'd specifically requested the instructions here as part of #1390. An alternative approach would be to remove this entirely, and just say "See our contribution tools page for instructions on how to build locally."
i-khadra's change #2636 is what made me notice this issue. They're trying to add Windows notes to the README, but this change reflects my leaning it's better to let contribution_tools.md explain setup.
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This is starting to build out actual lowering logic, for a really simple `fn Main() -> i32 { return 0; }`
Notes for achieving this:
- In semantics, currently function names are bound separate from the signature. When emitting IR, this turns out to be inconvenient because we want to know the name when we process the declaration and the definition. This change addresses that by merging the name into the FunctionDeclaration node, which is also accessible from the definition. It removes the separate BindName. This should be the cause of all the test changes in semantics, because the IR generated changes.
- Add a "Lowering" class which I'm using to hold the llvm builder state. This class now has minimal support for the SemanticsIR generated by the above example.
- In the "Lowering", values from expressions are stored in a DenseMap. I'll keep thinking about whether there's a cleaner way to achieve this, and I'd call it a temporary solution for now. However, this is how the `0` in `return 0` gets properly associated across SemanticsIR instructions, and it'll frequently be an issue in less trivial cases.
The toolchain misinterprets escaped whitespace characters as unescaped when trimming trailing whitespace on a line. This PR adds a variable to track the length of the string after escaping the most recent escape, making sure we don't backup past that character, whatever it is.
I did try the approach mentioned in #2132 of not backing up `end_of_regular_text` number of characters, but this caused problems on lines like <kbd>tab</kbd> <kbd>space</kbd> <kbd>tab</kbd> (those characters literally, not escaped) where it would leave the first tab since that is processed in a different iteration of that loop.
I added a test case for this bug. I kept getting mixed up in the test output which one was the expected value, so I also changed a variable name there for clarity.
Fixes#2132.
Adjusts handling of class constants (`static const`) to use CamelCase. This probably better reflects how we use it in C++ code, treating as appropriate for CamelCase instead of under_score.
Fixes adding_children to be preorder in caller (not sure why this wasn't automated).
No automated changes.
Just opening files in vscode and seeing what clangd flags.
Some edits to ostream.h to stop it from getting flagged (the usage pattern means it's not always obviously used).
This fixes some bugs in each, where the fixes had only been made on one
side of the switch or the other. Also don't forget to instantiate
deduced generic arguments in a call when we read them out of the AST.
This is intended to address currently flaky timeouts that are likely caused by the size of the prelude. I'm addressing a performance bottleneck in AnalyzeProgram with trace output. Trying to omit prelude traces reduces most trace output significantly, and I think it'll scale better as the prelude size increases.
The basic mechanics here are:
- In order to consistently track whether tracing is on, I've added a TraceStream class, explorer/interpreter/trace_stream.h.
- The AST now has a num_prelude_declarations field, so that it's provided where the boundary is.
- In order to mark where we try to skip prelude output, I've added calls to set_in_prelude in type_checker.
- In exec_program, I just use num_prelude_declarations directly to skip over.
- Everywhere checks TraceStream::is_enabled before printing, similar to the std::optional check that was previously used.
This does add some timing output in order to better diagnose where slowness is coming from, when tracing. It also adds "verbose" targets to make it easier to get the trace output.
So for example, here's a timing for zero.carbon:
```
Timings:
- Parse: 13ms
- AddPrelude: 25ms
- AnalyzeProgram: 116ms
- ExecProgram: 12ms
```
If I make a small change to just not set skipping_prelude (essentially getting back to current output):
```
- Parse: 13ms
- AddPrelude: 25ms
- AnalyzeProgram: 2359ms
- ExecProgram: 57ms
```
Thus in this trivial example, I'm eliminating about 95% of the execution time.
Note this approach could still be refined in a few ways:
- We could add a flag to allow overriding in_prelude. It should be a small amount of work after this change. But it's a little consistent with how parser_debug works, that it won't print prelude output by default (unless there's an error).
- Execution could skip messages involving initialization of globals declared in the prelude. This is a little noisy right now, but I don't think it's significant for performance because ExecProgram is tiny.
- Once files are more separated, we should be able to change the num_prelude_declarations/set_in_prelude approach.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This starts handling return types on functions, and comparing types with `return` statements.
Note, errors remain poor because the type literal is currently associated with a builtin, losing the parse_node that specified it. This means we don't have the original source location to associate with, even though it may be helpful to point at the type in source. We could point at the signature overall, but my leaning is that we wouldn't want that long-term, so TODOs for now and may want to change a little about how the parse node is tracked once things are a little further along.