-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
diagnostic: properly deal with hygienic names on unresolved fields and imports #116575
Conversation
PatKind::Struct(path, [], false) if path.span().eq_ctxt(pat.span) => { | ||
(" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can generalize this by looking at path.span().ancestor_within_span(pat.span)
.
PatKind::Struct(..) if field.span.eq_ctxt(pat.span) => { | ||
(", ", " }", field.span.shrink_to_hi().with_hi(pat.span.hi())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can generalize this by looking at field.span.ancestor_within_span(pat.span)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've already tried using find_ancestor_inside
in some earlier version of this patch before opening a PR without a satisfying result if I remember correctly. However, let me check again tomorrow, I might've missed something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, so I'm almost certain that pat.span.FIND_ANCESTOR(field.span)
with FIND_ANCESTOR
∊ {find_ancestor_inside
, find_ancestor_in_same_ctxt
} or just field.span
isn't what we want here, (see next comment).eq_ctxt
is conservative and correct
If the field and the struct patterns aren't in the same syntax context, there's not much we can do here structured-suggestion-wise without resorting to elaborate span_to_snippet
hacks. If the field comes from a different expansion, then the struct pattern has to be of the form S { … $field … }
or S { … $( … )… … }
, meaning the field has to be a metavariable or a repetition but notably not a macro call like S { … m!(…) … }
(ungrammatical). Therefore, there are two location were we could theoretically suggest the unmentioned fields:
- At the end of the struct pattern (~
pat.span
): However, we don't know if we should add a leading comma or not since we'd need to look at def-site (considerS { $( $fields/*,*/ )* }
) and use-site (considerm!(field/*,*/)
) which requiresspan_to_snippet
I think and is ugly. The suggestion is markedMachineApplicable
btw (we could ofc tweak that in this case to beMaybeIncorrect
). - At the end of the last field (~
field.span
)- However, the other fields (other than the last one) might come from a more "general" expansion.
- The suggestion might be incorrect since we don't know the shape of the metavariable
$field
(etc.). Considerm!(field: _)
where we don't know if the suggestionm!(field: _, missing: _)
would be valid input for macrom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've noticed that eq_ctxt
is not sufficient anyway for preventing invalid suggestions. For example:
struct S {
a: (),
b: (),
}
macro_rules! n {
($( $f:ident )?) => {
let S { $( $f )? } = loop {};
}
}
fn main() {
n!(a);
}
Here, we suggest garbage:
error[E0027]: pattern does not mention field `b`
--> krash.rs:17:13
|
17 | let S { $( $f )? } = loop {};
| ^^^^^^^^^^^^^^ missing field `b`
...
23 | n!(a);
| ----- in this macro invocation
|
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
help: include the missing field in the pattern
|
17 | let S { $( $f, b } = loop {};
| ~~~~~
help: if you don't care about this missing field, you can explicitly ignore it
|
17 | let S { $( $f, .. } = loop {};
| ~~~~~~
On master, we don't but on the other hand we misclassifiy a
and b
to be inaccessible:
error: pattern requires `..` due to inaccessible fields
--> krash.rs:17:13
|
17 | let S { $( $f )? } = loop {};
| ^^^^^^^^^^^^^^
...
23 | n!(a);
| ----- in this macro invocation
|
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
help: ignore the inaccessible and unused fields
|
17 | let S { $( $f, .. )? } = loop {};
| ++++
Seems like I still need to tweak some things :|.
@@ -2170,15 +2171,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||
fn available_field_names( | |||
&self, | |||
variant: &'tcx ty::VariantDef, | |||
expr: &hir::Expr<'_>, | |||
span: Span, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you specify which span this is?
☔ The latest upstream changes (presumably #118046) made this pull request unmergeable. Please resolve the merge conflicts. |
@fmease any updates on this? thanks |
Ping from triage: I'm closing this due to inactivity, Please reopen when you are ready to continue with this. @rustbot label: +S-inactive |
Follow-up to #116429:
Case
and the macroenvironment
)e.f
/ struct patternS { f }
when comparing syntax contexts which wasn't correct since their constituent parts may come from different expansions, consider$e.f
vse.$f
orS { $f, $g }
with expn($f
) ≠ expn($g
). Now I use the most precise span where possibler? @compiler-errors (feel free to reassign if you're short on time)