Skip to content

Add CoerceShared field-wise reborrow WF checks#157489

Open
P8L1 wants to merge 1 commit into
rust-lang:mainfrom
P8L1:split/coerceshared-wf-check
Open

Add CoerceShared field-wise reborrow WF checks#157489
P8L1 wants to merge 1 commit into
rust-lang:mainfrom
P8L1:split/coerceshared-wf-check

Conversation

@P8L1
Copy link
Copy Markdown
Contributor

@P8L1 P8L1 commented Jun 5, 2026

This PR attempts to add a well-formedness check for CoerceShared.
Split out of #157101

r? @aapoalas

Localize the WF helper logic to builtin coherence and add the directly related UI coverage.
@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 Jun 5, 2026
@P8L1
Copy link
Copy Markdown
Contributor Author

P8L1 commented Jun 5, 2026

@rustbot label +F-Reborrow

@rustbot rustbot added the F-reborrow `#![feature(reborrow)]`; see #145612 label Jun 5, 2026
Copy link
Copy Markdown
Contributor

@aapoalas aapoalas left a comment

Choose a reason for hiding this comment

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

Some issues but overall this looks pretty promising.

I'd kind of like the tests to all rather be added in the #157490 and then this PR to show which ones it fixes and which ones remain issues, but I'm not too partial on that point. I've reviewed the PR in the conventional comments style, so anything marked "thought" or "note" is just musings and not something you need to necessarily react to (unless you wish to), "question" is me being unsure but not something that would block the PR from merging, and "issues" and anything else marked "blocking" must be addressed before this can be considered for merging.

I'm also somewhat surprised that this PR didn't actually change any of the existing test results... I guess that's just a sign of our existing ui feature tests being insufficient :D

View changes since this review


// FIXME(#155345): This should return `Unnormalized`
fn collect_struct_data_fields<'tcx>(
#[derive(Clone, Copy, Debug)]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: If some of these types don't use the Debug impl we could remove it to save a bit of code generation.

}

fn single_region_arg<'tcx>(args: ty::GenericArgsRef<'tcx>) -> Option<ty::Region<'tcx>> {
let mut lifetimes = args.iter().filter_map(|arg| arg.as_region());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

note: The region arguments are always at the beginning, so just doing args.first().is_some_and(|arg| arg.as_region().is_some()) or something like that would be equivalent.

lifetimes.next().is_none().then_some(lifetime)
}

fn wf_data_fields<'tcx>(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: I'd like this function name to mention collecting, and I'm not sure "wf" is correct naming here since we don't really know that the field is well-formed at this point yet.

}

// This is a coherence/WF check only. It verifies that the impl describes a
// structurally valid field relation; later runtime lowering still starts from
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: Future readers won't know what "the signle reborrow adjustment" is (and that thing might not exist at some later point in time, while this wf-check might still remain). Let's maybe reword this to something like

This is a coherence/WF check only. It verifies that the CoerceShared impl describes a structurally valid field-wise relation. Runtime lowering of the operation is not modeled here.

if by_position {
target_fields
.into_iter()
.zip(source_fields.into_iter().map(Some).chain(std::iter::repeat(None)))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thought: Huh... I somehow thought zipping iterators of different lengths would crash but that doesn't seem to be the case. Nice. Maybe I was thinking of zipping vectors?

@@ -0,0 +1,23 @@
//@ normalize-stderr: "\n\n\z" -> "\n"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: This does not appear anywhere in the code base currently. Normally this normalisation is used to deal with various platform-dependent outputs and random sources. This sort of "let's make the stderr file a little smaller in size" seems like an unnecessary complication.


// SAFETY invariant: the pointer is valid as `&'a i32`.
#[derive(Clone, Copy)]
pub struct ForeignPtrRef<'a>((*const i32, PhantomData<&'a ()>));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: The two types are subtly different to one another for no particular reason.

//~^ ERROR

fn main() {
let local = LocalPtrMut((ptr::null(), PhantomData));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

issue: This code here is not related to what is actually being tested here AFAIU. The LocalMut/ForeignRef test above does not have anything in main.

|
LL | let a = CustomMarker(PhantomData);
| - binding `a` declared here
LL | method(a);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thought: Huh... this seems confusing to me: if we've given an error from the CoerceShared implementation then I'd have assumed that here we'd get an error that CustomMarker does not match type StaticMarkerRef, ie. no adjustment should happen because CustomMarker should not implement CoerceShared...

@@ -0,0 +1,25 @@
//@ run-pass
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question (blocking): This seems to be just a copy of the custom_marker_coerce_shared_copy.rs test - is there any difference?

@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 Jun 5, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Jun 5, 2026

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-reborrow `#![feature(reborrow)]`; see #145612 S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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.

3 participants