-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix unuseful span in type error in some format_args!() invocations #140916
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
base: master
Are you sure you want to change the base?
Conversation
Report: Current Situation (May 11 JST)Currently, my approach is to sort the candidates so that the error associated with the span of the later argument is selected: https://github.com//pull/140916/files#diff-eccdf22e4bc52ce30713fd36374bb637af1f5d233bf7f60bdf84a21de12dbe9fR166-R168At first glance, this seems to resolve the issue: // a1.rs
fn main() {
println!("{:?}", []);
}
// a2.rs
fn main() {
println!("{:?} {a} {a:?}", [], a = 1 + 1);
} $ ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc a1.rs
error[E0282]: type annotations needed
--> a1.rs:2:20
|
2 | println!("{:?}", []);
| ^^ cannot infer type
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.
$ ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc a2.rs
error[E0282]: type annotations needed
--> a2.rs:2:30
|
2 | println!("{:?} {a} {a:?}", [], a = 1 + 1);
| ^^ cannot infer type
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`. However, this approach is ad hoc and doesn't make sense. It seems necessary to limit the sorting targets to spans originating from the same $ ./x.py test --stage 1
...
failures:
...
[ui] tests/ui/typeck/issue-7813.rs
test result: FAILED. 17957 passed; 23 failed; 168 ignored; 0 measured; 0 filtered out; finished in 301.39s
$ git --no-pager diff --no-index \
tests/ui/typeck/issue-7813.stderr \
<(./build/x86_64-unknown-linux-gnu/stage1/bin/rustc tests/ui/typeck/issue-7813.rs 2>&1) diff --git a/tests/ui/typeck/issue-7813.stderr b/dev/fd/63
index 953cbd206dc..00000000000 100644
--- a/tests/ui/typeck/issue-7813.stderr
+++ b/dev/fd/63
@@ -1,13 +1,15 @@
error[E0282]: type annotations needed for `&[_; 0]`
- --> $DIR/issue-7813.rs:2:9
- |
-LL | let v = &[];
- | ^ --- type must be known at this point
- |
+ --> tests/ui/typeck/issue-7813.rs:2:9
+ |
+2 | let v = &[]; //~ ERROR type annotations needed
+ | ^
+3 | let it = v.iter();
+ | - type must be known at this point
+ |
help: consider giving `v` an explicit type, where the placeholders `_` are specified
- |
-LL | let v: &[_; 0] = &[];
- | +++++++++
+ |
+2 | let v: &[_; 0] = &[]; //~ ERROR type annotations needed
+ | +++++++++
error: aborting due to 1 previous error
↑ |
This comment has been minimized.
This comment has been minimized.
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.
@m-ou-se Could you review it at your convenience?
#[inline] | ||
pub fn len(self) -> u32 { | ||
(self.len_with_tag_or_marker & !PARENT_TAG) as u32 | ||
} |
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.
NOTE: no need in the current logic
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 be removed since it unused.
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.
yeah, remove this pls
}, | ||
) => | ||
{ | ||
(-1, e.obligation.cause.span.index()) |
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.
- Is
-1
appropriate? (Should I use unsigned integers for this sorting?) - Is
span.index()
an appropriate metric to prioritize arguments? (My initial assumption was that the negative ofspan.index()
would help prioritize arguments, but that didn't seem to be the case.)
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.
span.index seems strange... what's it for?
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.
@compiler-errors
I now understand the relevant rustc code better!
Instead of using -span.index
, it seems better to sort by -e.obligation.cause.span.data().lo
, or by:
let sm = self.tcx.sess.source_map();
let bpos = e.obligation.cause.span.data().lo
let sf_bpos = sm.lookup_byte_offset(bpos);
let line_col_dcol = sf_bpos.sf.lookup_file_pos_with_col_display(sf_bpos.pos);
-line_col_dcol.1
However, this approach also seems to have a problem.
For the following span:
2 | print!("{:?} {a} {a:?}", [], a = 1 + 1);
| ^^ cannot infer type
the captured values during sorting are bpos=BytePos(52)
, line_col_dcol.0=2
, and line_col_dcol.1=CharPos(27)
.
On the other hand, for the following span:
2 | print!("{:?} {a} {a:?}", [], a = 1 + 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
the captured values during sorting are bpos=BytePos(191660)
, line_col_dcol.0=374
, and line_col_dcol.1=CharPos(4294769381)
.
Thus, the later span is mistakenly reported as the error by -e.obligation.cause.span.data().lo
or -line_col_dcol.1
.
So my question here is:
- Is this
BytePos(191660)
just completely wrong? Could this be a bug in thelookup_file_pos_with_col_display
method? - Or is it possible that
self.tcx.sess.source_map()
is somehow inappropriate, causinglookup_file_pos_with_col_display
to return an incorrect result?
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.
Is this BytePos(191660) just completely wrong? Could this be a bug in the lookup_file_pos_with_col_display method?
I found out that lookup_file_pos_with_col_display
reports the location within the macro-expanded virtual file. In contrast, lookup_char_pos
appears to provide the correct location in the original source file. 🤔
if e.obligation.cause.span.macro_backtrace().next().is_some_and( | ||
|trace| match trace.kind { | ||
ExpnKind::Macro(_, name) => { | ||
name.as_str().rsplit("::").next() == Some("format_args_nl") |
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.
Should does this search format_args
rather than format_args_nl
?
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 think we should not limit it only for format_args_nl
, otherwise other macro such as print!
will do not got right.
@m-ou-se may be busy nowadays. |
I tried to understand why adding a sort strategy could resolve the issue, but haven't figured out it yet. maybe r? @compiler-errors know what's going on here, since the logic of suppressing was written by him. |
@@ -163,14 +163,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | |||
// Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics | |||
// with more relevant type information and hide redundant E0282 errors. | |||
errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() { | |||
ty::PredicateKind::Subtype(_) | |||
if e.obligation.cause.span.macro_backtrace().next().is_some_and( |
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 think this can be simplified with some other method like span.parent
or span.expn_kind
or something? Look on the span type for relevant functions, b/c using backtrace.next
smells wrong 🤔
}, | ||
) => | ||
{ | ||
(-1, e.obligation.cause.span.index()) |
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 could use an enum with PartialOrd
implemented on it to give these ordering precedences a name, or bump everything +1.
This comment has been minimized.
This comment has been minimized.
@compiler-errors (CC @chenyukang) I've addressed all the points you mentioned! Please take a look when you have a moment. |
Fixed #140578.
r? @m-ou-se