-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
a fn pointer doesn't implement Fn
/FnMut
/FnOnce
if its return type isn't sized
#100096
a fn pointer doesn't implement Fn
/FnMut
/FnOnce
if its return type isn't sized
#100096
Conversation
LL | foo::<fn() -> str, _>(None, ()); | ||
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | ||
| | ||
= help: within `fn() -> str`, the trait `Sized` is not implemented for `str` |
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.
Random thought: I wonder if we could get the span for the str
and use it for a span_help
here, opportunistically (because for things like type aliases in a foreign crate, we might not be able to recover them).
note: required by a bound in `foo` | ||
--> $DIR/unsized-ret.rs:4:11 | ||
| | ||
LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) { | ||
| ^^^^^ required by this bound in `foo` |
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.
The implicit Sized
requirements should have their own obligation cause so that we could mention why it was required (as the code doesn't mention it, this would be mystifying the first time you encounter it).
Could we add this test to this PR as well? |
I'm ok with landing this instead of my PR. I'll let the types team decide whether this is the right approach (although it looks reasonable to me). |
i guess this really should be r? @nikomatsakis since he reviewed the last one |
Discussed in T-compiler triage meeting. Nominating for T-types to handle forward movement. @rustbot label: I-types-nominated |
r? @jackh726 |
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.
r=me with testing for fn ptrs with bound vars
// The binder on the Fn obligation is "less" important than the one on | ||
// the signature, as evidenced by how we treat it during projection. | ||
// The safe thing to do here is to liberate it, though, which should | ||
// have no worse effect than skipping the binder here. | ||
let liberated_fn_ty = self.infcx.replace_bound_vars_with_placeholders(obligation.self_ty()); | ||
let output_ty = self | ||
.infcx | ||
.replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output()); | ||
let output_ty = normalize_with_depth_to( | ||
self, | ||
obligation.param_env, | ||
cause.clone(), | ||
obligation.recursion_depth, | ||
output_ty, | ||
&mut nested, | ||
); | ||
let tr = ty::Binder::dummy(ty::TraitRef::new( | ||
self.tcx().require_lang_item(LangItem::Sized, None), | ||
self.tcx().mk_substs_trait(output_ty, &[]), | ||
)); |
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.
Just for completeness, can you update the test to include some fn ptrs with bound vars?
98b5f4e
to
29ace82
Compare
29ace82
to
3b573c9
Compare
Added some check-pass tests with higher-ranked lifetimes, and a failure to the |
| | | ||
| required by a bound introduced by this call | ||
| | ||
= help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` |
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.
Interestingly this mentions for<'a> Sized
, but I think that's because we print placeholder regions as if they were in binders.
@bors r+ IIUC, this doesn't change stable behavior, only fixes unstable behavior. |
☀️ Test successful - checks-actions |
Finished benchmarking commit (1de00d1): comparison URL. Overall result: ❌ regressions - ACTION NEEDEDNext Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Footnotes |
Oh my goodness, I will look into those perf regressions ASAP. |
FWIW, the regressions are on a single secondary benchmark, and while they're real this is a soundness fix so if we can't mitigate them it makes sense to move forward I think. (That said the change here seems like it could definitely affect other code, wg-grammar probably just has more fn ptrs or something). We do see a similar-ish regression in some of the bootstrap benchmarks, though to a lesser extent, so it's not entirely limited I guess. |
So I haven't had time to fix this, nor do I think this is an easily mitigated regression. I'm not sure if @rust-lang/wg-prioritization deems this a bad enough perf regression that we should roll it back. This is technically an issue that is only triggered with |
I don't think we should revert this PR, the regression is limited to only one secondary benchmark and while it may make sense to look into how we can reduce that regression there, it doesn't feel bad enough to warrant a complete revert of this soundness fix |
…safety, r=lcnr Check that built-in callable types validate their output type is `Sized` (in new solver) Working on parity with old solver. Putting this up for consideration, it's not *really* needed or anything just yet. Maybe it's better to approach this from another direction (like always checking the item bounds when calling `consider_assumption`? we may need that for coinduction to be sound though?) This basically implements rust-lang#100096 for the new solver.
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 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 thatstr: !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.