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

Enforce Sized return types on Fn* bounds #83915

Closed

Conversation

estebank
Copy link
Contributor

@estebank estebank commented Apr 6, 2021

In a fn() -> Out bound, enforce Out: Sized to avoid unsoundness.

Fix #82633.

r? @pnkfelix cc @nikomatsakis

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 6, 2021
@rust-log-analyzer

This comment has been minimized.

@camelid camelid added the A-typesystem Area: The type system label Apr 6, 2021
@rust-log-analyzer

This comment has been minimized.

@estebank
Copy link
Contributor Author

estebank commented Apr 6, 2021

I'm puzzled, I haven't been able to reproduce the problem locally.

def_id: lang_items.sized_trait().unwrap(),
substs: self.tcx().mk_substs_trait(ty, &[]),
};
if !matches!(ty.kind(), ty::Projection(_) | ty::Opaque(..)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For reviewer context, the filtering out of projections and opaque types is a hack and shouldn't be necessary long term if we find a better place to inject the Sized obligation.

If I don't keep this in, then we start failing stage 1 builds. This tells me there's a better place to inject this obligation, but I haven't been able to find it.

if [lang_items.fn_once_trait(), lang_items.fn_trait(), lang_items.fn_mut_trait()]
.contains(&Some(obligation.predicate.def_id()))
// Skip `MiscObligation`s for better output.
&& matches!(obligation.cause.code, ObligationCauseCode::BindingObligation(_, _))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can look at the diff between the two commits to see what this check changes.

@nikomatsakis nikomatsakis self-assigned this Apr 6, 2021
In a `fn() -> Out` bound, enforce `Out: Sized` to avoid unsoundness.

Fix rust-lang#82633.
@estebank estebank force-pushed the closure-return-must-be-sized branch from 093d25b to 670d20d Compare April 6, 2021 20:01
{
// Do not allow `foo::<fn() -> A>();` for `A: !Sized` (#82633)
let fn_sig = obligation.predicate.self_ty().skip_binder().fn_sig(self.tcx());
let ty = self.infcx.replace_bound_vars_with_placeholders(fn_sig.output());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using replace_bound_vars_with_placeholders pacified CI, but I still don't understand why it wasn't triggering on my machine. Maybe the assert! wasn't being run locally?

@nikomatsakis
Copy link
Contributor

@nikomatsakis
Copy link
Contributor

Alternate branch: https://github.com/nikomatsakis/rust/tree/issue-82633-sized-return-types

This fix is not perfect, but may be a better stepping stone.

@crlf0710 crlf0710 added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 8, 2021
@apiraino apiraino added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Oct 14, 2021
@bors
Copy link
Contributor

bors commented Feb 21, 2022

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

bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 21, 2022
…zed, r=jackh726

a fn pointer doesn't implement `Fn`/`FnMut`/`FnOnce` if its return type isn't sized

I stumbled upon rust-lang#83915 which hasn't received much attention recently, and I wanted to revive it since this is one existing soundness hole that seems pretty easy to fix.

I'm not actually sure that the [alternative approach described here](rust-lang#83915 (comment)) is sufficient, given the `src/test/ui/function-pointer/unsized-ret.rs` example I provided below. Rebasing the branch mentioned in that comment and testing that UI test, it seems that we actually end up only observing that `str: !Sized` during monomorphization, whereupon we ICE. Even if we were to fix that ICE, ideally we'd be raising an error that a fn pointer is being used badly during _typecheck_ instead of monomorphization, hence adapting the original approach in rust-lang#83915.

I am happy to close this if people would prefer we rebase the original PR and land that -- I am partly opening to be annoying and get people thinking about this unsoundness again ❤️ 😸

cc: `@estebank` and `@nikomatsakis`
r? types

Here's a link to the thread: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/PR.20.2383915/near/235421351 for more context.
@lcnr
Copy link
Contributor

lcnr commented Oct 4, 2022

I think this PR can now be closed in favor of #100096? 🤔

feel free to reopen if that isn't the case

@lcnr lcnr closed this Oct 4, 2022
@estebank
Copy link
Contributor Author

estebank commented Oct 5, 2022

@lcnr I'm just happy it's finally handled

RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this pull request Apr 20, 2024
…ckh726

a fn pointer doesn't implement `Fn`/`FnMut`/`FnOnce` if its return type isn't sized

I stumbled upon #83915 which hasn't received much attention recently, and I wanted to revive it since this is one existing soundness hole that seems pretty easy to fix.

I'm not actually sure that the [alternative approach described here](rust-lang/rust#83915 (comment)) is sufficient, given the `src/test/ui/function-pointer/unsized-ret.rs` example I provided below. Rebasing the branch mentioned in that comment and testing that UI test, it seems that we actually end up only observing that `str: !Sized` during monomorphization, whereupon we ICE. Even if we were to fix that ICE, ideally we'd be raising an error that a fn pointer is being used badly during _typecheck_ instead of monomorphization, hence adapting the original approach in #83915.

I am happy to close this if people would prefer we rebase the original PR and land that -- I am partly opening to be annoying and get people thinking about this unsoundness again ❤️ 😸

cc: `@estebank` and `@nikomatsakis`
r? types

Here's a link to the thread: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/PR.20.2383915/near/235421351 for more context.
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this pull request Apr 27, 2024
…ckh726

a fn pointer doesn't implement `Fn`/`FnMut`/`FnOnce` if its return type isn't sized

I stumbled upon #83915 which hasn't received much attention recently, and I wanted to revive it since this is one existing soundness hole that seems pretty easy to fix.

I'm not actually sure that the [alternative approach described here](rust-lang/rust#83915 (comment)) is sufficient, given the `src/test/ui/function-pointer/unsized-ret.rs` example I provided below. Rebasing the branch mentioned in that comment and testing that UI test, it seems that we actually end up only observing that `str: !Sized` during monomorphization, whereupon we ICE. Even if we were to fix that ICE, ideally we'd be raising an error that a fn pointer is being used badly during _typecheck_ instead of monomorphization, hence adapting the original approach in #83915.

I am happy to close this if people would prefer we rebase the original PR and land that -- I am partly opening to be annoying and get people thinking about this unsoundness again ❤️ 😸

cc: `@estebank` and `@nikomatsakis`
r? types

Here's a link to the thread: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/PR.20.2383915/near/235421351 for more context.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. 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.

fn() -> Out is a valid type for unsized types Out, and it implements FnOnce<(), Output = Out>
10 participants