Move the operation of resolving the specific decl block from
`GetConstantValue()` to `TryEvalTypedInst()`, with is now happening
after replacing the fields of the instruction with new constant values,
but before running the evaluation of the instruction. Since imported
instructions are not evaluated, this avoids resolving the specific decl
block from imported instructions, resolving a TODO in
`AddImportedConstant()`. Now `AddImportedConstant()` can replace
constant values in its fields without having to worry about that
operation resolving any specific decl blocks.
We get to add a new TODO however, to explain why we still need a special
case in resolving specific decl blocks for handling `Impl` construction.
The witness table contains instructions with specifics referring to the
generic self of the impl declaration. But the table must be constructed
before the impl's generic is finished, in order to make the instructions
dependent for the generic. But then resolving the specific decl block
can't be done when the instructions are created and evaluated, as that
requires a finished generic.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Outside of `match_first` this adds diagnostics for invalid non-final and
final `impl` declarations in line with those being proposed in
https://github.com/carbon-language/carbon-lang/pull/5337.
- Two non-final `impl`s with the exact same type structure is invalid.
- A `final impl` that matches the self/constraint of another `impl` as a
query would always be preferred, making the second one invalid.
- Two `final impl`s that overlap (have compatible type structures) in
different files is invalid.
- Two `final impl`s that overlap (have compatible type structures) in
the same file is invalid outside of `match_first`.
- A `final impl` in a different file from its root self type and
interface is invalid.
We add tests for all these scenarios as well as correct scenarios.
The "compatible" test for two type structures was being done
symmetrically, which is incorrect. We want it to test that a query type
structure is the same _or more specific_ in a compatible way with an
impl's type structure. This is corrected in the implementation, and the
diagnostics now have to test both directions to get the desired output,
as expected.
---------
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
- Track the `VarPattern` instruction on the `VarStorage` instruction so
that it's available for name mangling.
- Mangle global variables based on the first binding name within their
pattern.
- Give global variables external rather than internal linkage, except if
they have no bindings whatsoever in their pattern.
- To support lowering references to bindings nested within a global var,
such as for `var (x: i32, b: i32)`, add some basic initial support for
reference constant expressions. Treat a global `var` as a reference
constant, and treat an aggregate access into a reference constant as a
reference constant.
This restructures the import and merge logic to support parameter
patterns in a more scalable way.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
When a `LookupImplWitness` instruction is created in a generic function
for a witness obtained from a `BindSymbolicName`, it stores the
`BindSymbolicName` as the query self type along with the interface it
obtained from it.
Later, when an argument is substituted into the `LookupImplWitness` in
deduction, and it is re-evaluated, the `BindSymbolicName` in the query
interface's specific arguments was being substituted, but the same
`BindSymbolicName` in the query self type was not. This was because we
did not substitute into the type of `BindSymbolicName`. In this case the
type is a `FacetType` which has inside it one or more specific
interfaces. The same substitution needs to be applied to both the
interfaces in the self type as to the interfaces in the query.
This issue was found by a fuzzer - though in a weirder and more invalid
way, by putting all of the code for our test case inside an `interface`,
which creates an implicit generic `Self` in the enclosing context and
yet makes it concrete inside a function body.
A fuzzer found that converting a pointer to a `FunctionTypeWithSelfType`
to `type` does an impl lookup and ends up in TypeIterator with the
`FunctionTypeWithSelfType` being iterated over in the self type, where
we crash. It's a valid type, so the iterator should be able to walk over
and return it.
We also constructed a similar example for `FunctionType`.
I think this would probably have prevented the missed include in #5469
-- it would've just failed completely with a "missing prelude"
diagnostic.
Also note this excludes the included IR from output, because it's
probably low-value to print.
We were importing all impls as non-final, since we forgot to set the new
field when constructing the imported Impl. Adds a test that fails before
this PR, since the imported Impl is treated as non-final.
Such impls will never be used, so they should not exist. And test that a
final impl partially overlapping a non-final impl is accepted.
There is a question about a final impl partially overlapping a final
impl that is part of
https://github.com/carbon-language/carbon-lang/pull/5337
The TypeStructureBuilder recursively iterates through a type, interface,
or facet value and constructs a type structure that includes each
concrete and symbolic value found. This iteration is a more general
thing that can be useful elsewhere. For instance, to get just the root
type out of a general type, it is the result of the first iteration
step.
We abstract out the iteration logic into a SemIR::TypeIterator to create
a clear boundary between the work of iterating and the work of building
the TypeStructure from it.
Along the way this pointed out some issues in the TypeStructureBuilder
where it could have ambiguity between types that include non-type
values. So we add some tests for these cases, and they now pass. There
are also TODOs left behind, as concrete TypeStructure is overly specific
right now in order to keep these tests passing, which means that the
concrete elements can't be used for impl lookup matching yet. Only the
shape of concrete vs symbolic is used for now, and then type deduction
is used to compare the actual concrete types, which could be skipped
when the concrete values could be compared directly and reject an impl
for not matching.
Instead of building the definition of a thunk immediately when we
generate the thunk declaration, wait until we reach the `}` of the
outermost class, interface, etc. -- at the same time when we would parse
the definition of the thunk if it were defined inline.
This fixes issues where we fail to define the thunk because it requires
an enclosing class to be complete, or its definition depends on
something declared later in the enclosing class.
Make the representation of a suspended function scope, and its
constituent suspended components, be move-only, and switch to passing it
around by rvalue reference instead of by value because it's expensive
both to move and especially to copy.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This is fixing a deduce crash, with regression tests added in
binding_pattern.carbon. In `needs_substitution`, it adds the
`BindSymbolicName` with the compile time bind index corresponding to the
wrong generic scope, which causes a bad result. It appears
`needs_substitution` logic is no longer needed (per zygoloid,
`CheckDeductionIsComplete` handles related issues) so can be removed.
This changes the order of IR in use_assoc_const.carbon but the result
appears equivalent to me.
This was a fuzzer-found crash.
The canonical location of the instruction may be an entirely different
instruction, which the instruction in question was not imported from. In
particular, we shouldn't assume that we can use the constant value of an
instruction that the *location* of an imported instruction refers to as
the constant value of the imported instruction.
The only time we should be looking at the `ImportIRInstId` for a `LocId`
is when determining its location in some other file.
Fixes a crash when importing thunks (which can contain instructions
whose location points to an instruction in a differnt IR).
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
When two non-final impls have the same type structure (neither is a
specialization of the other), it is an error unless they are within a
`match_first` block. For now, we don't have `match_first` implemented,
so it's always an error.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
A final impl must be written in the same file as the root self type or
the interface. This provides tests that should fail but don't yet for
writing a final impl in a third file that defines neither, as well as a
blanket final impl over an interface outside the file that defines the
interface.
When we fill the witness table with errors, set the witness id to an
error too, which signals to impl lookups to not use the impl.
Make the use of the `Impl` from the store more consistent once it's been
added to the store (or known to be there already).
When checking whether we can use the function in an impl directly to
satisfy a signature in an interface, allow the parameter names to differ
between the two declarations.
Instead of building an eval block as a separate pass at the end of a
generic, build the eval block incrementally.
The larger change here is that asking for the type or constant value of
an instruction now always returns an unattached type or constant value,
in order to preserve the behavior that we previously achieved by doing
the rewrite to attached types and constant values at the end of handling
the generic.
This also incidentally fixes some subtle issues where attached types and
constant values would leak out into check and cause it to get confused
about differences between attached and unattached values. Check should
no longer see attached values except where it explicitly asks for them.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
Don't import `ImplWitnessTable` into the `constants` block, because we
generally don't put `Unique` constants there. This matches the handling
of the other kinds of `Unique` constants. In order to keep the
instruction visible in formatted SemIR, add it to the `imports` block
instead.
Also fix a bug in the instruction formatter that resulted in
instructions in the `imports` block being omitted from the output if
they were only referenced by earlier instructions in the `imports` block
and by instructions in the `constants` block. This was already resulting
in some referenced instructions being omitted from the output, but also
occurred frequently for `impl_witness_table` instructions after this
change because it is common for the only reference to those instructions
to be from `impl_witness` instructions in the `constants` block.
Once a concrete result has been found, it's not legal to write an `impl`
that would change the concrete result afterward.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
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.
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).
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>
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.
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.
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.
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.
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`.
This allows us to import the table for a given impl only once, while we
can import many ImplWitness instructions with different specifics for a
generic impl.
For example in convert_facet_value_to_narrowed_facet_type.carbon we see
that a single witness table is imported for the BitAnd interface, with
multiple witnesses (for different specifics) imported and sharing the
same table.
The ImplWitnessTable now contains a back-link to the Impl the witness is
for, allowing inst namer to name that interface in the textual semir,
and allowing the interface to be found when debugging from a witness.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
In preparation for shifting from `TypeId`s potentially representing
attached types to always representing unattached types, using
[terminology suggested on
Discord](https://discord.com/channels/655572317891461132/963846118964350976/1359286326779973712).
This change causes us to track slightly more type spelling information
through SemIR.
One change that has significant impact on the SemIR output is that we
now build a `struct_type` instruction in each class representing the
types of the fields, including the spelling used for those types. This
is now no longer always identical to the corresponding canonical
`struct_type` for the object representation, so it's built separately
and owned by the class.
Also remove `TypeBlock` support entirely, as its only use was
representing `TupleType`s, which now use an `InstBlock`.
Use it to stringify associated constant values in diagnostics. In
passing, add missing support for stringifying bool literals. Note that
there are some cases that it doesn't stringify properly, but that's not
new here; such cases could already be observed when stringifying generic
arguments.
While facets may come with a rewrite for an associated constant, they
are symbolic. A final impl has the ability to provide a concrete value
instead, which allows generic code to use the concrete value in place of
the associated constant's (fully qualified) name.
For instance, instead of `I.Type`, the concrete type `()` can be used if
there is an `impl final [T:! type] T as I where .Type = ()` impl.
This does not yet cache the result of the lookups.
Depends on https://github.com/carbon-language/carbon-lang/pull/5255
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This follows the pattern used elsewhere, and allows facet types in eval
blocks to directly reference their operands instead of doing so
indirectly via a `ConstantId` attached to the generic. This prepares us
for making `ConstantId`s always be unattached.
In passing, add a stringified version of the `InstId` to diagnostics in
a couple of places where it seems useful.
Unintentionally, we were adding ImplWitnessAssociatedConstant to the
witness table and then immediately evaluting and replacing it with its
constant value instruction, which is incorrect. The point of the
instruction is to be a symbolic value in the witness table that is a
dependent of the generic impl declaration being built.
This gives a slightly simpler representation for `UnboundElementType`s
in eval blocks, and in principle allows us to preserve the spelling of a
field's type into the `UnboundElementType` and thereby into a field
reference, although as of right now this doesn't affect our diagnostic
output in any way.
During error recovery for a field with a non-concrete type, preserve the
type in the `UnboundElementType` regardless. It's not really problematic
to have a non-concrete type there, and this makes it easier to track the
instruction used to specify the type.
This is a step towards switching symbolic types to always be abstract
during type checking.
Use that instead of `AddInstInNoBlock` to get the value of an
instruction when evaluation might depend on the `InstId` but only the
`ConstantId` of the instruction is desired by the consumer.
Instead of using None, use an explicit ImplWitnessTablePlaceholder in
the witness table for entries that have not yet been populated, to aid
debugging. This would ensure they would show up very clearly in the
SemIR. This uncovered some `<invalid>` in the SemIR under erroneous
conditions that have now been turned into `<error>`.
Add the ImplWitnessAssociatedConstant instruction which wraps the
canonical instruction found from the constant value of the rewrite
constraint. This ensures that we have an instruction inside the eval
block for a generic impl declaration for each rewrite constraint's
value, which allows Subst to be performed to rewrite the symbolic
constant of the ImplWitnessAssociatedConstant instruction to associate
it with the generic. This will prevent the otherwise orphaned symbolic
constant of the rewrite's value from being used which can not have a
specific applied to them.
While applying the new insts in InitialFacetTypeImplWitness(), rearrange
the function to use less nesting. And avoid using entity names from
imported instructions (as we found is not effective in deduce.cpp) and
use a local instruction by going through the constant value.
This PR is part of the effort to allow a rewrite to name a generic
parameter, such as `impl forall [T:! type] T as Z where .X = T`, however
tests for this involve a final impl so that we can typecheck that the .X
value is a specific T, so the tests will come with that work. This piece
is split off because introducing new instructions causes a lot of SemIR
churn, and I wanted to get that done separately.
For each kind of instruction, specify whether its constant evaluation
needs an `InstId` or not. If it does, ensure that all constant
evaluation of that instruction provides one. Otherwise, allow calling
into the evaluator without providing an `InstId`.
This allows us to reliably use the `InstId` in evaluation steps that
either need a location or need to look at the original operands of the
instruction prior to evaluation, and also to support `TryEvalInst` calls
safely for instructions whose evaluation does not need an `InstId`.