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

ty: projections in transparent_newtype_field #73257

Merged

Conversation

davidtwco
Copy link
Member

Fixes #73249.

This PR modifies transparent_newtype_field so that it handles
projections with generic parameters, where normalize_erasing_regions
would ICE.

@rust-highfive
Copy link
Collaborator

r? @eddyb

(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 Jun 11, 2020
@lcnr
Copy link
Contributor

lcnr commented Jun 11, 2020

I don't think this is the best approach here.
Afaict the following still causes an ICE:

pub trait Foo {
    type Assoc: 'static;
}

impl Foo for () {
    type Assoc = u32;
}

extern "C" {
    pub fn lint_me(x: Bar<()>);
}

#[repr(transparent)]
pub struct Bar<T: Foo> {
    value: &'static <T as Foo>::Assoc,
}

Afaik extern functions must be fully monomorphic (ignoring lifetimes), in which case you should probably have relevant substs here.

@davidtwco davidtwco force-pushed the issue-73249-improper-ctypes-projection branch from 8171d28 to 3b094d3 Compare June 11, 2020 22:28
@davidtwco
Copy link
Member Author

davidtwco commented Jun 11, 2020

I don't think this is the best approach here.

I've force pushed over the commit to make the case you highlighted work - well spotted.

I added the function being modified here in #72890. It deliberately does not apply substitutions so that it can identify the field in a transparent struct which is a non-ZST. If the non-zero-sized field were a generic parameter, and if it were substituted for () and we didn't do this then the previous logic would find that all fields were zero-sized and lint incorrectly for that reason. Using this function, we can identify which field is normally non-zero-sized, and handle that case correctly.

Given that, I think that having this function is the appropriate approach and it being unable to handle this case is just an oversight. If you have a better approach, then I'm open to making changes though.

@lcnr
Copy link
Contributor

lcnr commented Jun 12, 2020

Your current approach still seems somewhat unfortunate to me, I think this warns on:

use std::marker::PhantomData;

trait Foo {
    type Assoc;
}

impl Foo for () {
    type Assoc = PhantomData<()>;
}

#[repr(transparent)]
struct Wow<T> where T: Foo<Assoc = PhantomData<T>> {
    x: <T as Foo>::Assoc,
    v: u32,
}

extern "C" {
    fn test(v: Wow<()>);
}

It deliberately does not apply substitutions so that it can identify the field in a transparent struct which is a non-ZST. If the non-zero-sized field were a generic parameter, and if it were substituted for () and we didn't do this then the previous logic would find that all fields were zero-sized and lint incorrectly for that reason.

I can't quite follow you here, do you explicitly not want to lint for

#[repr(transparent)]
struct Foo<T> {
    inner: T,
}

extern "C" {
    fn foo(v: Foo<()>);
}

If I understand this correctly, structs with #[repr(transparent)] must have exactly 0 or 1 non zero sized fields. Would it work to add FfiResult::FfiZst and delay emitting errors on ZST fields of transparent structs similar to what is already done with FfiPhantom.

@davidtwco
Copy link
Member Author

davidtwco commented Jun 12, 2020

Your current approach still seems somewhat unfortunate to me, I think this warns on:

It does - I've pushed a commit that fixes this and simplifies transparent_newtype_field further.

I can't quite follow you here, do you explicitly not want to lint for

This case does lint and it should.

The previous behavior for transparent types was to skip any that were zero-sized. Consider the second example from your comment, with struct Foo, and the old logic:

  • In argument position, this type's fields would all be skipped and the type would be considered "composed only of PhantomData" - that's not entirely correct, but the lint would trigger, so we're good.
  • In return position, this type is equivalent to () - which shouldn't lint, because that's just a function which doesn't return anything - that was the subject of Types equal to/wrapping () result in "not FFI-safe" warning #66202. However, a lint would be produced, as the type is still considered "composed only of PhantomData".

With the new behavior for transparent types, where the non-ZST field is identified and only that field is checked, we would correctly determine that the () is FFI-unsafe; but that result can then be threaded up to the logic that says "ignore that FFI-unsafe result if this is the return type and it was a ()".

In the previous behaviour, the FfiPhantom that we had contained the whole type (not just the field's type) and so we couldn't handle that return-type case easily.

There are certainly other ways I could have solved this - I don't think that identifying the non-ZST field is the only way, but it's quite explicit about what we're checking and I prefer that; I am open to better approaches, but I don't think using a FfiZst would necessarily handle that case (it could be made to, in the same way as the FfiPhantom approach taken previously to transparent types could have but I don't think that would be better necessarily).


I've pushed some other commits too:

Copy link
Contributor

@lcnr lcnr left a comment

Choose a reason for hiding this comment

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

LGTM, the new transparent_newtype_field now also looks good 👍

src/librustc_lint/types.rs Show resolved Hide resolved
@davidtwco davidtwco force-pushed the issue-73249-improper-ctypes-projection branch from c8c9404 to 94d337d Compare June 12, 2020 18:26
@rust-highfive

This comment has been minimized.

@davidtwco davidtwco force-pushed the issue-73249-improper-ctypes-projection branch from 94d337d to 61b24fd Compare June 13, 2020 15:52
@davidtwco
Copy link
Member Author

Pushed a minor commit re-wording to re-trigger CI as the last failure was spurious.

@jonas-schievink
Copy link
Contributor

r? @varkor

@rust-highfive rust-highfive assigned varkor and unassigned eddyb Jun 16, 2020
@varkor
Copy link
Member

varkor commented Jun 18, 2020

@bors r=lcnr,varkor

@bors
Copy link
Contributor

bors commented Jun 18, 2020

📌 Commit 61b24fd2561beccc4787878272c96b52d4d8a0a8 has been approved by lcnr,varkor

@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 Jun 18, 2020
@spastorino
Copy link
Member

@bors p=1

@bors
Copy link
Contributor

bors commented Jun 18, 2020

⌛ Testing commit 61b24fd2561beccc4787878272c96b52d4d8a0a8 with merge 70af37bb5fb964d44612cfb095dc2c498e8f2a6e...

@bors

This comment has been minimized.

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jun 18, 2020
@jonas-schievink
Copy link
Contributor

@bors r=lcnr,varkor

@bors
Copy link
Contributor

bors commented Jun 19, 2020

📌 Commit a730d88 has been approved by lcnr,varkor

@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 Jun 19, 2020
@bors
Copy link
Contributor

bors commented Jun 19, 2020

⌛ Testing commit a730d88 with merge 3406beccc47c0d5beafc066cb3b14dbba08f1298...

Manishearth added a commit to Manishearth/rust that referenced this pull request Jun 19, 2020
…es-projection, r=lcnr,varkor

ty: projections in `transparent_newtype_field`

Fixes rust-lang#73249.

This PR modifies `transparent_newtype_field` so that it handles
projections with generic parameters, where `normalize_erasing_regions`
would ICE.
@Manishearth
Copy link
Member

@bors retry yield

@bors
Copy link
Contributor

bors commented Jun 19, 2020

⌛ Testing commit a730d88 with merge 2d8bd9b...

@Manishearth
Copy link
Member

@bors yield

@Manishearth
Copy link
Member

@bors retry yield

@bors
Copy link
Contributor

bors commented Jun 19, 2020

☀️ Test successful - checks-azure
Approved by: lcnr,varkor
Pushing 2d8bd9b to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Jun 19, 2020
@bors bors merged commit 2d8bd9b into rust-lang:master Jun 19, 2020
@Manishearth
Copy link
Member

wh...what the hell? @pietroalbini this had yielded to the rollup, but it still merged

is yield implemented properly?

@Manishearth
Copy link
Member

I think this is how those "test timed out" locks happen, because bors will continue testing the rollup and then realize it can't merge it

bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 19, 2020
…arth

Rollup of 13 pull requests

Successful merges:

 - rust-lang#71568 (Document unsafety in slice/sort.rs)
 - rust-lang#72709 (`#[deny(unsafe_op_in_unsafe_fn)]` in liballoc)
 - rust-lang#73214 (Add asm!() support for hexagon)
 - rust-lang#73248 (save_analysis: improve handling of enum struct variant)
 - rust-lang#73257 (ty: projections in `transparent_newtype_field`)
 - rust-lang#73261 (Suggest `?Sized` when applicable for ADTs)
 - rust-lang#73300 (Implement crate-level-only lints checking.)
 - rust-lang#73334 (Note numeric literals that can never fit in an expected type)
 - rust-lang#73357 (Use `LocalDefId` for import IDs in trait map)
 - rust-lang#73364 (asm: Allow multiple template string arguments; interpret them as newline-separated)
 - rust-lang#73382 (Only display other method receiver candidates if they actually apply)
 - rust-lang#73465 (Add specialization of `ToString for char`)
 - rust-lang#73489 (Refactor hir::Place)

Failed merges:

r? @ghost
@davidtwco davidtwco deleted the issue-73249-improper-ctypes-projection branch June 20, 2020 11:09
@pietroalbini
Copy link
Member

wh...what the hell? @pietroalbini this had yielded to the rollup, but it still merged

is yield implemented properly?

@Manishearth "yield" does not exist in the bors code, is just a comment saying why the PR was retried. The yield usually works because when the retry happens bors starts testing the PR with higher priority, and cancelbot kills the previous build since a new commit was pushed to auto.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. 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.

ICE: could not fully normalize