Skip to content

Add method find_ancestor_not_from_macro and find_ancestor_not_from_extern_macro to supersede find_oldest_ancestor_in_same_ctxt #144268

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

Merged
merged 1 commit into from
Jul 30, 2025

Conversation

xizheyin
Copy link
Contributor

As I was using it, I realized that the function is supposed to walk up to expand the chain? This seems to be the opposite of what I understood.

r? @jieyouxu

@rustbot
Copy link
Collaborator

rustbot commented Jul 21, 2025

jieyouxu is currently at their maximum review capacity.
They may take a while to respond.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 21, 2025
Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

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

Hm, I'm not actually 100% this helper is doing what I originally wanted it to do... This will try to keep traversing up the macro invocation chain that produced the provided final span at hand to find the oldest ancestor which has... the same syntax context as the provided final span (???) I suppose this might work if the passed in span you know is "local" and the user actually has control over 🤔

I feel like this is wrong, or least quite confusing... I wonder if you could go the other direction and use instead https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.find_ancestor_in_same_ctxt or https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.find_ancestor_inside_same_ctxt and get rid of this helper.

@jieyouxu
Copy link
Member

@rustbot author (re. discussion)

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 22, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jul 22, 2025

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jul 22, 2025
@xizheyin
Copy link
Contributor Author

I found some problems with the comments of these APIs, I subconsciously thought that finding an ancestor would be traversing the macro expansion chain from bottom to top, but they all use “walk down”. This seems to create ambiguity. I'll look into these APIs later when I have time and find the best way to do it.

@xizheyin xizheyin force-pushed the find-oldest-ancestor branch from a2a1033 to 2f977ce Compare July 22, 2025 16:23
@xizheyin xizheyin changed the title Fix comments of find_oldest_ancestor_in_same_ctxt Add method find_ancestor_not_from_macro and find_ancestor_not_from_extern_macro to fix find_oldest_ancestor_in_same_ctxt Jul 22, 2025
@xizheyin
Copy link
Contributor Author

I found that find_oldest_ancestor_in_same_ctxt does have a logical problem, but by some mischance it works successfully in some places.
The places where it is needed are basically related to macros, and my understanding is that the proper ancestor should be found without any other span help, e.g. outer in span.find_ancestor_inside(outer).

I added two methods that allow for more fine-grained control. This change should help fix all the diagnostics shown in the macros in the standard library(#142403).

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 22, 2025
@rust-log-analyzer

This comment has been minimized.

Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

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

Hm, is it possible to add specific test cases demonstrating the behaviors of

  • find_ancestor_not_from_macro
  • find_ancestor_not_from_extern_macro
  • find_oldest_ancestor_in_same_ctxt

Otherwise, we'd have no idea what effect changing the impls of these helpers might be.

@rustbot rustbot 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 Jul 25, 2025
@xizheyin
Copy link
Contributor Author

I don't know how to add the right test cases, but I can find the test case corresponding to the diagnostic I modified in this PR, which should be very helpful to understand its behavior. I'm going to insert the debug macro in the method of concern, and then print the debug message via what compile-flag? Do you have a better idea?

@xizheyin
Copy link
Contributor Author

For find_ancestor_not_from_macro, it will look along the call chain from the span inside the macro until it finds the first span that is not inside the macro. As in this example, the span is in L16 instead of L11.

macro_rules! perform { ($e:expr) => { D(&$e).end() } }
//~^ ERROR does not live long enough
//~| ERROR does not live long enough
fn main() {
{ let l = (); perform!(l) };
//~^ SUGGESTION ;

help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
LL | { let l = (); perform!(l); };
| +


For find_ancestor_not_from_macro, it will look along the call chain from the initial span until it finds the first span that is not inside the external macro.
In this example, the initial span is located inside the format macro, and we need user-written code (not concerned here with whether it's located inside the macro), so we use find_ancestor_not_from_macro. It return the span inside entire_fn which is user-written code.

macro_rules! entire_fn {
() => {
pub fn baz(x: &str) -> Result<(), Box<dyn std::error::Error>> {
Err(format!("error: {x}"))
//~^ ERROR mismatched types
}
}
}

error[E0308]: mismatched types
--> $DIR/issue-110017-format-into-help-deletes-macro.rs:51:5
|
LL | nontrivial!(x)
| ^^^^^^^^^^^^^^ expected `Box<dyn Error>`, found `String`
|
= note: expected struct `Box<dyn std::error::Error>`
found struct `String`
= note: this error originates in the macro `format` which comes from the expansion of the macro `nontrivial` (in Nightly builds, run with -Z macro-backtrace for more info)
help: call `Into::into` on this expression to convert `String` into `Box<dyn std::error::Error>`
|
LL | Err(format!("error: {}", $x).into())
| +++++++


For the find_oldest_ancestor_in_same_ctxt implementation, we can see from the source code that it looks for the oldest ancestor in the same syntactic context.

pub fn find_oldest_ancestor_in_same_ctxt(self) -> Span {
let mut cur = self;
while cur.eq_ctxt(self)
&& let Some(parent_callsite) = cur.parent_callsite()
{
cur = parent_callsite;
}
cur
}

For both examples, it worked successfully by mistake.

  1. for the first example, the initial span (i.e. self) is located at L11, but since at the very beginning cur.eq_ctxt(self) is true, it goes into a loop once, so self becomes its parent, i.e. L16. in the second loop, L11.eq(L16) is false, so it ends up returning L16.
  2. for the second example, the original span is located inside the format macro (there is only one layer of calls), and similarly, after the first loop, the new self is located in L20, and the original span is located in the standard library, so cur.eq_ctxt(self) is false, and once again the correct value is returned by mistake.
    So we can see that the method actually returns the first ancestor span that is not in the same context.

This problem was discovered when I was solving #144266. Because it had multiple layers of macro calls, so the returned span of find_oldest_ancestor_in_same_ctxt was still in the debug_assert_eq macro.

@rustbot ready

  1. https://github.com/rust-lang/rust/blob/master/tests/ui/borrowck/span-semicolon-issue-139049.rs
  2. https://github.com/rust-lang/rust/blob/d242a8bd5a73f633ba1ec5aacf19acf35a3c747d/tests/ui/typeck/issue-110017-format-into-help-deletes-macro.rs

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 28, 2025
Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

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

Okay, I think there might still be cases where these are insufficient, but at least find_oldest_ancestor_in_same_ctxt seems definitely wrong.

@jieyouxu
Copy link
Member

Thanks
@bors r+ rollup

@bors
Copy link
Collaborator

bors commented Jul 28, 2025

📌 Commit 66d2d16 has been approved by jieyouxu

It is now in the queue for this repository.

@bors bors removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 28, 2025
samueltardieu added a commit to samueltardieu/rust that referenced this pull request Jul 28, 2025
…ieyouxu

Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`

As I was using it, I realized that the function is supposed to walk up to expand the chain? This seems to be the opposite of what I understood.

r? `@jieyouxu`
bors added a commit that referenced this pull request Jul 29, 2025
Rollup of 11 pull requests

Successful merges:

 - #143289 (Remove `[T]::array_chunks(_mut)`)
 - #143883 (Add `--link-targets-dir` argument to linkchecker)
 - #144034 (tests: Test line number in debuginfo for diverging function calls)
 - #144236 (Add `core::mem::DropGuard`)
 - #144268 (Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`)
 - #144303 (Consolidate staging for `rustc_private` tools)
 - #144539 (constify with_exposed_provenance)
 - #144569 (rustc-dev-guide subtree update)
 - #144573 (Raw Pointers are Constant PatKinds too)
 - #144578 (Ensure correct aligement of rustc_hir::Lifetime on platforms with lower default alignments.)
 - #144582 (fix `Atomic*::as_ptr` wording)

r? `@ghost`
`@rustbot` modify labels: rollup
Zalathar added a commit to Zalathar/rust that referenced this pull request Jul 29, 2025
…ieyouxu

Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`

As I was using it, I realized that the function is supposed to walk up to expand the chain? This seems to be the opposite of what I understood.

r? ``@jieyouxu``
Zalathar added a commit to Zalathar/rust that referenced this pull request Jul 29, 2025
…ieyouxu

Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`

As I was using it, I realized that the function is supposed to walk up to expand the chain? This seems to be the opposite of what I understood.

r? ```@jieyouxu```
@Zalathar
Copy link
Contributor

This seems to have failed in rollup: #144619 (comment)

@bors r-

@bors bors 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jul 29, 2025
@jieyouxu jieyouxu closed this Jul 29, 2025
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jul 29, 2025
@jieyouxu jieyouxu reopened this Jul 29, 2025
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 29, 2025
@rust-log-analyzer

This comment has been minimized.

@xizheyin
Copy link
Contributor Author

i should rebase the branch

@xizheyin xizheyin force-pushed the find-oldest-ancestor branch from 66d2d16 to 81176b1 Compare July 29, 2025 06:55
Copy link
Contributor Author

@xizheyin xizheyin left a comment

Choose a reason for hiding this comment

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

waiting for CI green

@@ -1302,7 +1302,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => ".clone()".to_string(),
};

let span = expr.span.find_oldest_ancestor_in_same_ctxt().shrink_to_hi();
let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span).shrink_to_hi();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

rebased.

@xizheyin
Copy link
Contributor Author

ready:>

@jieyouxu
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Jul 30, 2025

📌 Commit 81176b1 has been approved by jieyouxu

It is now in the queue for this repository.

@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 30, 2025
bors added a commit that referenced this pull request Jul 30, 2025
Rollup of 6 pull requests

Successful merges:

 - #144042 (Verify llvm-needs-components are not empty and match the --target value)
 - #144268 (Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`)
 - #144411 (Remove `hello_world` directory)
 - #144662 (compiletest: Move directive names back into a separate file)
 - #144666 (Make sure to account for the right item universal regions in borrowck)
 - #144668 ([test][run-make] add needs-llvm-components)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 02a68e4 into rust-lang:master Jul 30, 2025
10 checks passed
@rustbot rustbot added this to the 1.90.0 milestone Jul 30, 2025
rust-timer added a commit that referenced this pull request Jul 30, 2025
Rollup merge of #144268 - xizheyin:find-oldest-ancestor, r=jieyouxu

Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`

As I was using it, I realized that the function is supposed to walk up to expand the chain? This seems to be the opposite of what I understood.

r? `@jieyouxu`
github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Jul 31, 2025
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#144042 (Verify llvm-needs-components are not empty and match the --target value)
 - rust-lang/rust#144268 (Add method `find_ancestor_not_from_macro` and `find_ancestor_not_from_extern_macro` to supersede `find_oldest_ancestor_in_same_ctxt`)
 - rust-lang/rust#144411 (Remove `hello_world` directory)
 - rust-lang/rust#144662 (compiletest: Move directive names back into a separate file)
 - rust-lang/rust#144666 (Make sure to account for the right item universal regions in borrowck)
 - rust-lang/rust#144668 ([test][run-make] add needs-llvm-components)

r? `@ghost`
`@rustbot` modify labels: rollup
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. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants