This is in addition to finding a `where` on the RHS of another `where`.
Since a generic binding introduces `.Self`, any `where` expression that
isn't part of a facet type modifying the binding itself would introduce
an ambiguous `.Self`.
Add virtual parse nodes for let, var, and form bindings, which goes
before the type. This allows us to track if `where` appears in the
binding's type. We only need to look for an invalid `where` if any
appeared in the type. We combine these three nodes together into a
single node kind, which requires us to remove the name from it as a
child. We move it up to the Pattern node again, and rename the
PatternStart nodes to PatternTypeStart as they are now located in the
middle of the Pattern nodes, just before the type.
And we only need to thaw `.Self` in generic bindings. Non-generic
bindings can only have `.Self` through a `where` expression, since the
name is not provided otherwise to non-generic bindings. And `where`
expressions thaw their `.Self` independently. So the binding only needs
to thaw a `.Self` that it introduced, which is only for generic
bindings.
Split up the CppRange interface into smaller parts, with the intent of
improving the diagnostic quality and making the implementation easier to
understand.
This also makes the implementation details of the CppRange machinery
private, which breaks one of the existing tests; that test is split into
two files, one which tests the low-level machinery works, and another
that tests the resulting prelude behavior.
This change exposes a crash in `where` expression handling, where we
would perform a substitution that creates a new `SpecificConstant` that
refers into a region of a generic that has never been resolved. Fix that
by resolving the definition region of a generic if eval sees a
`SpecificConstant` that refers into it. This is usually not necessary
because something else should have resolved that region first, but that
doesn't happen here.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
Instead of tracking the cleanup scope depth on entry to each scope,
track an "ambient" cleanup scope depth that's *after* the destructors of
local variables in that scope. This gets increased to include the
destructors of local variables when we create a name-binding
declaration. Then, when we reach a point where temporaries should be
destroyed, run cleanups that are after the ambient cleanup scope depth
on the stack. This happens:
* At the `;` of a statement expression.
* At the `)` of an `if` or `while` statement.
* After performing the implied `HasValue()` call in a `for` statement.
Per informal agreement with leads, this means we lifetime-extend all
temporaries created in the initializer of a name-binding declaration to
the full scope of that declaration, but that temporaries created in an
expression statement are destroyed at the `;`.
Destroy local variables and temporaries at each `}`, and when branching
with `break` and `continue`. In `for` statements, destroy loop variables
along with anything created within the loop at the end of each loop
iteration, and destroy the cursor and range object when the loop
terminates.
Assisted-by: Gemini via Antigravity
---------
Co-authored-by: Geoff Romer <gromer@google.com>
Implement the toolchain side of proposal #7254, removing the `:!`
binding
syntax for generic and template parameters in favor of the keywords
`generic`,
`template`, and `runtime` plus contextual defaults for phase.
For valid programs this is semantics-preserving: each binding resolves
to the
same phase, and produces the same SemIR, as it did under `:!`/`:`. The
parser
derives a binding's phase from its syntactic context plus any explicit
phase
keyword; new diagnostics and error recovery for misused keywords are
described
below.
Implementation details for each component:
- Lexer: remove the `:!` (`ColonExclaim`) token, move its virtual
parse-node
budget onto `:`, and add the `generic` and `runtime` keywords.
- Parser: thread a `BindingContext` (`ExplicitParam`, `DeducedParam`, or
`CompileTimeEntityParam`) from declaration introducers down through
parameter
lists to each binding pattern, using a one-token lookahead to
distinguish a
name-qualifier parameter list from a declaration's own final list.
Parameters
of a compile-time entity (`class`, `interface`, `constraint`, `choice`,
`alias`, `export`, `namespace`) and deduced `[]` parameters default to
checked
generic; explicit function parameters and local bindings default to
runtime.
`HandleBindingPattern` resolves the phase from that context plus the
keyword: a
`generic` keyword needs no node of its own (the phase is carried by the
binding's node kind), while a `runtime` keyword is preserved as a
`RuntimeBindingName` node so `check` can name it in a diagnostic. A
phase
keyword that is merely redundant with the contextual default is
diagnosed
here, without invalidating the parse tree.
- Check: a phase keyword that is invalid for its context (for example
`runtime`
on a checked-generic parameter) is diagnosed here, and recovers by
building an
error binding that still introduces the name so that later uses of it do
not
produce cascading errors.
The removed `:!` syntax is now rejected as an ordinary parse error.
The `form`/`:?`/`->?` ("extended types") portion of proposal #7254 is
left for a
separate change.
Assisted-by: Claude Code
In #7436 we stopped substituting `.Self` when collecting witnesses out
of a facet type. While this was correct, it did not capture all the
cases that need to avoid substituting `.Self`. And it poisoned the
`IdentifiedFacetType` cache by not replacing `.Self` but storing the
result in the cache. This led to incoherent behaviour, where the result
of an impl lookup would change depending on which ones had been done
previously.
Now we use a flag to track for each `.Self` if we're currently
type-checking inside the scope where it was introduced in a facet type.
While inside that scope, identify should not replace the `.Self`. Any
use of it should remain as-is since we don't yet know what value will
replace it. We call this state "frozen" since it should not be modified
by identify. This requires a substitution step when we leave the scope
that introduced the `.Self`, to remove the flag. The flag is set in the
`EntityName` of the `SymbolicBinding`, and is part of the canonical
value, since `.Self` can become part of types, which are constants, and
the flag needs to follow it for correct behaviour.
We also have to ensure the flag is the same when doing comparison with
constants from inside a facet type and constants from outside. For
instance in `(Z where .Z1 = ()) where .Z2 = .Z1`, when we arrive at the
second `.Z1` its `.Self` will be frozen, while the `.Z1 = ()` contains a
non-frozen `.Self`. So we add the frozen flag to the first when storing
it in `where_stack` in order to compare the constant values of the two
`.Z1`.
The `WhereExpr` requirement inst kinds now have an `InstConstantKind` of
`AlwaysUnique` instead of `Never`. This allows us to add them to the
usual InstBlocks, and in an `eval fn` body they have a constant value,
so eval does not fail when trying to call that function. We have to be
careful to not consider `AlwaysUnique` as being actually concrete
though, since their constant value erases `.Self`-dependence. This
allows us to stop special casing them when thawing the requirements
block in a `WhereExpr`, and we can just thaw each `InstId` in the block
in a straightforward manner.
We add the new flag to the instruction's fingerprint and name in
formatted semir.
This adds SemIR structs and implements building `observe` lists, as well
as naming, formatting, and importing `observe` declarations.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
In some cases the pattern block can depend on the initializer, so it
must be sequenced after it. See #7469 for a more detailed explanation of
why this is necessary.
In `PerformActionHelper`, use the unqualified type for lookup.
In `PerformInstanceBinding`, propagate qualifiers to the unbound element
type's class type when doing the `ConvertToValueOrRefOfType` conversion,
and to the element type when forming the `ClassElementAccess` instr
(except for `partial`, which is only used if the member being accessed
is `base`).
In handle_operator.cpp, prevent assignment to a reference to a const
type.
Move the existing derived->base conversion earlier in
`PerformBuiltinConversion`, into the block that handles qualifier
conversions. This allows, for example, converting from `partial Derived`
to `partial Base` -- see the tests in
`toolchain/check/testdata/class/inheritance/derived_to_base.carbon`.
Notably this allows accessing fields in an abstract base class via a
derived class without going through `base`. E.g.
`my_obj.field_in_base_class` rather than
`my_obj.base.field_in_base_class`.
In `Convert`, allow forming a value or reference of abstract class type,
but not an initializer.
For now, limit the scope to just `ClassElementAccess` to avoid affecting
tests where I'm unclear if allowing abstract types is correct.
The bulk of this change is changing most pattern insts to be `Always`
rather than `AlwaysUnique` constants, so that they can be wrapped in
`SpecificConstant`s to perform substitution. That then lets thunking
rely much more on `SpecificConstant` wrappers instead of deep-copying
the inst tree with modified types.
This approach to thunking should scale better, particularly as things
like form generics make function signatures more complex, because we can
leverage the existing support for constant evaluation and substitution.
Unfortunately, applying this approach to binding patterns will require
more work; see the TODO near the top of `thunk.cpp` for details.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Implements proposal #7016: `self` moves from the deduced implicit list
(`fn F[self: Self]()`) to the front of the explicit list. Its type may
be written explicitly (`fn F(self: Self)`) or omitted, in which case it
defaults to `Self` (`fn F(self)`, `fn F(ref self)`); `self` in the
implicit list is rejected.
Throughout checking, `self` is modeled as the first explicit parameter.
Because a method is just a function whose first parameter is `self`, it
can also be called as an ordinary function with the receiver passed
explicitly (`Type.M(obj, ...)`), not only as `obj.M(...)`. A new
`SemIR::CallArgParamPatterns` helper chooses the parameters matched
against the explicit arguments, excluding a leading `self` only when it
is supplied as a method-call receiver; arity checking, conversion, and
generic deduction use it. The resulting SemIR and lowering are
unchanged: `self` is still `call_param0`, and witnesses, thunks, and
vtables are unaffected.
An omitted `self` type is parsed as a `SelfBindingPattern` node with no
type expression; checking synthesizes the `Self` type so it behaves
exactly like `self: Self`. However, the exact spelling used must match
between a forward declaration and a definition, following #3763's rules
around declaration matching.
Generated functions, thunks, and C++ interop import/export build `self`
as the first explicit parameter, and the `self`-type override (e.g.
Derived->Base for a virtual override) applies to the explicit `self`.
Placement is validated by new diagnostics: `SelfInImplicitParamList`,
`SelfNotFirstParam`, and `SelfOutsideParamList`. The benchmark source
generator and the documentation adopt the `(self)` shorthand; the
prelude, the examples, and the test data are migrated in the following
commits.
Assisted-by: Claude Code with Claude Opus 4.7
---------
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Adapters were erroneously satisfying `Core.Destroy` because we were
directly getting the object's representation without consideration for
abstract and adapted types. This change ensures that adapted types'
representations are used instead of the adapter types.
This helps us move away from the clone-with-modifications approach to
thunking, which gets unwieldy as signatures get more complex.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
We exposed `Core.IntLiteral()`, `Core.FloatLiteral()`,
`Core.CharLiteral()`, and `Core.Bool()` as functions as a workaround,
because we had no way to provide the type names without parentheses that
the design requests. But now we can do so, by using an alias. Switch all
of these over from being functions to simply being names of the
corresponding types.
Assisted-by: Gemini via Antigravity
Fix import logic to make all imported packages be children of the
`NameScopeId::Package` scope. Previously, indirectly-imported packages
would end up as children of their importing package's scope, which
resulted in them not being treated as packages at all, and in particular
not being fingerprinted as packages.
Fixing that caused a failure in the fingerprinting logic as we started
to encounter packages with no correspoding import scopes. Instead of
looking for import scopes, use a simpler mechanism to map packages to
their package names, and clean up.
Unfortunately the latter change churns all the fingerprints again :(
Hopefully this is the last time for a while.
Fix a lowering crash when lowering a return by reference of a type with
an in-place initializing representation. We previously misinterpreted
this as an in-place initializing return.
This is addressed by changing lowering to interpret a `ReturnExpr` of a
reference expression as a reference return. However, that exposes
another issue: `return var;` produces a `ReturnExpr` of a reference
expression in the case where it returns in place! To fix that, we switch
`return var;` to producing a `ReturnExpr` of a value expression
regardless of whether the function has a return slot. This makes the
representation of `return var;` more uniform:
* If the expression is a reference, we're performing a `ref` return.
* If the expression is an initializing expression, we're performing a
normal by-initialization return.
* If the expression is a value expression, we're performing a `return
var;`.
When we import from another library in the same package, its entities
end up with our library as their parent scope, resulting in cross-file
fingerprint mismatches. Instead, only include the library ID when
fingerprinting either a package-private entity or an `ImportIRId` that
refers to a particular `SemIR::File`.
Include the library name in the fingerprint of an entity declared
`private` at namespace scope. Include the entity's fingerprint in the
mangling of a library-private entity.
This fixes miscompiles if two libraries in the same package declare
`private` entites with the same name. We can't fix this with internal
linkage because library-private entities can be reachable through
generics defined in the API file of the library.
Assisted-by: Gemini via Antigravity
As suggested in [1], replace `FieldInitializerMap` with a `FieldStore`.
The corresponding `FieldId` is now stored in `FieldDecl`. To make room
for the `FieldId`, the `ElementIndex` is now stored in the `Field`,
along with the initializer.
In import_ref.cpp, resolving `FieldDecl` initializers is now supported,
and in convert.cpp `LoadImportRef` is called to do so. The
`field_initializer_import.carbon` test now passes.
Printing a `FieldDecl` instruction now prints the initializer as well,
if present. See field_initializer.carbon for an example.
[1]:
https://github.com/carbon-language/carbon-lang/pull/7238#discussion_r3283217158
The `unused` modifier is rejected on parameters of a function
declaration, but the check only covered the explicit parameter list, so
an implicit parameter (such as self or a compile-time binding) could
carry unused without a definition. Check the implicit parameter list
too.
The code changes and the test updates are split into two commits for
easier review.
Assisted-by: Claude Code with Claude Opus 4.7
---------
Co-authored-by: Christopher Di Bella <cjdb.ns@gmail.com>
If a keyword or a sized type literal (eg, `f2`) is used in a context
where we are confident that we are expecting an identifier -- either
before a `:` in a binding pattern or after a `.` in a member access or
designator -- then recover as if a raw identifier was used.
This appears to be a particular stumbling block for coding agents, so
seems worth paying special attention to.
Add a mechanism to the tokenized buffer to track additional tokens
synthesized for error recovery so that we can keep the lexed token
sequence immutable and still satisfy the invariants throughout the rest
of the toolchain for recovery tokens. Thanks to chandlerc for suggesting
this approach!
In handle_let_and_var.cpp, field initializers are now handled like
regular `var` initializers, by calling `LocalPatternMatch`.
In pattern_match.cpp, `FieldDecl`s with initializers are handled by
storing a value in `SemIR::File::field_initializers()`. This is a new
map where the keys are `FieldDecl` `InstId`s and the map values are
`InstId`s representing the initializer value.
In convert.cpp, `ConvertStructToStructOrClass` now has a `get_default`
function parameter that callers can use to provide a field default.
`ConvertStructToClass` uses this to provide a default from field
initializers.
Fixes link failures when referencing a symbol involving a fingerprint
from a different package.
Previously we included the `Namespace`'s `import_id` as part of its
fingerprint, which caused local and imported namespaces to get different
fingerprints. We now store the `import_id` on the `NameScope` instead of
on the `Namespace` inst to avoid this problem.
Also, when we reach a package-level `NameScopeId`, consistently
fingerprint it as a (package name, library name) pair. Previously the
fingerprinting depended on whether it was imported or not, as an
imported `NameScopeId` had a parent scope (the current package). We need
to include the library name here so that private entities with the same
name in different libraries have different fingerprints.
When a class extends an interface, referring to a member name of the
interface as an unqualified name should refer to the class's
corresponding associated entity value, not to the associated entity
itself. Similarly, in an `impl`, unqualified names of associated
entities should refer to the `impl`'s corresponding value for that
entity.
To support this, we treat `impl`s as `extend`ing their implemented facet
type, and we make lookups into an extended facet type use the `Self`
type of the extending `impl` or `class` if lookup finds an associated
entity. We already did the latter if the extending entity was an
interface; this extends the existing support for these other cases.
This adds the `static` token to the lexer and parses it as a modifier.
In check, `FullPatternStack::Kind::FieldDecl` is now used for both
static and non-static vars. Static vars get treated basically the same
as `NameBindingDecl`s.
Global initialization is used for static var initializers. To make the
necessary stack information available to `pattern_match.cpp`, the
`full_pattern_stack` and `decl_introducer_state_stack` are now popped
later in `handle_let_and_var.cpp`.
In lowering, each class's body is checked for `VarStorage` insts and
lowered the same as global vars.
Class vars are still restricted to simple `name: type` bindings, not
full patterns. This is now handled in the check phase instead of during
parsing.
This is in preparation for supporting `static var`.
For now, hide `override fn`s from name lookup, so that the base class
version is always used, as the derived-class version does not have its
own vptr entry and so would not do the right thing if a further-derived
class adds a new override. This is implemented via a new access kind of
`Hidden`.
When checking the overriding function, pass in the expected `Self` type
and check the `self` parameter against that; the signature that we
generate for the thunk in the derived class is the base class signature
with the `self` parameter's type changed to the derived class.
When we generate a thunk for a virtual function, the thunk is assigned a
`virtual_index`, and the virtual function itself is not. When the thunk
makes a direct call to the virtual function, recognize this situation by
checking for a `virtual_index`, and perform a non-virtual call if there
isn't one.
Assisted-by: Gemini via Antigravity
When an outer type defines an `extend` relationship to an inner type, we
require that inner type to be complete so that we can know that name
lookup can search both scopes as soon as the outer type is complete.
When doing name lookup, we require the type in which we are looking to
be complete. Then, we recursively add extended scopes, but then also
require each of them to be complete again, which inserts
RequireCompleteType instructions into the block doing lookup.
While these new instructions may differ in terms of their specifics,
they are redundant since we already required the type to be complete,
and specifics can not change the completeness of a type. They are also
problematic because a named constraint or interface can extend a scope
with a symbolic specific, by using `Self` as an argument. This inserts a
symbolic instruction into the block doing name lookup, even though that
block may not be generic.
Implement the alias rules from proposal #5389, wherein an alias is
permitted so long as the target has a constant value. While that
proposal is not yet accepted, this seems like a reasonable basis for
further iteration, and will be useful for the examples we're currently
pursuing.
This lets us stop eliding it in textual semir tests with dump ranges.
Previously it would always get elided, even though it was part of the
range being dumped, and was referred to by other instructions in the
dump range.
Since each `.Self` is unique (can change its type if not its value) in a
facet type, having each one distinct by location also aids
understanding.
See
[here](https://docs.google.com/document/d/1rWcueFwIfZox6GKVGxiUG4cBzjrZ6djXiIDGyJDtrE4/edit?tab=t.0)
for the design doc.
This also removes the default value of the `result_type_inst_id`
parameter of `HandleAction`, moves it before the action in the parameter
list, and documents it. This solves two problems:
- The default made it easy to forget, leading to unnecessary
`TypeOfInst` instructions.
- When it was present, putting it after the fairly "bulky" action
argument tended to make the callsite harder to read.
- A function with a return declaration always has exactly one
`ReturnSlotPattern`, representing the whole return declaration (whereas
previously that was omitted for value and reference returns).
- The `ReturnSlotPattern` always has a subpattern with the same form.
`OutParamPattern` already plays that role for initializing forms, and
`TuplePattern` will play that role for tuple forms. This change
introduces `ValueReturnPattern` and `RefReturnPattern` to represent
value and reference return forms.
- As before, the `ReturnSlotPattern` has a corresponding `ReturnSlot`
that represents the output that is initialized by a `return` statement.
Its structure parallels the structure of the `ReturnSlotPattern`, so we
need `ValueReturn` and `RefReturn` insts that correspond to
`ValueReturnPattern` and `RefReturnPattern`.
This is a step toward supporting generic return forms, where the
`ReturnSlotPattern`'s subpattern may be an action: this change ensures
that evaluating the action for a specific form produces the same SemIR
as if the form were concrete to begin with. More speculatively, this
should simplify the implementation of `return` statements with compound
return forms.
---------
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Fix some situations where we'd drop the storage argument when building
an in-place initializing expression. We now guarantee that an expression
with the in-place initializing category always has a storage argument.
This is only fixing the decision about *whether* to produce a witness.
Implementation of the witness is still a TODO, though where a body is
generated, it should also precisely reflect where one _needs_ to be
generated.
Note the tests:
- toolchain/lower/testdata/function/generic/import_core_witness.carbon
- toolchain/lower/testdata/function/generic/import_unused_def.carbon
These tests can probably be produced _without_ Core.Destroy, but I found
the essence of them while trying to build //examples with Core.Destroy
and a simpler minimization wasn't striking me.
Assisted-by: Google Antigravity with Gemini
---------
Co-authored-by: jonmeow <jperkins@google.com>
This will be used for const-evaling functions. Splitting into a separate
commit since it touches a lot of test files, and a couple fail_todo
tests are no longer failing.
EvalOrAddInst has to create a non-canonical instruction for evaluating a
few typed insts, such as LookupImplWitness which uses an InstId to
provide a location for diagnostics.
But the output of the function is a ConstantId. We do not have access to
the non-canonical InstId after the function returns. But if the constant
value was symbolic, it was being attached to the inst, and the inst
would be added to the eval block of the enclosing generic. This
needlessly added semir for a symbolic value.
The ConstantId returned by EvalOrAddInst can be used immediately, such
as to evaluate an ImplWitnessAccess. In that case, the final evaluated
result is all we need to keep in semir.
If the ConstantId needs to be replaced by specifics, it is only as part
of some other instruction, since ConstantIds themselves are not modified
by specifics, instructions are. In that case, the canonical instruction
in the constant value would have been added to some other (now symbolic)
instruction, which would be replaced by a specific.
This has no functional change, but it reduces runtime overhead and semir
output for LookupImplWitness and ImplWitnessAccess.