Commit Graph
45 Commits
Author SHA1 Message Date
Dana JansensandDavid Blaikie fb12984713 Forbid nested where inside a where expression through eval (#7397)
In #7378 we forbid writing `where` on the RHS of another `where`
expression. However it's still possible to inject a `where` expression
through eval, using an `alias` or an `eval fn`. We address this by
looking in the constant value of constraints of a `WhereExpr` (which
sees the outcome of eval) and searching for a nested `where` there. We
can determine a facet type was written with a nested `where` by seeing
that it has some non-extend constraint.

---------

Co-authored-by: David Blaikie <dblaikie@gmail.com>
2026-06-26 18:31:26 +00:00
Dana Jansens b22ee48c9b Forbid nested where inside a where expression (#7378)
This disallows building a facet type that contains another facet type
with non-extend constraints in it. Which in turn prevents the
possibility of introducing a different `.Self` into a facet type.

Eval can still insert a facet type with non-extend constraints, as we
only prevent it for `where` being written into the facet type. There is
a TODO in handle_where.cpp for this and some tests in
toolchain/check/testdata/facet/nested_facet_types_from_eval.carbon
2026-06-25 18:56:36 +00:00
Dana Jansens b6774ab4c8 Remove TODO in impls handler that is already done (#7305) 2026-06-04 20:47:07 +00:00
Dana Jansens e7ed217d4e Require all constraints in where to have a designator (#7282)
Instead of requiring just one to have a designator, require each one.
You can't write `(type where A == B) & (type where C == .Self)` because
`A == B` has no designator. If the two facet types are combined into a
single `where` syntactically, their meaning does not change, and what we
allow should not change either. That is, `type where A == B and C ==
.Self` should be rejected since `A == B` does not contain a designator.

The design is also updated to make this clear.
2026-06-02 17:11:59 +00:00
Dana Jansens 42a4dba9fd Makes impls constraints available to use in later constraints within a facet type (#7209)
If a facet type contains `.X impls Y` then later references to `.X`
should know that it impls `Y`. This is done through a stack on the
context like for rewrites, where impl lookup can find constraints from
the current `where` expression being checked.

Similarly, if a facet type contains `.X impls (Y where .Z = T)`, then
`.X.(Y.Z) = T` should be available to later constraints in the facet
type for early application of rewrite rules. We add these rewrites to
the rewrite stack when handling the `impls` constraint
2026-05-15 18:53:51 +00:00
Dana Jansens 4d1a61de29 Don't consider designators in a nested facet type as constraining the current type (#7139)
The design says:
> We don’t allow a where constraint unless it applies a restriction to
the current type. This means referring to some
[designator](https://docs.carbon-lang.dev/docs/design/generics/details.html#kinds-of-where-constraints),
like .MemberName, or
[.Self](https://docs.carbon-lang.dev/docs/design/generics/details.html#recursive-constraints).
--
https://docs.carbon-lang.dev/docs/design/generics/details.html#constraints-must-use-a-designator

A nested facet type in a constraint does not constrain the current type,
with the exception of the LHS of a nested `where` in an impls
constraint. Diagnose this appropriately by not recursing into unrelated
parts of nested facet types to look for designators.

Before this change, this facet type is accepted:
```carbon
fn F(unused T:! Z where C impls (Y where .Y1 = .Y2)) {}
```

But then no calls to `F` work, since the `.Y1` and `.Y2` designators are
never resolved to anything from the caller, as they do not depend on `T`
in any way.
2026-05-04 16:42:06 +00:00
Dana Jansens 88931a4196 Give the .Self instruction a location (#7147)
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.
2026-05-04 14:45:06 +00:00
Dana Jansens 46bb0fecd4 Properly diagnose ambiguous .Self in T impls X where... (#7132)
A `where` expression nested inside a `T impls X` constraint makes
`.Self` ambiguous on the right-hand side of the `where` if `T` is
anything other than `.Self`. After the `where`, the value of a `.Self`
could be `T` or could be the value of `.Self` before the `impls`
constraint: the so-called top-level value of `.Self`.

Implicit use of `.Self` in designators is always allowed, and they are
bound (and replaced by a reference) to the inner-most possible value of
`.Self`. On the right-hand side of the nested `where` above, they have
the value `T as X`.

`.Self impls ...` is also always allowed, since it acts more as a
keyword here, and it always refers to the inner-most possible value of
`.Self`.

Any other explicit use of `.Self` is diagnosed when ambiguous, in any
kind of constraint. This is done in the handling of `WhereExpr` since it
has enough context to allow `.Self impls` (which is an explicit use)
while disallowing other explicit uses. And because it has non-canonical
instructions to work with, so it is able to diagnose errors with precise
locations.

Since `.Self` is no longer going to be marked with depth modifiers, the
eval of `WhereExpr` does not need an input facet value instruction
representing `.Self` to compare with, as they are now going to all be
equivalent. So revert it back to just looking for the `PeriodSelf` name
id, through a shared helper being introduced as `IsPeriodSelf`. And drop
the period self InstId from the `WhereExpr` instruction. This causes
most of the formatted SemIR changes.

Move helpers for working with and replacing `.Self` to their own file,
out of the `facet_type.h` header/cpp files. These are working with
`.Self` facet values more than facet types, though `.Self` is a name
that only exists inside the scope of a facet type.
2026-05-01 21:22:32 +00:00
Dana Jansens 554b1b8d10 Remove SymbolicBindingType (#7114)
This inst was meant to support tracking the depth of a `.Self` facet,
but we have now implemented substitution of `.Self` in facet type
identification, and in eval of where expressions, without needing to
track the depth.

See history here:
-
[2025-06-30](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.4qd5dkyfn2k3)
-
[2025-07-07](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.7urbxcq23olv)
- #6026
2026-04-27 19:04:59 +00:00
Dana Jansens 12d7574636 Include extended named constraints in the type of .Self for a where clause (#7048)
The `.Self` should see all extended constraints from the LHS of the
`where`, which is both interfaces and named constraints.
2026-04-10 18:05:22 +00:00
Dana JansensandRichard Smith cc5a42691e Add where T impls X constraints into the FacetTypeInfo (#7038)
This makes them part of the identified facet type, and we can see the
constraints as part of stringify and format output.

But this does not do enough to make them useful yet: Any `T impls X`
constraint must contain a reference to `.Self` somewhere. And `.Self`
references do not get substituted, so neither `T(.Self) impls X` and `T
impls X(.Self)` will match against an incoming facet value derived from
an `impl T(U) as X` or `impl T as X(U)`, since `U` and `.Self` are never
the same thing until `.Self` can be substituted.

Now that impl lookup runs into facet values containing `.Self` (a
symbolic binding), such as in `C(.Self)`, we were crashing assuming the
type of `.Self` is a FacetType, but it can be `type` in the case of
`type where C(.Self) impls...`. Instead, use an empty facet type for the
type of `.Self` so it is always a facet. This assists with substituting
other facets into it, without having to insert an extra FacetAccessType.
`MakePeriodSelfFacetValue()` now enforces this requirement.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-04-10 14:29:36 +00:00
Dana Jansens 17180558e5 Diagnose where clause without a designator (#6995)
> We don’t allow a where constraint unless it applies a restriction to
the current type. This means referring to some
[designator](https://docs.carbon-lang.dev/docs/design/generics/details.html#kinds-of-where-constraints),
like .MemberName, or
[.Self](https://docs.carbon-lang.dev/docs/design/generics/details.html#recursive-constraints).


https://docs.carbon-lang.dev/docs/design/generics/details.html#constraints-must-use-a-designator
2026-04-01 04:16:35 +00:00
fdb188ccfd Implement unused pattern bindings, continued (#6518)
Implementation of unused pattern bindings #2022, continued.

Whereas previous PR #6460 took care of parsing, and PR #6479 prepared
the stage by using _ in some test cases, this PR has the the actual
implementation, using a simple dataflow analysis.

---------

Co-authored-by: Burak Emir <bqe@google.com>
Co-authored-by: jonmeow <jperkins@google.com>
2026-02-19 23:33:36 +00:00
Jon Ross-Perkins 2c6d9c7f66 Rename type's GetInstId to GetTypeInstId, reflecting returned type (#6708)
Discussed briefly [on
Discord](https://discord.com/channels/655572317891461132/655578254970716160/1470442830118912265),
done to reduce confusion.

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-09 22:00:21 +00:00
Dana Jansens e5c94b193d Use the new IsFacetTypeOrError function (#6438)
It is introduced in #6434
2025-12-02 22:33:55 +00:00
Dana JansensandJon Ross-Perkins 4b0e2b03b6 Add the .Self name for the type expression of a compile time binding (#5937)
We add a virtual node (`CompileTimeBindingPatternStart`) as the first
child of `CompileTimeBindingPattern` which holds the identifier
underneath it, so that it is checked just before the type expression of
the `CompileTimeBindingPattern`. When we reach this virtual node during
check, we add `.Self` as a name in the current scope, and when we reach
`CompileTimeBindingPattern` we remove it from scope, which ensures it's
present during only the checking of the type expression for the compile
time pattern.

At the moment the `.Self` has a different type (it's a `TypeType`) than
other `.Self` in the facet type (which are a single `FacetType`), but
the intention is to immediately substitute it out of the facet type
entirely, replacing it with a reference to the compile time binding (a
`BindSymbolicName`) itself. A TODO has been added for this.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-08-12 16:27:07 +00:00
Dana Jansens 3d77c4441b Compare ImplWitnessAccess into Self as canonical constants (#5883)
This makes all `.Self` references in a facet type canonically the same
(which will remain true iff they refer to the same `Self` type in the
future), removing the need to do more complex comparisons between them
using the EntityName, interface, and index. This allows the comparison
of types containing `.Self` references to be done correctly regardless
of where the `.Self` appears, as such type expressions will all be
canonically equal if they otherwise equal now, regardless of whether
they are written in the context where `.Self` could have seen different
`Self` facet types.

In order to retain access to constraints on a base `.Self` facet type,
in the case of applying `where` to an existing facet type, we:
- Give the base facet type as a `RequirementBaseFacetType` constraint so
that eval of `WhereExpr` can find and copy all the constraints off of
it.
- Introduce eager/early rewrite constraint resolution, which allows a
constraint to eagerly resolve access to earlier rewrite constraints
(`where .A = () and .B = .A` is eagerly transformed into `where .A = ()
and .B = ()`) before the full constraint resolution step. This allows
use of rewrite constraints in larger type expressions, such as `where .A
= () and .B = C(.A)` and `C` will know that the argument is `()`.
2025-08-08 18:36:39 +00:00
Dana Jansens 565f39480a Make the .Self entity name in a WhereExpr a canonical one (#5827)
This will allow reusing existing entity names when there are nested
.Self references in a facet type. They are canonical as the contents of
a .Self reference are all canonical.
2025-07-18 20:42:16 +00:00
Jon Ross-PerkinsandGeoff Romer 03e693873b Detect control flow in entities nested inside functions (#5336)
Right now, return_scope_stack is being used to determine whether logic
is in a function scope. However, we need to handle nested entities
inside function scopes. For example where this crashes right now:

```
base class C(B:! bool) {}

fn F() {
  class B {
    extend base: C(true or false);
  }
}
```

This is doing a few things to make this kind of code not crash:

- Split `scope_stack().Push` into `PushForDeclName`, `PushForEntity`,
`PushForExpr`, and `PushForFunction` so that better decisions can be
made about behaviors.
- Hide `return_scope_stack` in the API, instead using interfaces to get
at the underlying data.
- Also using `PushForFunction` to update it similar to the other stacks
that `ScopeStack` manages.
- Add `IsInFunctionScope` as the best way to determine presence in
function scope.
- Remove `PeekIsLexicalScope` since destruction really wants function
scope information anyways.
- Clean up `destroy_id_stack` handling to be for function scopes rather
than lexical scopes.
- Return after related `context.TODO`s in a couple more spots, so that
code doesn't proceed to add control flow in spite of the lack of
support.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-04-23 19:03:53 +00:00
Jon Ross-Perkins 4923445e3a Drop Singleton from ErrorInst::SingletonInstId and similar (#5304)
We frequently want to operate on singletons. Per discussion, drop
`Singleton` to make the code shorter.

This started off as wanting to write `inst_id.is_error()`, but the
dependency relationship between ids.h and singleton_insts.h would
require some kind of delayed evaluation to allow the implementation to
remain in headers (which I suspect is helpful to have for inlining). I
could have added something like `IsErrorInst`, forward declared in ids.h
and defined in singleton_insts.h (which would always be included by
typed_insts.h), but the template approach felt like a decent balance
between (a) removing the boilerplate `::SingletonInstId`, (b)
understandability, (c) still visually mirroring if we immediately return
a singleton, and (d) flexibility for more than just `ErrorInst`. But TBH
I'd probably still have written `is_error()` if it didn't require
addressing the cross-header cycle.

Then I tried `SemIR::InstId::Is<SemIR::ErrorInst>`, which generally
worked with types but generated the complaint that it didn't shorten
*all* singleton uses. So pulling back on `::Is`, and instead just
dropping `Singleton`.
2025-04-15 22:40:29 +00:00
Dana JansensandRichard Smith cf57c85545 Introduce TypeInstId (#5288)
TypeInstId is an InstId whose constant value has a type of TypeType.
This includes:
- Type value instructions, the `ClassType` or `IntLiteralType`
instructions.
- Constraint value instructions, which are the `FacetType` and
`TypeType` instructions, each of which also have type TypeType.

TypeInstId encodes in the type system that it is safe to convert the
instruction's value to a TypeId, and CHECKs at construction that this
invariant is maintained.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-10 22:59:02 +00:00
Richard Smith c4c3381b18 Add TypeId::is_symbolic and is_concrete. (#5024)
These just forward to the corresponding members of `TypeId`.
2025-02-27 00:21:01 +00:00
eb69d7420e First iteration of completing and resolving facet types (#4920)
* Add `RequireCompleteFacetType` and `ResolveFacetTypeImplWitness` to
`check::Context`. Goal was to move code from `impl.cpp` (mostly) without
functional changes.
* Complete type information is cached with the facet type, and is stored
in a `complete_facet_types()` table.
* Main functional change is to diagnose attempts to use a rewrite
constraint on an associated function. Some existing diagnostics have
been updated.
* Remove `check::Context::RequireDefinedType`:
  * For class types, use `RequireCompleteType`
  * For facet types, use `RequireCompleteFacetType`
* Introduce a `SemIR::SpecificInterface` to hold an interface and
specific id pair.
* Keep the specific interface ids in the impl object.
* Avoid some extra copies in `Dump` functions.
* Future work missing from this PR:
  * Resolving for member access or actions that require impl lookup.
  * Resolving rewrites constraints that refer to non-concrete values.
* Any support for adding implied constraints that result from a `where`
clause (though TODOs have been added).

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-02-19 22:10:11 +00:00
Jon Ross-Perkins 311b4ff03d Refactor AddInst-family functions to their own file (#4941)
This in particular uses free functions because it's likely to end up
more consistent with types (versus a wrapper object for InstStore).
Note, this is unlikely to have a performance impact, but if it does, we
can look into related approaches (and we've already discussed using
LTO).

Renames `PendingBlock::AddInst` to `PendingBlock::Add` because
`MakeElementAccessInst` expects the matching name to exist.
2025-02-14 19:44:36 +00:00
Jon Ross-Perkins dc8f47e6ad Move type functions off Context (#4951)
This creates a new check/type.h for most logic, and also moves some
functions to TypeStore in sem_ir/type.h. My approach for TypeStore is to
focus on moving the read-only functions there.
2025-02-13 23:02:38 +00:00
Richard Smith 6dda094928 Superficial support for template modifier on symbolic bindings. (#4948)
Change parse tree from `template (T:! type)` to `(template T):! type`,
so that we have information about whether a binding is a template
binding available when forming the representation of the binding
pattern. This incidentally fixes a bug that we would accept `template
addr A:! B` instead of the intended `addr template A:! B`.

Track whether a symbolic binding is a template binding on the
`EntityName` object. I'm borrowing a bit from the `CompileTimeBindIndex`
for this in order to avoid making `EntityName`s larger. Longer-term, we
should think about using a different representation for symbolic
bindings, to avoid including these fields in all `EntityName`s, but
that's out of scope for this change.

So far, template bindings are treated as having the same phase as
checked bindings, but that will change in a future PR.
2025-02-13 02:15:22 +00:00
Richard Smith 5f888e1124 Treat associated constants as entities parameterized by Self (#4837)
Add a full entity representation for associated constants, and build a
`Generic` object for them. This `Generic` is parameterized by the
enclosing `Self` type, allowing the use of `Self` within the type of the
associated constant to be supported.

When performing impl lookup for an associated constant, produce the type
with the provided self type substituted for its `Self` along with any
generic parameters of the interface.

Split the handling of associated constant declarations into two parts,
corresponding to the code before the `=`, and the code between the `=`
and `;` (if any). The former goes into the generic declaration region;
the latter into the generic definition region. This prepares us to
handle the default value for an associated constant, but for now we're
just storing the information and not actually using it.

Remove the entity type field from `assoc_entity_type`, because it's
almost unused and is an attractive nuisance -- it must necessarily be a
type in the generic scope of the associated constant rather than in the
scope of the instruction (because there is no `Self` anywhere else),
which means that it's hard to substitute into or derive meaning from.

See `toolchain/check/testdata/impl/assoc_const_self.carbon` for tests of
the new functionality; these used to cause the toolchain to crash.
2025-01-25 02:13:52 +00:00
Jon Ross-Perkins 9c0faf007e Invalid comment cleanup (#4836)
This is a followup from #4834, I searched for "invalid" uses in our
codebase. This is mostly changing comments, and a couple debug
functions, but shouldn't affect testable behavior.

Note a couple things I'll highlight as not changing (but could) are:
- `ReturnTypeInfo::is_valid`
- `"invalid"` uses in the formatter
- `AddInvalid` for `!has_value` in `inst_fingerprinter` (because the
cases it's called sound invalid-ish)
2025-01-23 02:21:48 +00:00
Jon Ross-Perkins 6b5eb1a101 Id::Invalid -> Id::None (#4834)
High level, replacing `Id::Invalid` with `Id::None` and `Id::is_valid`
with `Id::has_value` for clarity, as discussed
[here](https://discord.com/channels/655572317891461132/655578254970716160/1331664574545395794).
The `IntId` refactoring is needed together with `AnyIdBase` because it's
also used with `ValueStore`.

Note, trying to be careful not to rewrite `EnumBase::InvalidIndex`, or
`is_valid` in general (e.g., `IdKind::is_valid`).

I've tried to sequence commits here:

1. Automatic replacements:

- `((?:Id|Index)(?: |::|\(|Base(?:\(|::)))Invalid((?:Index)?\W)` ->
`$1None$2`
  - `<invalid>` -> `<none>`
  - `InvalidNodeId` -> `NoneNodeId`
  - `/\*invalid\*/` -> `/*none*/`
  - `id((?:_|\(\))(?:\.|->))is_valid` -> `id$1has_value`

2. Manual edits:

  - In `int.h` and `int_test.cpp`
    - `IntT` has `is_value`, which I'm renaming to `is_embedded_value`.
    - Manual edits to comments in this file.
  - `AnyIdBase` and `IdBase`
- Declaration of `is_valid` -> `has_value`, `InvalidIndex` ->
`NoneIndex`.
  - In `ids.h` and `ids.cpp`
    - `is_valid` -> `has_value`
- `// An explicitly invalid ID.` -> `// An ID with no value.`; similar
for index
    - Various math on `InvalidIndex` -> `NoneIndex`
    - Various mentions of "valid" in comments
  - In `value_store.h`, for `IdT::Invalid`, plus one comment
- In `impl.h` and `tokenized_buffer.h`, we had different initialization
of `::None` values (versus `ids.h` syntax) that I fixed manually.
  - Spot checks to compile
- Particularly where `is_valid` replacements didn't catch spots due to
different naming.

3. Autoupdate tests

4. verbose.carbon (NOAUTOUPDATE)

5. Comment spot checks

Note there are probably other mentions of "Invalid" that should be swept
up, but I'd like to argue for merging and separating out remaining
cleanup since this is so sweeping (and likely to hit merge conflicts
from churn). We'll probably have lingering mentions of "invalid" for a
bit regardless, just because there are uses of "invalid" in non-Id APIs.
2025-01-22 23:15:00 +00:00
Jon Ross-Perkins efab39cbd9 Remove InstId::Builtin members (#4632)
- `InstId::Builtin<Inst>` -> `<Inst>::SingletonInstId`
- `InstId::PackageNamespace` -> `Namespace::PackageInstId`
2024-12-05 18:13:46 +00:00
Jon Ross-Perkins 0e92e6cc5a Switch TypeId::TypeType to TypeType::SingletonTypeId, and similar (#4619)
`ids.h` and `ids.cpp` are the manual edits, everything else is
search-and-replace.

The full list of things moved is:

- `TypeId::TypeType`
- `TypeId::AutoType`
- `TypeId::Error`
- `ConstantId::Error`

This is to unblock removing `InstId::Builtin*`.
2024-12-04 18:40:50 +00:00
33110d096c Facet types support rewrite (where .A =...) constraints (#4613)
* Rewrite constraints are stored in a facet type, substituted, imported,
and formatted.
* We now distinguish `.Self` from other symbolic bindings in two ways:
* `.Self` itself now has an invalid compile time binding index (since it
doesn't bind to any of the generic parameters). As a result, we no
longer need to create a generic region in `handle_where.cpp`.
* There is a new phase tracking values that are only symbolic because
they transitively depend on `.Self`. This allows us to give the result
of a `where` expression template phase as long as it doesn't use any
symbolic constants other than `.Self` or other designators.
* `AddConstant` has been removed from `check/context` since it was only
used from `eval`. This meant less plumbing of the phase change.
* Evaluation of `BindSymbolicName` now also performs substitution into
its type.
* Include a bit more information in some diagnostics.
* `StringifyTypeExpr` outputs rewrites, which required adding support
for associated entities as well.
  * Associated entities now have an entity name set when importing.
* Adds tests for some interesting cases with rewrites and uses of
`.Self` mixed with other symbolic constants.

Still to do:
* There is no validation that any particular type satisfies rewrite
constraints.
  * Access to members of a facet type do not see the rewritten values.
* Impls don't recognize whether associated constants have rewrites
setting their values.
  * No support for resolving facet types.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-12-03 22:44:39 +00:00
Jon Ross-Perkins 4a80d6758d Rename the builtin FloatType to LegacyFloatType, Error to ErrorInst (#4555)
This is for more clearly distinct names, and to make it a clearer
transition from `BuiltinInst` for name conflicts. `FloatType` is also an
instruction, and we have `Carbon::Error` (common/error.h). This avoids
affecting tests, although the name is embedded in the builtin test.

In `LegacyFloatType`, `Legacy` because I was having trouble coming up
with a more appropriate name. I'm not clear this is a `FloatLiteralType`
at present, it needs some work to mirror `IntLiteralType`.

In `ErrorInst`, the suffix `Inst` was discussed as good and similar to
`BuiltinInst` (although I'm trying to get rid of that).
2024-11-19 20:37:39 +00:00
a69c2630f9 Replace InterfaceType with FacetType (#4499)
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>
2024-11-11 18:01:50 +00:00
josh11bandJosh L 4febf7c459 Add capitilization and punctuation to TODO comments (#4486)
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-11-05 16:31:00 +00:00
josh11bandJosh L ea0b0b4b48 Add facet type values and an instruction that produces them (#4460)
Still to do:
* Represent facet type values in a canonical form
* Produce & consume facet type values instead of interface values
* `type` should be associated with a canonical facet type value
* Support `&` on facet type values
* Type check and enforce requirements in facet types

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-11-04 21:43:55 +00:00
josh11bandJosh L c30b1d1124 Fix where crash when empty decl_name_stack (#4451)
Bug found by fuzzer.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-10-29 19:38:02 +00:00
josh11bandJosh L 6dbeda612a where check stage, step 3: some type checking (#4364)
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>
2024-10-05 01:03:43 +00:00
Richard Smith 4ca711c175 When converting an expression to type type, retain the resulting instruction as well as the TypeId. (#4355)
The `TypeId` is lossy, as it represents only the canonical type, and not
the specific computation that produced it.
2024-10-01 01:49:39 +00:00
bdbd1079a6 where check stage, step 2: SemIR (#4349)
The check stage now produces SemIR instructions to represent a `where`
clause. It still does not check types.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-09-27 01:41:56 +00:00
Richard Smith 7f22a289b9 Push a generic region when handling a where expression. (#4340)
This fixes a crash in the case where a `where` expression appears
outside of any generic.
2024-09-26 00:24:38 +00:00
49a8efbe1b where check stage, step 1: designators (#4329)
Right now, there is no checking of `where` requirements. The result of a
where expression is just the type on the left-hand side. It does now
introduce `.Self` so that it is available in expressions on the
right-hand side, in addition to designators corresponding to the members
of type on the left-hand side. Note, though, that diagnostics could
still be improved significantly.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-09-25 02:44:12 +00:00
d6b2fb1736 Add parse support for multiple requirements after where separated by and (#4298)
Follow on to #4275 that added `where` parse support.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-09-11 21:36:55 +00:00
c33c9a02f6 Parse support for where operator (#4275)
Includes support for the `impls`, `=`, and `==` requirement operators to
the right of a `where`, but `and` to allow multiple requirements is
still a TODO.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-09-11 03:17:07 +00:00
702d0d8a53 Parsing of designators like .x or .Self (#4254)
These appear in `where` clauses, as in:

```
U:! InterfaceB where .C = Vector(.D)
V:! type where Vector(.Self) impls Sortable
```

`.Self` can additionally appear in type expressions in a binding pattern
such as `T:! InterfaceA(.Self)`.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-08-28 16:26:23 +00:00