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

Better diagnostics with mismatched types due to implicit static lifetime #87244

Merged
merged 2 commits into from
Jul 20, 2021

Conversation

jackh726
Copy link
Member

Fixes #78113

I think this is my first diagnostics PR...definitely happy to hear thoughts on the direction/implementation here.

I was originally just trying to solve the error above, where the lifetime on a GAT was causing a cryptic "mismatched types" error. But as I was writing this, I realized that this (unintentionally) also applied to a different case: wf-in-foreign-fn-decls-issue-80468.rs. I'm not sure if this diagnostic should get a new error code, or even reuse an existing one. And, there might be some ways to make this even more generalized. Also, the error is a bit more lengthy and verbose than probably needed. So thoughts there are welcome too.

This PR essentially ended up adding a new nice region error pass that triggers if a type doesn't match the self type of an impl which is selected because of a predicate because of an implicit static bound on that self type.

r? @estebank

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 18, 2021
@rust-log-analyzer

This comment has been minimized.

@jackh726 jackh726 force-pushed the issue-71883 branch 2 times, most recently from 0542c18 to 69531a4 Compare July 18, 2021 07:26
@rust-log-analyzer

This comment has been minimized.

Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

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

The new output is great! I have some nitpicks that I'd like to address before we land this.
Particularly I'd like to tweak the resulting output to be as short and clear as possible to people that might not know what a "requirement" or a "bound" is, or why a 'static lifetime requirement is involved.

I'm not sure if this diagnostic should get a new error code, or even reuse an existing one.

If we can add a new error code that'd be great, but it is perfectly fine to land things like this without an error code, at least at the beginning, as long as the error itself contains as much information as an error code index entry would.

Comment on lines 16 to 17
LL | pub struct Wrapper<T: Trait>(T);
| ^^^^^
Copy link
Contributor

Choose a reason for hiding this comment

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

In this case the 'static lifetime obligation is introduced by the type parameter (T: Trait is implicitly 'sized). It'd be nice to proactively handle this, detect this case and mention that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, this is because the lifetime on Ref in impl Trait for Ref {} falls back to 'static in resolution.

The lifetime for Ref in pub fn repro(_: Wrapper<Ref>) on the other hand defaults to an anonymous lifetimes.

A diagnostic here still might be useful to say something like "this lifetime is being assumed as 'static'"

Copy link
Member Author

Choose a reason for hiding this comment

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

I think an extra diagnostic here might make sense for another PR?

Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

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

I think an extra diagnostic here might make sense for another PR?

I would prefer if it was in the same PR, but I'm ready to merge this after addressing my nitpicks if you don't have the time to try and handle that case.

@jackh726
Copy link
Member Author

Ok @estebank I modified the output just a bit, in order to make it a bit better in cases where there is an explicit static, multiple implicit statics, or when the impl isn't local.

I also added a small note to the assumed static in cases of missing lifetimes. This isn't in the implicit static error message, but should maybe be enough for someone to figure out what's going on. I'd rather land this and maybe work more on that another time.

@@ -336,6 +336,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
insertion_sp,
suggestion,
);
err.note("assuming a `'static` lifetime...");
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a fan of this new note, but I see your point.

@estebank
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Jul 20, 2021

📌 Commit ae02491 has been approved by estebank

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 20, 2021
@bors
Copy link
Contributor

bors commented Jul 20, 2021

⌛ Testing commit ae02491 with merge da7d405...

@bors
Copy link
Contributor

bors commented Jul 20, 2021

☀️ Test successful - checks-actions
Approved by: estebank
Pushing da7d405 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Jul 20, 2021
@bors bors merged commit da7d405 into rust-lang:master Jul 20, 2021
@rustbot rustbot added this to the 1.55.0 milestone Jul 20, 2021
@jackh726 jackh726 deleted the issue-71883 branch July 20, 2021 14:10
@pnkfelix
Copy link
Member

This was flagged as causing a moderate regression with respect to instruction counts in the compiler: perf.rlo link

Most of the regressions are under the 1% threshold, but there's a lot of them that exceed the 0.2% threshold we use for non-noisy benchmarks.

Was this PR, which I understand adds an extra region error pass, expected to cause that much additional overhead? Skimming, I see a place where a Vec was replaced with a HashMap, maybe it is from that change?

@jackh726
Copy link
Member Author

@pnkfelix nope that's unexpected; the pass should should only run after a region error has been generated. The only thing that could have possibly had an effect, I think, is https://github.com/rust-lang/rust/pull/87244/files#diff-34d5893dd95fe09f9a0fd3341efacd1c21853bb34ba29d9d79bb9af26bb8a0a0R1906-R1911. Which is...not much of a change.

@Mark-Simulacrum
Copy link
Member

Log of investigation work:

Selected the most prominent regression, stm32f4-check full.

First checked the self-profile view on perf.rlo for any changes in # of queries run. That can point to obvious causes, but not in this case. This means we need some local cachegrind diff'ing.

# Get our parent/master toolchains
rustup-toolchain-install-master 718d53b0cb7dde93499cb92950d60b412f5a3d05 da7d405357600a76f2b93b8aa41fe5ee5da7885d
# Benchmark our top regressed benchmark in cachegrind
cargo run --release --bin collector -- profile_local cachegrind +718d53b0cb7dde93499cb92950d60b412f5a3d05 before --include stm32f4 --builds Check --runs Full
cargo run --release --bin collector -- profile_local cachegrind +da7d405357600a76f2b93b8aa41fe5ee5da7885d after --include stm32f4 --builds Check --runs Full

This generates results/cgout-{before,after}-stm32f4-Check-Full

Using the output of cg_diff directly doesn't work well -- the hashes for each compiler are embedded into the paths and that makes cg_diff fail. I usually directly sed the cgout files rather than using the built-in --mod-filename support, since it's more general and works OK anyway. rustfilt is also helpful to avoid any crate hashes and such in mangled names that also interfere with diffing.

In this case:

cg_diff results/cgout-{before,after}-stm32f4-Check-Full | \
sed 's@da7d405357600a76f2b93b8aa41fe5ee5da7885d@@' | \
        sed 's@718d53b0cb7dde93499cb92950d60b412f5a3d05@@' | \
        rustfilt | \
        cg_annotate /dev/stdin | less

This produces:

140,274,957 (26.56%)  ???:rustc_trait_selection::traits::select::SelectionContext::match_impl
 55,140,172 (10.44%)  ???:core::ptr::drop_in_place<rustc_middle::traits::ObligationCauseCode>
 50,909,434 ( 9.64%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 50,002,422 ( 9.47%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 43,048,392 ( 8.15%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 32,248,934 ( 6.11%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 32,223,227 ( 6.10%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 25,111,562 ( 4.75%)  /rustc///library/std/src/sys/unix/alloc.rs:__rdl_alloc
 21,427,608 ( 4.06%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 14,349,464 ( 2.72%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
 14,349,464 ( 2.72%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
  7,174,732 ( 1.36%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
  7,174,732 ( 1.36%)  /rustc///library/std/src/alloc.rs:__rdl_alloc
  7,143,206 ( 1.35%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
  4,673,042 ( 0.88%)  ???:<rustc_middle::ty::sty::TraitRef as rustc_infer::infer::at::ToTrace>::to_trace
 -3,618,984 (-0.69%)  ???:hashbrown::map::RawEntryBuilderMut<K,V,S,A>::from_hash
  3,587,366 ( 0.68%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
  3,587,366 ( 0.68%)  ???:__rust_alloc
  3,587,366 ( 0.68%)  ???:__rust_dealloc
  3,587,366 ( 0.68%)  /rustc///library/std/src/sys/unix/alloc.rs:__rdl_dealloc
  2,586,312 ( 0.49%)  ???:rustc_infer::infer::InferCtxt::commit_if_ok
  1,605,085 ( 0.30%)  ???:rustc_resolve::Resolver::resolve_ident_in_lexical_scope
    869,968 ( 0.16%)  ???:rustc_span::hygiene::HygieneData::is_descendant_of
    748,057 ( 0.14%)  /rustc//obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/build/tikv-jemalloc-sys-8def611f6>
    625,536 ( 0.12%)  ???:rustc_infer::infer::at::At::eq_impl_headers

Overall cachegrind is pretty good at pointing in a vague direction -- inlining and such can obscure a little what the actual effects of a change like this are. That said, it is pretty obvious based on the above that the regression is indeed due to the new ObligationCause being created.

The diff above has some more minor changes in other functions - but we can mostly ignore those in this case. The majority of the delta is pretty clearly from extra allocation/deallocation and the creation of the cause code itself.

Since the investigation points at an obvious cause and a pretty 'unavoidable' one, I'm going to go ahead and mark this as triaged. I've also gone ahead and filed #89000 with a possible mitigation, but regardless of whether that works, I don't think this needs further triage/investigation.

@rustbot label +perf-regression-triaged

@rustbot rustbot added the perf-regression-triaged The performance regression has been triaged. label Sep 16, 2021
@jackh726
Copy link
Member Author

Thank you so much for looking into this @Mark-Simulacrum

bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 18, 2021
…enkov

Reuse existing shared Lrc for MatchImpl parent

This is a small performance win for the hot path, which helps to address this regression: rust-lang#87244 (comment).
@jackh726 jackh726 restored the issue-71883 branch March 12, 2022 18:30
@jackh726 jackh726 deleted the issue-71883 branch March 12, 2022 18:35
@jackh726 jackh726 restored the issue-71883 branch March 12, 2022 18:42
@jackh726 jackh726 deleted the issue-71883 branch March 12, 2022 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GAT lifetime mismatch with type parametrised over dyn trait object with restricted lifetime
9 participants