Change:
is a valid type, even for unsized types , and it implements , even though is not . So far, I haven’t found a way to turn this into unsoundness without using . () <details<summarycode after <coderustfmt</code</summary</detailsErrors: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
The labeling is a bit tricky on this one. This is when using . (And you can, of course, also generate ICE’s in a multitude of ways.) On the other hand, the fact that there is a type implementing with unsized type , so this issue is not really only about the case. I mean, even though trait object types don’t seem to care too much about behaving soundly in other cases (, ).
modify labels: A-associated-items, A-typesystem, T-compiler
I had trouble seeing the unsoundness, so here's another example: is false, so should never be executed: yet it is anyway:
And note that you can ('s code, I just wanted to highlight it): This code compiles, but it shouldn't.
Assigning .20-.3E.20Out.60.20is.20a.20valid.20type.20for.20unsized.20types.20.60Out.E2.80.A6).
Another way to observe unsoundness: () This code compiles, but it shouldn't because is not .
That code used to give a compiler error: but regressed in 1.49 such that it is no longer erroring.
I suspect this might be more fallout from , but we'll need a bisection to be sure.
Yep, it's alright: searched nightlies: from nightly-2020-10-01 to nightly-2020-12-31 regressed nightly: nightly-2020-10-07 searched commits: from to regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.0</summaryHost triple: x86_64-apple-darwin Reproduce with: </details
I wonder if the issue is that, quoting from : But the compiler is the one that implements for types? Maybe that's a different thing though.
I’m not 100% sure what you mean by “observing the unsoundness”. Something like doesn’t feel necessarily unsound in and by itself. As you quoted, which sounds pretty reasonable to me. Similarly my reproduction on stable only observes that has an illegal implementation, but I wasn’t able to achieve much “actually unsound behavior” with this implementation without the ability to name the type, hence using . But just the inability to name (probably) preventing bad things for now doesn’t feel right. <hrAs to ways this should_ be fixed: Either disallow all types with in general, or at least change the compiler so that they don’t implement .
In particular, I don’t think that is appropriate. I can get ICE’s all the way since mid-2017 (bisect-rustc doesn’t seem to like older dates) with code like this Similarly, reading static memory and segfaulting can be archieved all the way back to e.g. (go much earlier and complains about missing ) with code such as <details<summary<iCLICK TO EXPAND</i</summary</detailsI would believe that the bug is not a regression but just always has been there. modify labels: -regression-from-stable-to-stable
label +I-nominated
Discussed very briefly at . The P-high prioritization seems okay to me, as long as we cannot identify an exploit requiring no feature flags. But nonetheless, this needs an owner. So, leaving I-nominated tag so that we'll revisit next week. Unless someone takes ownership of this issue in the meantime.
: I think I agree with the above assertion. I'm moving this from T-compiler to T-lang to get confirmation that such a change makes sense. (It might need a warning cycle, of course.) label -T-compiler +T-lang +I-nominated
(also, in T-compiler discussion, volunteered to take ownership of implementing the aforementioned restriction after T-lang confirms it should be so.)
Waiting on before further T-lang discussion
Starting a poll to check lang-team consensus: poll T-lang Should we prohibit types like if is not ?
Team member has asked teams: T-lang, for consensus on: [x] [x] [x] [x] [x]
Clarification: this does not prevent us from potentially improving support for unsized values in the future, it just prevents such function types from existing until we do.
ping Do you still have the bandwidth to implement this? Looks like we have consensus.
(we may want to warning-cycle the prohibition, to be clear)
I do. I'll cook up a PR.
published Sorry it took me so long, I had multiple false starts. It might need some changes to be good enough for merging, but that PR enforces for all s except and projections. As follow up work, I would like to change the spans to be tighter/easier to understand, but for now this is good enough:
Is there any way the exceptions for or projections could be used to generate unsoundness in the same style as the PoCs in this thread?
I could envision that being the case, but haven't come up with a way to trigger it.
Niko an .
fixed by which removes the builtin impl for function pointers with unsized return values. marking as needs test
Feel free to take to close this.
claim For adding the test.

Discussion:
<ins> #![feature(unboxed_closures)] trait A { fn a() where Self: Sized; } mod a { use crate::A; pub fn foo<F: FnOnce<()>>() where F::Output: A { F::Output::a() } pub fn bar<F: FnOnce() -> R, R: ?Sized>() {} pub fn baz<F: FnOnce<()>>() where F::Output: A, F::Output: Sized { F::Output::a() } } mod b { use crate::A; pub fn foo<F: Fn<()>>() where F::Output: A { F::Output::a() } pub fn bar<F: Fn() -> R, R: ?Sized>() {} pub fn baz<F: Fn<()>>() where F::Output: A, F::Output: Sized { F::Output::a() } } mod c { use crate::A; pub fn foo<F: FnMut<()>>() where F::Output: A { F::Output::a() } pub fn bar<F: FnMut() -> R, R: ?Sized>() {} pub fn baz<F: FnMut<()>>() where F::Output: A, F::Output: Sized { F::Output::a() } } impl A for Box<dyn A> { fn a() {} } fn main() { a::foo::<fn() -> dyn A>();         //~ ERROR E0277 a::bar::<fn() -> dyn A, _>();      //~ ERROR E0277 a::baz::<fn() -> dyn A>();         //~ ERROR E0277 a::foo::<fn() -> Box<dyn A>>();    //  ok a::bar::<fn() -> Box<dyn A>, _>(); //  ok a::baz::<fn() -> Box<dyn A>>();    //  ok b::foo::<fn() -> dyn A>();         //~ ERROR E0277 b::bar::<fn() -> dyn A, _>();      //~ ERROR E0277 b::baz::<fn() -> dyn A>();         //~ ERROR E0277 b::foo::<fn() -> Box<dyn A>>();    //  ok b::bar::<fn() -> Box<dyn A>, _>(); //  ok b::baz::<fn() -> Box<dyn A>>();    //  ok c::foo::<fn() -> dyn A>();         //~ ERROR E0277 c::bar::<fn() -> dyn A, _>();      //~ ERROR E0277 c::baz::<fn() -> dyn A>();         //~ ERROR E0277 c::foo::<fn() -> Box<dyn A>>();    //  ok c::bar::<fn() -> Box<dyn A>, _>(); //  ok c::baz::<fn() -> Box<dyn A>>();    //  ok } </ins>

<ins> error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:54:5 | LL |     a::foo::<fn() -> dyn A>(); |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:55:14 | LL |     a::bar::<fn() -> dyn A, _>(); |              ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `a::bar` --> $DIR/closure-return-type-must-be-sized.rs:14:19 | LL |     pub fn bar<F: FnOnce() -> R, R: ?Sized>() {} |                   ^^^^^^^^^^^^^ required by this bound in `a::bar` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:56:5 | LL |     a::baz::<fn() -> dyn A>(); |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:61:5 | LL |     b::foo::<fn() -> dyn A>(); |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:62:14 | LL |     b::bar::<fn() -> dyn A, _>(); |              ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `b::bar` --> $DIR/closure-return-type-must-be-sized.rs:28:19 | LL |     pub fn bar<F: Fn() -> R, R: ?Sized>() {} |                   ^^^^^^^^^ required by this bound in `b::bar` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:63:5 | LL |     b::baz::<fn() -> dyn A>(); |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:68:5 | LL |     c::foo::<fn() -> dyn A>(); |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:69:14 | LL |     c::bar::<fn() -> dyn A, _>(); |              ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `c::bar` --> $DIR/closure-return-type-must-be-sized.rs:42:19 | LL |     pub fn bar<F: FnMut() -> R, R: ?Sized>() {} |                   ^^^^^^^^^^^^ required by this bound in `c::bar` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:70:5 | LL |     c::baz::<fn() -> dyn A>(); |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0277`. </ins>