There are cases where an impl definition should apply to more than a single type and interface combination. The solution is to parameterize the impl definition, so it applies to a family of types, interfaces, or both. This includes:
- Declare an impl for a parameterized type, which may be external or declared out-of-line.
```
external impl [T:! Type] Vector(T) as Iterable { ... }
external impl Vector(T:! Type) as Iterable { ... }
```
- "Conditional conformance" where a parameterized type implements some interface if the parameter to the type satisfies some criteria, like implementing the same interface.
```
external impl [T:! Type] Pair(T, T) as Foo(T) { ... }
class Array(T:! Type, template N:! Int) {
impl [P:! Printable] Array(P, N) as Printable { ... }
impl Array(P:! Printable, N) as Printable { ... }
}
```
- "Blanket" impls where an interface is implemented for all types that implement another interface, or some other criteria beyond being a specific type.
```
external impl [T:! Ordered] T as PartiallyOrdered { ... }
```
- "Wildcard" impls where a family of interfaces are implemented for single type.
```
class BigInt {
external impl [T:! ImplicitAs(i32)] as AddTo(T) { ... }
external impl as AddTo(T:! ImplicitAs(i32)) { ... }
}
external impl [T:! ImplicitAs(i32)] BigInt as AddTo(T) { ... }
external impl BigInt as AddTo(T:! ImplicitAs(i32)) { ... }
```
In addition to a syntax for defining parameterized impls, we need rules for coherence:
- Orphan rules that ensure that impls are imported in any code that might use it.
- We need overlap rules that pick a specific impl when more than one impl declaration matches a specific query about whether a type implements an interface.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Add an appendix with the rationale for and alternatives to coherence, along with an entry in the terminology and updates to the coherence discussion in the goals.
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
There are some declaration order changes, and a few test classes switched from `struct` to `class`. However, this PR is mostly adopting `_` naming of private member variables due to the shift in naming style. None of what's here should have behavior impacts, it should just be style.
Note, there are a lot of things that *look* like they could be accessor-named, but I'm not doing that in this change. Happy to do it separately if you want me to do another PR focused on it.
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Implementations of interfaces are as public as the names used in their signature. No access control modifiers are allowed on `impl` declarations.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Includes a variety of changes:
Int -> i32
this -> me
expand terminology doc and add links to it
fix text to reflect inline external impl introduced in Support external impl in class and adapter scopes. #905
no longer have plans for runtime type parameters
style updates like removing parentheticals and "we"
observe is a "declaration" not a "statement", since it can appear outside function bodies
many individual updates, clean-ups, and fixes
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This doesn't actually use the results of name resolution, but it does verify that they are present.
Also ensures that name resolution and type checking are applied to deduced function parameters and the implicit call to `Main()`.
Co-authored-by: Jon Meow <46229924+jonmeow@users.noreply.github.com>
- Rename `PointerValue` to `LValue` to reflect how it's actually used. We can introduce a `PointerValue` type when we add support for actual pointer values.
- Remove support for pattern assignment. It's unclear if Carbon will support this, and even if we do, it raises questions that should first be addressed in a language proposal, like "is the left-hand side of `(x, y) = (1, 2)` an lvalue, or a pattern, or both, or something else entirely?"
This enables us to stop treating the return type as a Pattern (which is really isn't), treat return types more consistently with other static types in the typechecker, and drop ReturnTypeContext.
Additional changes:
- Merge TypeCheckFunDef with TypeOfFunDef.
- Handle implicit conversions in `return` statements.
- Require function type literals to have an explicit `->`.
- Move consistency check for omitted returns from TypeChecker to ResolveControlFlow.
#939 switch to `Main`, but #919 predated it and didn't get updated
before merging. Its tests passed on the PR branch as a consequence, but
failed when landed.
This just updates the test cases. Trivial fix forward.
I didn't fully configure the new dependencies correctly or fully get
them working with our tooling rigging for compilation databases.
- I needed to fix the sha256 of the benchmark. I pasted the wrong
one, but didn't test it effectively.
- Didn't successfully enable the use of Abseil from GoogleTest
(including nice things like its symbolization, etc). Doing this is
a bit awkward as it needs to go into our `.bazelrc`, but it works.
- Didn't add libraries other that GoogleTest to the compile flags.
- Didn't teach the compilation database creation step to cause these
external repositories to be linked in and populated nicely.
All of these are fixed. As I was making changes to the Python script
here, I've added a test to at least type check it and fixed the type
errors reported.
This avoids needing to have nearly as many rules here which should
reduce its churn.
I've tested that this reaches the exact same set of transitive
dependencies.
Note, only the last commit here is new.
This starts detecting naming collisions as a consequence of being able to determine when the name is declared twice in a given scope.
Co-authored-by: Geoff Romer <gromer@google.com>
This warning is looking low value; for example:
```
/usr/local/google/home/jperkins/dev/carbon-lang/executable_semantics/interpreter/value.h:199:21: warning: 2 adjacent parameters of 'NominalClassValue' of similar type ('Nonnull<const Carbon::Value *>') are easily swapped by mistake [bugprone-easily-swappable-parameters]
NominalClassValue(Nonnull<const Value*> type, Nonnull<const Value*> inits)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/google/home/jperkins/dev/carbon-lang/executable_semantics/interpreter/value.h:199:43: note: the first parameter in the range is 'type'
NominalClassValue(Nonnull<const Value*> type, Nonnull<const Value*> inits)
^~~~
/usr/local/google/home/jperkins/dev/carbon-lang/executable_semantics/interpreter/value.h:199:71: note: the last parameter in the range is 'inits'
NominalClassValue(Nonnull<const Value*> type, Nonnull<const Value*> inits)
^~~~~
```
This moves over to the vanilla upstream GoogleTest pulled in the more
expected manner with Bazel. It also adds Abseil and Google Benchmark
libraries in the same fashion (there are cross dependencies here).
As part of this, also introduce a dependency check test that can enforce
basic layering of dependencies. For example, this lets us ensure that
non-test Carbon code only depends on LLVM and Clang despite having other
libraries available. There remains some cleanup to improve the way these
dependency tests work, but this at least ensures we don't regress.
I've also provided workarounds to allow both Carbon code and LLVM code
to freely be used with GoogleTest (and other `std::ostream` based
output code). This is done by extending the code in
`//common/ostream.h`. One downside is that it requires opening the
`llvm` namespace and adding an ADL_found overload there. I think on
balance this is still a win and doesn't make me too nervous.
The new version of GoogleTest requires printing more often from matchers
and so I've also added several printing routines to types that
previously didn't require them. Otherwise, most of the updates are just
using the more conventional upstream style of including the headers and
adding `ostream.h` where it is needed.
I did consider moving code over to use `std::ostream` instead of LLVM's
`raw_ostream`, but the advantages of not doing virtual dispatch still
seem significant, and it also seems good to retain access to LLVM's
formatting utilities built around `raw_ostream` given that we can't pull
arbitrary dependencies into Carbon code outside of test code.
All of this was slightly motivated by requests for newer features in
GoogleTest, but much more-so by my desire to have access to Google
Benchmark and Abseil when writing benchmarks. For example, using
Abseil's random number generator seems extremely helpful when generating
inputs for benchmarks. The growing dependencies between these packages
further motivated me to just pull them all in and ensure they worked
well.
The `__Fn` naming is intended to mirror things like `__Continuation`.
The reason for this path is because it's not clear this is the form we'll want, and I think experimental naming will help reflect that.
This proposal describes `where` clauses that can add constraints on a type-of-type, for example define restrictions on its associated types. Example:
```
fn FindFirstPrime[T:! Container where .Element = i32]
(c: T) -> Optional(i32) {
// The elements of `c` have type `T.Element`, which is `i32`.
...
}
fn PrintContainer[T:! Container where .Element is Printable](c: T) {
// The type of the elements of `c` is not known, but we do know
// that type satisfies the `Printable` interface.
...
}
```
Some other constraints, such as `Sized` are defined as type-of-types directly, possibly parameterized.
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This proposal provides an `as` expression for casting. This supports implicit conversions plus some safe and unsurprising conversions that we do not support implicitly:
* lossy but fully defined conversions to floating-point types
* conversion from `bool` to integer types
* conversion between adaptors and their adapted type, and more generally between compatible types
This facility can be extended by implementing the `As(TargetType)` interface for a type.
Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: josh11b <josh11b@users.noreply.github.com>