-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
use implied bounds when checking opaque types #106038
Conversation
Some changes occurred in engine.rs, potentially modifying the public API of cc @lcnr |
☔ The latest upstream changes (presumably #106103) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
2 nits, otherwise r=me on the second commit.
blocked on #105982
} | ||
|
||
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>; | ||
fn define<T>() -> OuterOpaque<T> {} |
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.
can you add a test which checks that this errors when define
is used with a type which is not 'static
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've added a one in pass_sound
revision. Note that it relies on #99217 for soundness.
// We don't have to check them here because their well-formedness follows from the WF of | ||
// the projection input types in the defining- and use-sites. | ||
hir::OpaqueTyOrigin::TyAlias | ||
if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(def_id.to_def_id())) => {} |
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.
that makes me a bit unhappy. Can you not instead add the type of the parent opaque type as an assumed wf type?
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.
We should not only include the type of the parent opaque type in assumed_wf_types, but also all other types that appear in the trait inputs (e.g &'static T
in impl Trait<&'static T, Assoc=impl Nested>
). The implementation can get easily complicated if we consider multiple levels of nesting and binders like:
impl Fn<(&'static T,), Output = impl for<'a> Fn<(&'a T,), Output = impl Sized + 'a>>
I think the current implementation strikes a balance between simplicity and completeness. That being said, if you feel strongly about it, I'm happy to implement the limited version of including only the parent opaque type. Note that we would reject the test wf-nested.rs
.
dfcf78d
to
4e0b8d5
Compare
☔ The latest upstream changes (presumably #110275) made this pull request unmergeable. Please resolve the merge conflicts. |
no longer blocked. |
@bors r=lcnr |
use implied bounds when checking opaque types During opaque type inference, we check for the well-formedness of the hidden type in the opaque type's own environment, not the one of the defining site, which are different in the case of TAIT. However in the case of associated-type-impl-trait, we don't use implied bounds from the impl header. This caused us to reject the following: ```rust trait Service<Req> { type Output; fn call(req: Req) -> Self::Output; } impl<'a, Req> Service<&'a Req> for u8 { type Output= impl Sized; // we can't prove WF of hidden type `WF(&'a Req)` although it's implied by the impl //~^ ERROR type parameter Req doesn't live long enough fn call(req: &'a Req) -> Self::Output { req } } ``` although adding an explicit bound would make it pass: ```diff - impl<'a, Req> Service<&'a Req> for u8 { + impl<'a, Req> Service<&'a Req> for u8 where Req: 'a, { ``` I believe it should pass as we already allow the concrete type to be used: ```diff impl<'a, Req> Service<&'a Req> for u8 { - type Output= impl Sized; + type Output= &'a Req; ``` Fixes rust-lang#95922 Builds on rust-lang#105982 cc `@lcnr` (because implied bounds) r? `@oli-obk`
…mpiler-errors Rollup of 7 pull requests Successful merges: - rust-lang#106038 (use implied bounds when checking opaque types) - rust-lang#111366 (Make `NonUseContext::AscribeUserTy` carry `ty::Variance`) - rust-lang#111375 (CFI: Fix SIGILL reached via trait objects) - rust-lang#111439 (Fix backtrace normalization in ice-bug-report-url.rs) - rust-lang#111444 (Only warn single-use lifetime when the binders match.) - rust-lang#111459 (Update browser-ui-test version to 0.16.0) - rust-lang#111460 (Improve suggestion for `self: Box<self>`) Failed merges: - rust-lang#110454 (Require impl Trait in associated types to appear in method signatures) r? `@ghost` `@rustbot` modify labels: rollup
During opaque type inference, we check for the well-formedness of the hidden type in the opaque type's own environment, not the one of the defining site, which are different in the case of TAIT.
However in the case of associated-type-impl-trait, we don't use implied bounds from the impl header. This caused us to reject the following:
although adding an explicit bound would make it pass:
I believe it should pass as we already allow the concrete type to be used:
Fixes #95922
Builds on #105982
cc @lcnr (because implied bounds)
r? @oli-obk