When creating a tuple or struct type object/value, we will walk each of
the tuple's or struct's parts, respectively, and Convert() each of them.
This allows (T, T) to convert to (U, U) and so forth. It also performs
the conversion from value to initialization even for the same types,
such as converting from a value of (T, T) to an object of (T, T).
Classes need to define their own conversions but when the target and
source types are the same, there is no conversion of types taking place.
If the class adapts a tuple or struct then walk each of the tuple's or
struct's parts, respectively, and Convert() each of them in order to
initialize the parts of the target.
For copyable types, the conversion implies a copy in the initialization,
and for non-copyable types, an error is emitted.
This supports copying a class value to a class object when it is an
adapter of a tuple or struct.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
* Change `InterfaceWitness` -> `ImplWitness`
* Include a `SpecificId` in the `ImplWitness`. This allows the
`InstBlock` it contains to have its own identity, allowing it to be
changed as the impl is processed. Evaluation only updates the specific.
* Create the `ImplWitness` at the start of the impl definition. In the
future, this will be populated with the values of non-function
associated constants. For now, it starts full of invalid instruction
ids.
* Implements the model suggested in #4672 .
Note that the non-SemIR testdata changes are to these file:
* `toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon`
* `toolchain/check/testdata/struct/import.carbon`
* `toolchain/check/testdata/tuple/import.carbon`
The last two are due to an import of generics bug exposed by this PR,
which will be fixed in a follow-on.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Fixes integer builtins to produce the correct values (and not
CHECK-fail) when used on integer literals. Also adds impls to the
prelude to use the new builtins to perform operations on integer
literals.
Perhaps most importantly, this allows directly initializing `i32` values
with negative numbers, as the negation operation on integer literals now
works.
For testing I've added tests for use of literals with one operator in
each class (addition, multiplication, ordering, bitwise, etc) for which
there are distinct rules or overflow behavior, rather than exhaustively
testing all the combinations. This is aimed at finding a good tradeoff
between maintainability of the tests and thorough test coverage.
Also fixes lowering of heterogeneous shifts and comparisons. These are
currently disabled when one of the operands is an integer literal, but
we may want to allow that when the integer literal operand has a known
constant value.
Pursuant to discussion regarding #4699, turn on
`misc-non-private-member-variables-in-classes` using the
`IgnoreClassesWithAllMemberVariablesBeingPublic` flag (the check treats
structs as classes, so we need this for structs with all-public
members). Updates the style guide notes to match, which should be pretty
minor due to the scoping of test fixtures.
Also fixes some underscore uses in test files on the way. Basically this
is keeping the style for [class data member
naming](https://google.github.io/styleguide/cppguide.html#Variable_Names)
even while making them public.
Instead of treating `Core.Int` as the toolchain's builtin `IntType`,
model it as a class that adapts the builtin type. This aligns us better
with the intended language model, gives an associated library for
`impl`s involving `Core.Int` to live within, and opens the door adding
member functions to `Core.Int` if we decide that is desirable.
Remarkably it also seems to make the formatted SemIR a little smaller,
because a call to a generic class generates less IR than a call to a
function.
Also fix a bug in `Context::GetClassType` that previously tried to
complete the class type before returning it. That's not correct --
`GetCompleteTypeImpl` is only appropriate for cases where the type can
trivially be completed and completing it can't fail -- and led to
infinite recursion with this change because we would call `GetClassType`
when producing a diagnostic if completing that class type failed.
When a generic requires a symbolic type to be complete, add a new
`require_complete_type` instruction to the generic eval block. During
monomorphization of such an instruction, require that type to be
complete.
The new `FacetValue` instruction represents `C as I` for some type `C`
and facet type `I`. It is named `FacetValue` instead of just `Facet` to
parallel the `FacetType` instruction.
This PR uses this instruction represent the facet value `Self` in an
`impl` declaration. This instruction will be used in the future to also
support things like:
* `C as I` where `C` is a class; and
* forming a specific for a generic with a `T:! I` parameter where `T` is
being given a concrete value.
(Here `I` is an interface or other non-`type` facet type.)
Also do some renaming and add some comments to make things a bit more
clear.
* `FacetTypeAccess` -> `FacetAccessType` to clarify this is not access
of a facet type, but access of the type of a facet
* `.facet_id` -> `.facet_value_inst_id` to parallel the `FacetValue`
instruction
`FacetAccessWitness` will be in a future PR.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
When an `IntLiteral` appears as an operand of an `if` expression,
convert it to `i32` for now, so that we don't reject things like `if
cond then 1 else 2` due to having a non-constant value of type
`IntLiteral`.
For tuple indexing expressions such as `(a, b).0`, convert the index to
type `IntLiteral`, not to type `i32`. This isn't strictly necessary to
do in this PR, but avoids the need to provide an `IntLiteral` -> `i32`
implicit conversion for `no_prelude` tests using this syntax.
As a prerequisite for switching the type of int literals to be the
`IntLiteral` type, add support for performing conversions of in-bounds
integer constant values to other integer types in which they fit.
This incidentally is our first compile-time-only builtin function, so
add very minimal support for compile-time-only functions while we're
here.
* The `extended_scopes` in a `NameScope` were represented by a
`NameScopeId`. Replace that with an `InstId` of an instruction returning
the type that is extending this name scope.
* `Context::LookupQualifiedName` now can take multiple scopes to look
in.
* `GetAsLookupScope` was moved out of `member_access.cpp` and is now
`Context::AppendLookupScopesForConstant`
This PR also fixes some existing issues that were revealed as part of
writing and testing this PR:
* Additional validation and handling of invalid ids.
* `extend impl` in a class is not properly imported yet, but at least
now it doesn't crash.
The change to use an `InstId` also allowed some diagnostics and
formatting to be improved.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
I'm working to make sure remaining diagnostics have coverage, at least
the ones I'd previously added a TODO for. Note in particular that I
couldn't figure out a repro for UnaryOperatorRequiresWhitespace; if you
have one, I can add a test, but otherwise maybe it's actually
unreachable due to being diagnosed through infix logic (or, maybe
this'll let fuzzing tell me an example).
This does a few things:
* Replaces the single `TypeId` in the `FacetTypeInfo` struct with a
vector of `InterfaceId`, `SpecificId` pairs (sorted in id order)
representing the set of interface requirements of the facet type. This
will later be used to support facet types with multiple interface
requirements (as in `I & J` or `I where .Self impls J`).
* Replace `InterfaceType` instructions (used as the type of an
`InterfaceDecl` instruction) with `FacetType` instructions (introduced
in #4460) with a (newly introduced) `FacetTypeFromInterface()` function.
* Replace code that consumed `InterfaceType` values with code that
consumed `FaceType` values. I've generally left the assumption in the
code that it is dealing with a single interface, using the (newly
introduced) `FacetTypeInfo::TryAsSingleInterface`, and producing an
error otherwise. There isn't yet support for the `&` operator or `where
.Self impls`, so this is generally a good assumption for now, except you
can get a facet type with no associated interfaces from a `type
where`... expression. In some cases, the facet type value is pulled from
the evaluation of an `InterfaceDecl` instruction, where the single
interface assumption will hold permanently.
* Some related cleans up: nicer stringification and formatting of facet
types, suppression of some errors when there already was an error.
There is still a lot left to do, including:
* Type `type` should be a facet type with a reserved id, replacing the
built-in instruction.
* Code using `TryAsSingleInterface` should generally be upgraded to
handle more than (or less than) one interface. Name lookup should be
particularly exciting.
* Operator `&` should be defined on facet types, unioning their
interface and other requirements.
* Requirements from a `where` clause don't do anything yet.
* Impls and impl lookup need to resolve facet types, and do things like
determine if all the associated constants are given values.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Geoff Romer <gromer@google.com>
Adds coverage for an existing diagnostic. Code appears to work without
modification.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
This rejects type literals with more digits than we can lex without
APInt's help, and using a custom diagnostic. This is a pretty arbitrary
implementation limit, I'm wide open to even more strict rules here.
Despite no special casing and a very simplistic approach, by not using
APInt this completely eliminates the lexing overhead for `i32` in the
generated compilation benchmark where that specific type literal is very
common. We see a 10% improvement in lexing there:
```
BM_CompileAPIFileDenseDecls<Phase::Lex>/256 39.0µs ± 4% 34.8µs ± 2% -10.86% (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/1024 180µs ± 1% 158µs ± 2% -12.22% (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/4096 731µs ± 2% 641µs ± 1% -12.31% (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Lex>/16384 3.20ms ± 2% 2.86ms ± 2% -10.47% (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/65536 13.8ms ± 1% 12.4ms ± 2% -9.78% (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/262144 64.0ms ± 2% 58.4ms ± 2% -8.70% (p=0.000 n=19+18)
```
This starts to fix a TODO in the diagnostic for these by giving a
reasonably good diagnostic about a very large type literal. However, in
practice it regresses the diagnostics because error tokens produce noisy
extraneous diagnostics from parse and check currently. Leaving the TODO
there, and I have a follow-up PR to start improving the extraneous
diagnostics.
This refactors the diagnostic kind coverage check into something that
also works for node kinds. Then, since this points out a few node kinds
that aren't having their parse verified, I'm adding minor tests for
those.
Also surround it in square brackets rather than parentheses. This
matches the format used by Clang and GCC, and means diagnostics will
still match the `file:line:col: error: ` pattern used by some IDE tools.
Before:
```console
fail_builtins.carbon:11:11: error(AliasRequiresNameRef): alias initializer must be a name reference
```
After:
```console
fail_builtins.carbon:11:11: error: alias initializer must be a name reference [AliasRequiresNameRef]
```
Also tighten up test regex to only match on `STDERR` lines that list a
file name.
Previously in an optimized build we'd produce bogus tokens, such as
tokens with incorrect IdentifierIds, and in a debug build we would try
to CHECK-fail -- but actually wouldn't, because we're incorrectly
checking for `2 << bits` instead of `1 << bits`. I hit this while I was
trying to do some profiling and was seeing some very strange
diagnostics.
The diagnostic is pointed at the first token that is beyond the limit to
help people determine where to split their files.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Use the diagnostic kind printing in #4425 to catch when we have
diagnostics with no tests.
This merges a couple other use-cases of filegroup manifests into a
common rule.
Note I do add a few tests for things, and also some things are
_actually_ unit tested (just not in the file_test structure). But I
stopped when I realized that dealing with merge conflicts is going to be
a pain. I might end up reverting test changes (as part of merge conflict
resolution) and doing narrow test additions in a separate PR, after both
this and #4425 are merged.
Building on #4411, avoid using StringLiteral in format strings. This
includes a diagnostic check to prevent regressions (which is also how I
gathered issues).
Note, I haven't looked at `std::string` uses yet, but we might need
things like that to be able to pass strings in code back to the user.
StringLiteral though means that it's literally written down in the
toolchain, at which point it should probably be written in the format
string instead of separately.
---------
Co-authored-by: Geoff Romer <gromer@google.com>
This is to help identify which diagnostics we're actually using.
Note that driver/testdata still has tests which don't pass this flag,
and so continue to test the kind-less (default) behavior.
Distinguish between deduction against a symbolic binding pattern and
deduction against a symbolic binding name. In the former case, the value
is being explicitly specified and must be constant. In the latter case
we encountered a use of the binding name as a subexpression, and should
deduce against it if it's not explicitly specified.
I'm taking the approach of making DiagnosticBase an API so that we can
pass similar diagnostics as parameters. An alternative would be to do
the function_ref approach we've done elsewhere, but these felt more
boilerplate to me.
Note I'm also modifying messages here. Let me know if you'd like
different changes and/or just keeping current formatting (keeping
current formatting would also allow removing some of the templating I've
added, but it felt helpful putting explicit tokens where possible). But
also, things like "`protected` not allowed on `interface` declaration at
file scope" were part of the phrasing issue, I think.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Per discussion on #toolchain, add "s" as a special-case for the common
plural format.
Note this removes periods from a few diagnostics; the periods shouldn't
be there per message style. Also, while I'm ignoring llvm::StringLiteral
uses, those should be addressed as #4416 -- this'll probably conflict
and make me clean up one or the other.
Building on https://github.com/carbon-language/carbon-lang/pull/4411,
replace format_provider uses (other than `TokenKind`, which is more on
the okay side of things)
Also does some edits to `ClassMemberDefinition` to try to better match
diagnostic style
Note, this supports plurals, but doesn't apply it anywhere. I'm mainly
doing that to demonstrate the approach regarding syntax. See
format_providers.h for details.
Also propagate the pattern IR along with the pattern-match IR, and use
it where appropriate.
Strictly speaking, some parts of the pattern-match IR are allocated
eagerly, while traversing the pattern's parse tree, but they still
aren't actually emitted until we traverse the associated pattern insts.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
A good first-pass, at least. (abstract adapters are rejected with this
change, though pending further language design discussion)
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Add a new `specific_function` instruction that represents a generic
function plus its deduced argument list as a callee in a function call.
The new instruction can only appear as the immediate operand of a call
instruction, so we give it a builtin placeholder type.
At the end of each file, require definitions for all specific functions
used in that file. Resolve the generic with the argument list to produce
those specific function definitions as needed, and diagnose if the
generic doesn't have a definition available.
A few tests are updated in cases where they declared and used generic
functions but didn't previously provide a function definition.
With this, we now check:
* The left argument to `where` is a facet type
* The right argument of a rewrite (`=`) requirement converts to the type
of the left argument.
* The left argument of an `impls` requirement is a type and the right
argument is a facet type.
No checking is done for `==` constraints yet.
In addition, make the "is facet type" query into its own function and
fix some comments noticed as part of this change.
This change reveals that accessing the members of a facet, like `.Self`,
isn't doing the right thing, and will have to be fixed in a follow-on
PR. Some tests have been adjusted or disabled as a result.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Not sure about error recovery options - can/should we drop the
definition as a means of recovery when building the SemIR? I guess
probably not, so I guess this change is about right.
Phrasing of the error message I'm certainly open to.
According to
https://docs.carbon-lang.dev/docs/design/generics/details.html#adapting-types:
> You can add any declaration that you could add to a class except for
declarations that would change the representation of the type. This
means you can add methods, functions, interface implementations, and
aliases, but not fields, base classes, or virtual functions. The
specific implementations of virtual functions are part of the type
representation, and so no virtual functions may be overridden in an
adapter either.
So, let's check/reject that.
Checking at the end of the class ensures that no matter the order of
methods and adapt statements, the issue will still be correctly
diagnosed.
This risks diagnsotic formatting crashing, but I think we more
frequently see cases where it'd be interesting to know what diagnostics
were being delayed as part of the default sorting.