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

Add lint for multiple associated types #50682

Merged
merged 4 commits into from
May 23, 2018
Merged

Conversation

F001
Copy link
Contributor

@F001 F001 commented May 12, 2018

Fix #50589. cc @abonander

@rust-highfive
Copy link
Collaborator

r? @michaelwoerister

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 12, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

[00:05:26] travis_fold:start:tidy
travis_time:start:tidy
tidy check
[00:05:27] tidy error: /checkout/src/librustc_lint/builtin.rs:1595: line longer than 100 chars
[00:05:28] some tidy checks failed
[00:05:28] 
[00:05:28] 
[00:05:28] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/tidy" "/checkout/src" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "--no-vendor" "--quiet"
[00:05:28] 
[00:05:28] 
[00:05:28] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test src/tools/tidy
[00:05:28] Build completed unsuccessfully in 0:02:15
[00:05:28] Build completed unsuccessfully in 0:02:15
[00:05:28] make: *** [tidy] Error 1
[00:05:28] Makefile:79: recipe for target 'tidy' failed

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:089e33f0
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

fn check_bindings(&self, ctxt: &EarlyContext, bindings: &[ast::TypeBinding]) {
let mut dup_binds = HashMap::with_capacity(bindings.len());
for b in bindings {
dup_binds.entry(b.ident.name).or_insert(vec![]).push(b.ident.span);
Copy link
Contributor

Choose a reason for hiding this comment

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

So the lint doesn't allocate for every path it checks, I think it'd be better just to do a nested loop search for any duplicates and push their spans to a Vec.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, using a HashMap<Name, Vec> to collect all the spans with the same associate type name can avoid the inner loop.
What do you mean by "the lint doesn't allocate for every path it checks"?

Copy link
Contributor

Choose a reason for hiding this comment

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

Your approach is fine, actually, I just think it shouldn't allocate until a duplicate is found, so use HashMap::new(). That way we're not allocating when we don't end up using it.

Copy link
Contributor Author

@F001 F001 May 14, 2018

Choose a reason for hiding this comment

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

Thanks. If we want to avoid allocation every time, how about keeping the HashMap as a member of struct struct DupAssocTypeBinding?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that's quite necessary, I was just concerned about allocating every time this function is called.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you are right. I have updated this function. Thanks.

@michaelwoerister
Copy link
Member

r? @nikomatsakis for re-assignment

@petrochenkov
Copy link
Contributor

Everybody forgets about hygiene :(
Rather than repeating name resolution's job incorrectly, this lint should use its results instead.
Associated type bindings are resolved to their definitions in fn ast_type_binding_to_poly_projection_predicate and then checked for privacy/stability in the same place.
The duplication check should be performed somewhere in the same place too.

@petrochenkov petrochenkov self-assigned this May 16, 2018
@abonander
Copy link
Contributor

@petrochenkov It's probably my mistake. This and #50763 were both started from my mentoring instructions and I was purely looking at the AST types since anything further in-depth would probably not be a good starting ticket.

@bors
Copy link
Contributor

bors commented May 16, 2018

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

@F001
Copy link
Contributor Author

F001 commented May 16, 2018

I will fix this when I have time in the next two days. Thanks very much!

@nikomatsakis
Copy link
Contributor

@F001 do you think you know what to do from @petrochenkov's notes?

@nikomatsakis
Copy link
Contributor

r? @petrochenkov — since you seem to have a pretty specific idea for what you want, can you take on the review? (let me know if that's a problem)

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 17, 2018
@F001
Copy link
Contributor Author

F001 commented May 18, 2018

@petrochenkov This lint is re-implemented. Please help to review. Thanks!

@@ -279,6 +279,12 @@ declare_lint! {
"detects name collision with an existing but unstable method"
}

declare_lint! {
pub DUPLICATE_ASSOCIATED_TYPE_BINDING,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add this lint to the list of deprecation lints?
(See e.g. PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES as an example.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Also duplicate_associated_type_binding -> duplicate_associated_type_bindings (see https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#lints).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@@ -565,6 +577,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
tcx.sess.span_err(binding.span, &msg);
}
tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span);
dup_bindings.entry(assoc_ty.def_id).or_insert(Vec::new()).push(binding.span);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we model this error after duplicated fields:

error[E0062]: field `a` specified more than once
 --> src/main.rs:4:23
  |
4 |     let s = S { a: 0, a: 1 };
  |                 ----  ^ used more than once
  |                 |
  |                 first use of `a`

We keep FxHashMap<DefId, Span> instead of FxHashMap<DefId, Vec<Span>> and if the inserted DefId was already in the table, report an error pointing to the first use right here.
I'd even reuse all the wording for fields (except for replacing "field a" with "associated type binding a", of course).

Copy link
Contributor

Choose a reason for hiding this comment

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

(You can attach labels and notes to the object returned by struct_span_lint_node, there are plenty of examples in the codebase.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>

warning: associated type binding `Item` specified more than once
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, the warning is reported twice.
I suspect it needs to be reported only when speculative is false.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems the warning is reported twice when speculative is false. I don't know why.

@bors
Copy link
Contributor

bors commented May 19, 2018

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

@@ -566,6 +568,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span);

if speculative {
Copy link
Contributor

Choose a reason for hiding this comment

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

if speculative -> if !speculative

@petrochenkov
Copy link
Contributor

r=me after inverting the speculative flag
@bors delegate+

@bors
Copy link
Contributor

bors commented May 20, 2018

✌️ @F001 can now approve this pull request

@F001
Copy link
Contributor Author

F001 commented May 22, 2018

@petrochenkov Thank you for your detailed mentoring. As I mentioned in the previous comment, when I use if !speculative, the warning is still reported twice.
I tried to use if speculative, this time the warning is reported only once. I think if !speculative is not the best way to solve this problem, though I can't explain why.

@petrochenkov
Copy link
Contributor

Weird. I'll look what happens.

@petrochenkov
Copy link
Contributor

Ok, this may look logically impossible unless you know that fully identical diagnostics are merged!
if speculative actually emits the warning once from the privacy pass, but if !speculative emits it thrice and the first one is not like the others due to note: #[warn(duplicate_associated_type_bindings)] on by default emitted by lint machinery itself, so it means two non-identical warnings.

This happens because instantiate_poly_trait_ref is called several times in astconv/collect for some reason.
Fixing this is probably out of scope for this PR, so let's land this with if !speculative and duplicate diagnostics.

@F001
Copy link
Contributor Author

F001 commented May 23, 2018

@bors: r=petrochenkov

@bors
Copy link
Contributor

bors commented May 23, 2018

📌 Commit 88f810f has been approved by petrochenkov

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 23, 2018
@bors
Copy link
Contributor

bors commented May 23, 2018

⌛ Testing commit 88f810f with merge 9a4e5df...

bors added a commit that referenced this pull request May 23, 2018
Add lint for multiple associated types

Fix #50589. cc @abonander
@bors
Copy link
Contributor

bors commented May 23, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: petrochenkov
Pushing 9a4e5df to master...

@bors bors merged commit 88f810f into rust-lang:master May 23, 2018
@F001 F001 deleted the issue-50589 branch August 28, 2018 10:25
Centril added a commit to Centril/rust that referenced this pull request Jan 9, 2020
Do not deduplicate diagnostics in UI tests

Error reporting infrastructure deduplicates identical diagnostics with identical spans.

While it's preferable to do this in "release"/"user-facing" mode, it sometimes brings [confusion](rust-lang#50682 (comment)) and hides details that may be important during development.

Do we run some passes multiple times when we could do it once?
How many times we run them exactly? Can this number be large? Can the multiplied error construction be expensive? Can speculative checks be made cheaper if they don't report errors?

*Relying* on this mechanism to deduplicate some specific error never looks like a proper solution to me personally.

In this PR I attempt to disable this deduplication by applying `-Z deduplicate-diagnostics=no` to UI tests.
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Jan 9, 2020
Do not deduplicate diagnostics in UI tests

Error reporting infrastructure deduplicates identical diagnostics with identical spans.

While it's preferable to do this in "release"/"user-facing" mode, it sometimes brings [confusion](rust-lang#50682 (comment)) and hides details that may be important during development.

Do we run some passes multiple times when we could do it once?
How many times we run them exactly? Can this number be large? Can the multiplied error construction be expensive? Can speculative checks be made cheaper if they don't report errors?

*Relying* on this mechanism to deduplicate some specific error never looks like a proper solution to me personally.

In this PR I attempt to disable this deduplication by applying `-Z deduplicate-diagnostics=no` to UI tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

7 participants