Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make fields of `Span` private #43968

Merged
merged 3 commits into from Aug 30, 2017

Conversation

Projects
None yet
7 participants
@petrochenkov
Copy link
Contributor

petrochenkov commented Aug 18, 2017

I actually tried to intern spans and benchmark the result*, and this was a prerequisite.
This kind of encapsulation will be a prerequisite for any other attempt to compress span's representation, so I decided to submit this change alone.

The issue #43088 seems relevant, but it looks like SpanId won't be able to reuse this interface, unless the tables are global (like interner that I tried) and are not a part of HIR.
r? @michaelwoerister anyway

* Interning means 2-3 times more space is required for a single span, but duplicates are free. In practice it turned out that duplicates are not that common, so more memory was wasted by interning rather than saved.

}
#[inline]
#[must_use]
pub fn set_lo(self, lo: BytePos) -> Span {

This comment has been minimized.

@petrochenkov

petrochenkov Aug 18, 2017

Author Contributor

I'm not sure set_x are the best possible names since the functions are not mutating, but at least I guarded them from mistakes with #[must_use].

This comment has been minimized.

@estebank

estebank Aug 18, 2017

Contributor

Should the fields be named with_x? In my mind that conjures the fact that the method returns a copy of the same type with the field having the new value.

This comment has been minimized.

@petrochenkov

petrochenkov Aug 18, 2017

Author Contributor

Yeah, seems better, I'll rename.

@@ -425,7 +425,7 @@ impl<'a> LoweringContext<'a> {
allow_internal_unsafe: false,
},
});
span.ctxt = SyntaxContext::empty().apply_mark(mark);
span = span.set_ctxt(SyntaxContext::empty().apply_mark(mark));
span

This comment has been minimized.

@kennytm

kennytm Aug 18, 2017

Member

Huh? Just return span.set_ctxt(SyntaxContext::empty().apply_mark(mark)) directly.

#[inline]
#[must_use]
pub fn set_lo(self, lo: BytePos) -> Span {
Span::new(lo, self.hi(), self.ctxt())

This comment has been minimized.

@estebank

estebank Aug 18, 2017

Contributor

Wouldn't it make more sense to do the following in all the set_x methods?

Span {lo, ..self}

This comment has been minimized.

@petrochenkov

petrochenkov Aug 18, 2017

Author Contributor

It was necessary with interning (the same is true for #43968 (comment)). It will be necessary with any non-trivial Span::new/Span::lo/etc, so I left it.

}
#[inline]
#[must_use]
pub fn set_lo(self, lo: BytePos) -> Span {

This comment has been minimized.

@estebank

estebank Aug 18, 2017

Contributor

Should the fields be named with_x? In my mind that conjures the fact that the method returns a copy of the same type with the field having the new value.

let lo = cmp::max(self.hi.0 - 1, self.lo.0);
Span { lo: BytePos(lo), ..self }
let lo = cmp::max(self.hi().0 - 1, self.lo().0);
self.set_lo(BytePos(lo))

This comment has been minimized.

@estebank

estebank Aug 18, 2017

Contributor

Is it really necessary to use the public getters in the impl?

This comment has been minimized.

@michaelwoerister

michaelwoerister Aug 18, 2017

Contributor

I guess it would be if spans were really interned. For now I'd also opt for just accessing the fields directly.

@michaelwoerister
Copy link
Contributor

michaelwoerister left a comment

Looks good to me. Thanks, @petrochenkov! I'm also for renaming the set_x methods to with_x. Other than that (and maybe not using the getters in impl Span) this is good to go.

You might be interested in this: A couple of years ago I did some experiments with span interning plus storing the span information directly in the interning key, if it fit in there (like a tagged pointer). The results were actually quite promising, if I remember correctly: https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/23. Maybe you want to revisit interning with this additional optimization?

let lo = cmp::max(self.hi.0 - 1, self.lo.0);
Span { lo: BytePos(lo), ..self }
let lo = cmp::max(self.hi().0 - 1, self.lo().0);
self.set_lo(BytePos(lo))

This comment has been minimized.

@michaelwoerister

michaelwoerister Aug 18, 2017

Contributor

I guess it would be if spans were really interned. For now I'd also opt for just accessing the fields directly.

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 18, 2017

@michaelwoerister

The results were actually quite promising, if I remember correctly: https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/23. Maybe you want to revisit interning with this additional optimization?

I remembered there was a thread about this somewhere! Thanks for the link.
Yes, I was going to experiment further with keeping "short" spans inline and other spans "somewhere else".

@petrochenkov petrochenkov force-pushed the petrochenkov:span2 branch from 2c1d664 to 9fed6da Aug 18, 2017

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 18, 2017

Updated.

Some(Span::new(
cmp::min(sp_lhs.lo(), sp_rhs.lo()),
cmp::max(sp_lhs.hi(), sp_rhs.hi()),
sp_lhs.ctxt()

This comment has been minimized.

@estebank

estebank Aug 19, 2017

Contributor

I believe this can be replaced with Some(sp_lhs.to(sp_rhs)).

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 19, 2017

☔️ The latest upstream changes (presumably #43933) made this pull request unmergeable. Please resolve the merge conflicts.

@michaelwoerister

This comment has been minimized.

Copy link
Contributor

michaelwoerister commented Aug 19, 2017

Thanks! r=me after rebasing.

@mcarton mcarton referenced this pull request Aug 19, 2017

Closed

Breakage incoming #1972

@petrochenkov petrochenkov force-pushed the petrochenkov:span2 branch from 9fed6da to cdae234 Aug 19, 2017

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 19, 2017

@bors r=michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 19, 2017

📌 Commit cdae234 has been approved by michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 19, 2017

⌛️ Testing commit cdae234 with merge 17e924e...

bors added a commit that referenced this pull request Aug 19, 2017

Auto merge of #43968 - petrochenkov:span2, r=michaelwoerister
Make fields of `Span` private

I actually tried to intern spans and benchmark the result<sup>*</sup>, and this was a prerequisite.
This kind of encapsulation will be a prerequisite for any other attempt to compress span's representation, so I decided to submit this change alone.

The issue #43088 seems relevant, but it looks like `SpanId` won't be able to reuse this interface, unless the tables are global (like interner that I tried) and are not a part of HIR.
r? @michaelwoerister anyway

<sup>*</sup> Interning means 2-3 times more space is required for a single span, but duplicates are free. In practice it turned out that duplicates are not *that* common, so more memory was wasted by interning rather than saved.
@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 19, 2017

💔 Test failed - status-travis

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 19, 2017

Sigh, need to send a PR to rustfmt first.

@kennytm

This comment has been minimized.

Copy link
Member

kennytm commented Aug 20, 2017

We've hit a deadlock situation where the rustfmt PR cannot pass without the get/set methods added in this PR, and this PR cannot pass without rustfmt stop reading the now-private fields. I don't think turning rustfmt's status red is a good idea.

I think this PR should be split into two stages,

  1. This PR keep the fields public, so rustfmt doesn't need to be updated at the moment.
  2. rustfmt (as well as clippy, rls, etc.) all accept PRs stop using the fields.
  3. Submit another PR to turn the fields private (can be done simultaneously with step 2).
@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 20, 2017

@kennytm
Situations like this were previously resolved by creating a new branch in rustfmt/rls, merging the breaking patch into that branch and not master, then setting rls submodule in rust-lang/rust to that branch.

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 20, 2017

I gathered some span statistics from rustc/libstd and found a significant number of "reverse" spans with lo > hi!
That seems bad, some code may work correctly with such spans, but I've certainly seen ICEs caused by code that doesn't work with them.

I'm going to add "normalization" to lo <= hi into Span::new.
It also boosts the percent of inline spans a bit when compression is used.

nrc added a commit to rust-lang/rls that referenced this pull request Aug 20, 2017

@petrochenkov petrochenkov force-pushed the petrochenkov:span2 branch from cdae234 to 3da163f Aug 20, 2017

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 20, 2017

@bors r=michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 20, 2017

📌 Commit 3da163f has been approved by michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 20, 2017

⌛️ Testing commit 3da163f with merge 4ad2c42...

bors added a commit that referenced this pull request Aug 20, 2017

Auto merge of #43968 - petrochenkov:span2, r=michaelwoerister
Make fields of `Span` private

I actually tried to intern spans and benchmark the result<sup>*</sup>, and this was a prerequisite.
This kind of encapsulation will be a prerequisite for any other attempt to compress span's representation, so I decided to submit this change alone.

The issue #43088 seems relevant, but it looks like `SpanId` won't be able to reuse this interface, unless the tables are global (like interner that I tried) and are not a part of HIR.
r? @michaelwoerister anyway

<sup>*</sup> Interning means 2-3 times more space is required for a single span, but duplicates are free. In practice it turned out that duplicates are not *that* common, so more memory was wasted by interning rather than saved.
@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 21, 2017

💔 Test failed - status-travis

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 21, 2017

@bors r=michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 21, 2017

📌 Commit c4125e2 has been approved by michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 21, 2017

⌛️ Testing commit c4125e2 with merge c1ad755...

bors added a commit that referenced this pull request Aug 21, 2017

Auto merge of #43968 - petrochenkov:span2, r=michaelwoerister
Make fields of `Span` private

I actually tried to intern spans and benchmark the result<sup>*</sup>, and this was a prerequisite.
This kind of encapsulation will be a prerequisite for any other attempt to compress span's representation, so I decided to submit this change alone.

The issue #43088 seems relevant, but it looks like `SpanId` won't be able to reuse this interface, unless the tables are global (like interner that I tried) and are not a part of HIR.
r? @michaelwoerister anyway

<sup>*</sup> Interning means 2-3 times more space is required for a single span, but duplicates are free. In practice it turned out that duplicates are not *that* common, so more memory was wasted by interning rather than saved.
@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 21, 2017

💔 Test failed - status-travis

@kennytm

This comment has been minimized.

Copy link
Member

kennytm commented Aug 21, 2017

x86_64-gnu-aux, same error. It's legit then.

@nrc

This comment has been minimized.

Copy link
Member

nrc commented Aug 22, 2017

RLS tests timed out or some span is not found. Maybe legit

Possibly a bad span produced in save-analysis?

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 22, 2017

The errors are caused by RLS update, not by span patches, i.e. 9061581 alone (without rust-lang/rls@f4e6f16) is enough to reproduce them.
In theory, #44028 should hit them as well.
cc @nrc

@estebank

This comment has been minimized.

Copy link
Contributor

estebank commented Aug 22, 2017

Could you provide a dump of the reversed spans? I've seen them every now and then but have put off investigating the root cause(s). There are a few possible very unseemly results that could happen, for example when doing end.to(start), so I'd hate to just mask the incorrect spans by doing the obvious fix but rather fix the source (probably during parsing).

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 23, 2017

Waiting on #44028

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 23, 2017

@estebank

Could you provide a dump of the reversed spans?

I have only numbers unfortunately. Looks like the only way to obtain the source of inverted spans from Span::new is backtrace.
Once this PR lands, Span::new will be the single point of span creation, so you will be able to detect inverted spans by inserting an assert(lo <= hi) into it and building everything with RUST_BACKTRACE=1.
EDIT: Maybe that assert could be left there forever once all inverted spans are fixed.

@estebank

This comment has been minimized.

Copy link
Contributor

estebank commented Aug 24, 2017

Sounds reasonable. Will do. Are asserts only enabled on nightly? Would rather not cause ICEs for a rather benign bug just because it isn't caught in the test, but would like to see he effects of it on cargo bomb.

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 26, 2017

☔️ The latest upstream changes (presumably #44028) made this pull request unmergeable. Please resolve the merge conflicts.

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 26, 2017

@estebank

Are asserts only enabled on nightly?

Not sure about debug_assert, but assert is always enabled.
FWIW, nightly can be detected through an environmental variable CFG_RELEASE_CHANNEL, but I'm not sure it's a good idea.

nrc added a commit to rust-lang/rls that referenced this pull request Aug 27, 2017

petrochenkov added some commits Jul 31, 2017

Make fields of `Span` public again
This helps to avoid landing changes to rustc and rustfmt in one step

@petrochenkov petrochenkov force-pushed the petrochenkov:span2 branch from c4125e2 to a0c3264 Aug 29, 2017

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Aug 29, 2017

I'll try to land changes to rustc and rustfmt in two steps (rustfmt is moving forward too fast), so I made fields of Span public again for compatibility.
@bors r=michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 29, 2017

📌 Commit a0c3264 has been approved by michaelwoerister

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 30, 2017

⌛️ Testing commit a0c3264 with merge ca9cf35...

bors added a commit that referenced this pull request Aug 30, 2017

Auto merge of #43968 - petrochenkov:span2, r=michaelwoerister
Make fields of `Span` private

I actually tried to intern spans and benchmark the result<sup>*</sup>, and this was a prerequisite.
This kind of encapsulation will be a prerequisite for any other attempt to compress span's representation, so I decided to submit this change alone.

The issue #43088 seems relevant, but it looks like `SpanId` won't be able to reuse this interface, unless the tables are global (like interner that I tried) and are not a part of HIR.
r? @michaelwoerister anyway

<sup>*</sup> Interning means 2-3 times more space is required for a single span, but duplicates are free. In practice it turned out that duplicates are not *that* common, so more memory was wasted by interning rather than saved.
@bors

This comment has been minimized.

Copy link
Contributor

bors commented Aug 30, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: michaelwoerister
Pushing ca9cf35 to master...

@bors bors merged commit a0c3264 into rust-lang:master Aug 30, 2017

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details

@petrochenkov petrochenkov deleted the petrochenkov:span2 branch Sep 10, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.