Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Build Entity instances, not Term* instances. (#674)#778

Merged
ncalexan merged 8 commits into
mozilla:masterfrom
ncalexan:entity-builder
Jul 5, 2018
Merged

Build Entity instances, not Term* instances. (#674)#778
ncalexan merged 8 commits into
mozilla:masterfrom
ncalexan:entity-builder

Conversation

@ncalexan

@ncalexan ncalexan commented Jul 5, 2018

Copy link
Copy Markdown
Member

I haven't tried to rename EntityBuilder (or remove it), and I haven't tried to rename TermBuilder to EntityBuilder. Those can come later.

This also doesn't intern TempId handles at parse time; we can get to that.

This addresses #674.

ncalexan added 4 commits July 5, 2018 11:16
It's not great to keep lifting functionality higher and higher up the
crate hierarchy, but we really do want to intern while we parse.
Eventually, I expect that we will split the `edn` crate into `types`
and `parsing`, and the `types` crate can depend on a more efficient
interning dependency.
We haven't observed performance issues using `Arc` instead of `Rc`,
and we want to be able to include things that are interned (including,
soon, `TempId` instances) in errors coming out of the
transactor.  (And `Rc` isn't `Sync`, so it can't be included in errors
directly.)
This pattern is generally how newtype wrappers (like `struct
Foo(Bar)`) are implemented in Rust.
This is all part of moving the entity builder away from building term
instances and toward building entity instances.  One of the nice
things that the existing term interface does is allow consumers to use
lightweight reference counted tempid handles; I don't want to lose
that, so we'll build it into the entity data structures directly.

@grigoryk grigoryk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You say "we haven't observed" - which I assume to mean "at some point we've profiled, and didn't find the added cost of Arc to be an issue given our usage patterns"?

There is a cost, but I don't have a good enough sense of the flow of things to guess if/when it'll be a problem.

What about somehow shifting the burden to the somewhat rare (once things application code stabilizes in its ways) error cases, maybe? e.g. clone whatever's is in Rc's if things go wrong, maybe?

@ncalexan

ncalexan commented Jul 5, 2018

Copy link
Copy Markdown
Member Author

You say "we haven't observed" - which I assume to mean "at some point we've profiled, and didn't find the added cost of Arc to be an issue given our usage patterns"?

Correct. That happened in #659 and friends; see #659 (comment). This is more analogy than science in this instance.

There is a cost, but I don't have a good enough sense of the flow of things to guess if/when it'll be a problem.

Exactly.

What about somehow shifting the burden to the somewhat rare (once things application code stabilizes in its ways) error cases, maybe? e.g. clone whatever's is in Rc's if things go wrong, maybe?

I'm happy to do that at some point, and considered it for this -- cloning names out of TempId instances while building errors wouldn't be onerous, for example. Right now, in a number of places, we expose our guts (ValueRc<String>, say, rather than String or &str) directly to consumers. It's not clear if that's foolish quite yet.

Comment thread edn/src/entities.rs Outdated

/// Entity and value places embed values, either directly (i.e., `ValuePlace::Atom`) or indirectly
/// (i.e., `EntityPlace::LookupRef`). In order to maintain the graph of `Into` and `From`
/// relations, we need to ensure that `{Value,Entity}Place` can't match as a potential value. This

@grigoryk grigoryk Jul 5, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On first read, the dual meaning of "value" in this comment makes things a little confusing - but perhaps that's just my unfamiliarity with the subject. Unsure what you'd call "embedded values" other than values though. A "concrete value"?

Stepping back from the graph of Intos, perhaps this can also be talked about in terms of being able to guarantee termination of value resolution? E.g. "{Entity,Value}Place need to resolve to a concrete value, which could happen either directly (i.e. ValuePlace::Atom, concrete value is embedded in the enum) or indirectly (i.e. EntityPlace::LookupRef, concrete value is a hop away). We need to ensure that the resolution is guaranteed to terminate, etc etc".

@grigoryk grigoryk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't claim to understand everything that's going on, but generally I think this makes some sense to me. I thought the use of TransactableValueMarker was quite elegant.

Rubber stamp if you need this landed!

ncalexan added 3 commits July 5, 2018 16:33
There are a few tricky details to call out here.  The first is the
`TransactableValueMarker` trait.  This is strictly a marker (like
`Sized`, for example) to give some control over what types can be used
as value types in `Entity` instances.  This expression is needed due
to the network of `Into` and `From` relations between the parts of
valid `Entity` instances.  This allows to drop the `IntoThing`
work-around trait and use the established patterns.  (Observe that
`KnownEntid` makes this a little harder, due to the cross-crate
consistency restrictions.)

The second is that we can get rid `{add,retract}_kw`, since the
network of relations expresses the coercions directly.

The third is that this commit doesn't change the name `TermBuilder`,
even though it is now building `Entity` instances.  This is because
there's _already_ an `EntityBuilder` which fixes the `EntityPlace`.
It's not clear whether the existing entity building interface should
be removed or whether both should be renamed.  That can be follow-up.
The `core` create didn't exist when the `db` was started, but this
type is clearly part of the public interface of Mentat.
…nctions.

These are functions on `TermBuilder` itself to prevent mixing mutable
and immutable references in the most natural style.  That is,
```
builder.add(e, a, builder.lookup_ref(...))
```
fails because `add` borrows `builder` mutably and `lookup_ref` borrows
`builder` immutably.  There's nothing here that requires a specific
builder (since we're not interning lookup refs on the builder, like we
are tempids) so we don't need an instance.
@ncalexan ncalexan merged commit 99deb87 into mozilla:master Jul 5, 2018
ncalexan added a commit that referenced this pull request Jul 5, 2018
…f Mentat. (#779) r=grisha

These build on #778, and implement a variety of small fixes (related
parts are labelled as such), and one non-trivial part -- matching
tuple results with the `BindingTuple` trait. In practice, this is very
helpful, and greatly streamlined the logins API.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants