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

Prevent opaque types in impl headers #87382

Closed
wants to merge 3 commits into from
Closed

Conversation

lqd
Copy link
Member

@lqd lqd commented Jul 22, 2021

Previously, #76940 forbade simple trait impls only from using opaque types, to prevent ICES.

However, this still allowed the same ICEs in codegen on more complex cases like #86411, and could also allow weaponization via a safe transmute, as shown in #84660.

This PR prevents opaque types from appearing in impl headers altogether as requested in Niko's comment.

Fixes #86411.
Fixes #84660.

r? @oli-obk

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 22, 2021
if let ty::Opaque(def_id, _) = *ty.kind() {
self.tcx
.sess
.struct_span_err(sp, "cannot implement trait on type alias impl trait")
Copy link
Contributor

Choose a reason for hiding this comment

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

I have an idea that could help with this span, not sure if it pans out. Create a new visitor struct. Implement intravisit::Visitor for it, most notably implement the Visitor::visit_qpath method and use qpath_res to get the DefId. If it is equal to the opaque type's use that span. If no span is found during visiting, fall back to the one you have right now.

First visit the self_ty variable, and if no span is found, visit the tr variable.

Copy link
Member Author

@lqd lqd Jul 23, 2021

Choose a reason for hiding this comment

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

IIUC qpath_res doesn't work here since we're not in an Expr or Pat node, but the qpath should be resolved so we can extract its res anyway. However, when visiting the self_ty, the qpath's def_id is not the same as the opaque type's here. (It's almost as if the visitor is seeing the type alias node, while the TypeFolder sees the opaque type node)

@oli-obk
Copy link
Contributor

oli-obk commented Jul 22, 2021

i wonder if we need to walk trait bounds of the impl, too

@lqd
Copy link
Member Author

lqd commented Jul 22, 2021

IIUC this is where the difference between walking and folding will be most visible: folding over the substs like this PR does will visit the trait bounds of the impl (and it was my understanding that we should do so), while walking will need to visit both the self_ty and the tr ?

@oli-obk
Copy link
Contributor

oli-obk commented Jul 23, 2021

yea, I think a visitor is indeed better. I didn't mean walking the self_ty and tr, these are HIR variables, I only meant to use them to improve the span.

i wonder if we need to walk trait bounds of the impl, too

What I mean here is that we just look at the generics on the traitref. So for impl<T: Foo, U: Meh> Bar<T> for Mop<U> the substs are

[Mop<U>, T]

as the Self of a TraitRef is always at index 0 and in this case is Mop<U>

We entirely ignore Foo and Meh here, so I'm guessing we could still have a Foo<SomeTypeAliasImplTrait> bound and I'm not sure of the effects of that, but we should probably forbid it for now, too.

In order to get these generics, you can call tcx.predicates_of which gives you all the where bounds, and then visit those, too (just visit a tuple of the predicates and the substs, no need to visit twice)

@bors
Copy link
Contributor

bors commented Jul 28, 2021

☔ The latest upstream changes (presumably #87540) made this pull request unmergeable. Please resolve the merge conflicts.

@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 15, 2021
@inquisitivecrystal inquisitivecrystal added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 24, 2021
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 13, 2021
@JohnCSimon
Copy link
Member

Triage:
@lqd Can you please address the merge conflicts?

@JohnCSimon
Copy link
Member

Ping from Triage:
@lqd Can you please address the merge conflicts?

@lqd
Copy link
Member Author

lqd commented Sep 28, 2021

Sure.

I do have a question for @oli-obk though: does the new lazy TAIT approach change anything with respect to the ICEs, "safe transmute" above, and so on. That is, do we still have the problem and the solution we talked about earlier is still the one to follow ? (Or maybe this would be fixed with the new lazy TAITs ?)

@oli-obk
Copy link
Contributor

oli-obk commented Sep 28, 2021

No, lazy taits do not help here, they only change behavior within functions, not anything about their theoretically legal use sites. This site is still as problematic as in the linked comments in the main post

@lqd
Copy link
Member Author

lqd commented Sep 29, 2021

Great, I'll update this PR, thanks @oli-obk !

@lqd
Copy link
Member Author

lqd commented Oct 3, 2021

Closing so that it doesn't need to be triaged periodically by the WG. Will reopen when I update this PR.

@lqd lqd closed this Oct 3, 2021
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Apr 12, 2022
prevent opaque types from appearing in impl headers

cc `@lqd`

opaque types are not distinguishable from their hidden type at the codegen stage. So we could either end up with cases where the hidden type doesn't implement the trait (which will thus ICE) or where the hidden type does implement the trait (so we'd be using its impl instead of the one written for the opaque type). This can even lead to unsound behaviour without unsafe code.

Fixes rust-lang#86411.
Fixes rust-lang#84660.

rebase of rust-lang#87382 plus some diagnostic tweaks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.
Projects
None yet
7 participants