Stream: general

Topic: needs_drop


gnzlbg (Sep 13 2019 at 10:21, on Zulip):

Is there a needs_drop RFC somewhere ? I can't find it.

gnzlbg (Sep 13 2019 at 10:25, on Zulip):

@centril you said:

For types without a Drop impl it isn't correct as these types may have recursive drop glue due to fields having Drop impls (or at any level transitively).

But needs_drop returns true for such types, and we guarantee that

gnzlbg (Sep 13 2019 at 10:26, on Zulip):

As in, needs_drop returns true if a type _needs drop glue_, independently of whether the type itself is Drop or not

centril (Sep 13 2019 at 10:26, on Zulip):

we don't guarantee false :P

gnzlbg (Sep 13 2019 at 10:26, on Zulip):

no?

gnzlbg (Sep 13 2019 at 10:27, on Zulip):

For which type does that fail ?

centril (Sep 13 2019 at 10:27, on Zulip):

how can we guarantee true and false at the same time?

gnzlbg (Sep 13 2019 at 10:27, on Zulip):

(I can't find an RFC)

gnzlbg (Sep 13 2019 at 10:27, on Zulip):

I don't understand the question

gnzlbg (Sep 13 2019 at 10:27, on Zulip):

If a type does not need drop glue, we return false, if it does, we return true

gnzlbg (Sep 13 2019 at 10:28, on Zulip):

are there types that both need and don't need drop glue, or types for which that cannot be computed ?

gnzlbg (Sep 13 2019 at 10:29, on Zulip):

The nomicon specifically defines types that need drop glue as "needs drop" types, so I'd supposed that needs_drop would implement the nomicon semantics

gnzlbg (Sep 13 2019 at 10:30, on Zulip):

The docs of std::mem::needs_drop do indeed say that the answer doesn't need to be accurate:

This is purely an optimization hint, and may be implemented conservatively: it may return true for types that don't actually need to be dropped.

gnzlbg (Sep 13 2019 at 10:32, on Zulip):

This is the only place I can find with any discussion about this: https://github.com/rust-lang/rust/pull/41892

gnzlbg (Sep 13 2019 at 10:33, on Zulip):

@eddyb seems to suggest here that this is an implementation bug: https://github.com/rust-lang/rust/pull/41892#discussion_r116155381

gnzlbg (Sep 13 2019 at 10:34, on Zulip):

No idea if there is an open issue tracking that bug

centril (Sep 13 2019 at 10:41, on Zulip):

@gnzlbg we do not guarantee that a type with drop glue has needs_drop::<Type>() == false

gnzlbg (Sep 13 2019 at 10:41, on Zulip):

why

gnzlbg (Sep 13 2019 at 10:42, on Zulip):

wait, that's correct

centril (Sep 13 2019 at 10:42, on Zulip):

@gnzlbg I think you were mixing up true & false

gnzlbg (Sep 13 2019 at 10:42, on Zulip):

types with drop glue should always have needs_drop::<Type>() == true

centril (Sep 13 2019 at 10:42, on Zulip):

yes, correct

centril (Sep 13 2019 at 10:42, on Zulip):

which is what I was saying in the thing you quoted

gnzlbg (Sep 13 2019 at 10:43, on Zulip):

we don't guarantee that types _without_ drop glue have needs_drop::<Type>() == false

centril (Sep 13 2019 at 10:43, on Zulip):

also correct

gnzlbg (Sep 13 2019 at 10:43, on Zulip):

needs_drop can return true for them, and that isn't a correctness issue

gnzlbg (Sep 13 2019 at 10:43, on Zulip):

the question is why don't we guarantee that

gnzlbg (Sep 13 2019 at 10:43, on Zulip):

why don't we guarantee that for types without drop glue needs_drop always returns false ?

centril (Sep 13 2019 at 10:44, on Zulip):

well if you do that then you have guaranteed this as a matter of semver for all crates

centril (Sep 13 2019 at 10:44, on Zulip):

doing it for Copy is a more explicit commitment which already has semver implications

gnzlbg (Sep 13 2019 at 10:44, on Zulip):

sure, so are many other things

gnzlbg (Sep 13 2019 at 10:44, on Zulip):

AFAICT, we could have a NeedsDrop auto-trait, and then mem::needs_drop can be implemented using specialization:

auto trait NeedsDrop {}
impl<T> NeedsDrop for T where T: Drop {}
trait _ComputeNeedsDrop { default const VALUE: bool = false; }
default impl<T> _ComputeNeedsDrop for T {}
impl<T: NeedsDrop> _ComputeNeedsDrop for T { const VALUE: bool = true; }
pub fn needs_drop<T: _ComputeNeedsDrop>() -> bool { T::VALUE }
centril (Sep 13 2019 at 10:45, on Zulip):

It's not a question of "can", it's a question of "want".

gnzlbg (Sep 13 2019 at 10:45, on Zulip):

so where is the rationale that says that doing so is a bad idea

gnzlbg (Sep 13 2019 at 10:45, on Zulip):

the only rationale I can find is that given by @eddyb on that issue

gnzlbg (Sep 13 2019 at 10:45, on Zulip):

which says, we can't do this on the compiler two years ago because of associated types

gnzlbg (Sep 13 2019 at 10:46, on Zulip):

it doesn't say anything about it being a good or bad idea

gnzlbg (Sep 13 2019 at 10:46, on Zulip):

and i mean, the compiler has to be able to know precisely whether a type needs drop glue or not..

centril (Sep 13 2019 at 10:47, on Zulip):

(specialization isn't stable)

centril (Sep 13 2019 at 10:47, on Zulip):

it doesn't say anything about it being a good or bad idea

I'm saying that we should be careful with more auto traits and such semver commitments

centril (Sep 13 2019 at 10:48, on Zulip):

I do think it's probably a bad idea

centril (Sep 13 2019 at 10:48, on Zulip):

Copy is still quite a lot of types

eddyb (Sep 13 2019 at 14:05, on Zulip):

it's a bug because it's not computed by the trait system

eddyb (Sep 13 2019 at 14:05, on Zulip):

that's it

eddyb (Sep 13 2019 at 14:06, on Zulip):

that's all there is to it

eddyb (Sep 13 2019 at 14:06, on Zulip):

@pnkfelix might have more info

eddyb (Sep 13 2019 at 14:06, on Zulip):

@gnzlbg ah I see you mention specialization. I hope that doesn't work, I don't think I've heard anything about autotraits being sound wrt specialization

gnzlbg (Sep 13 2019 at 14:42, on Zulip):

@eddyb I don't specialize an auto trait, I just use them in bounds

gnzlbg (Sep 13 2019 at 14:42, on Zulip):

is that unsound?

eddyb (Sep 13 2019 at 14:42, on Zulip):

that might work

gnzlbg (Sep 13 2019 at 14:43, on Zulip):

@centril

(specialization isn't stable)

needs_drop is already a #[lang_item] - how we implement it internally doesn't really matter

eddyb (Sep 13 2019 at 14:43, on Zulip):

surprises me that you can do that, I thought you needed Copy to change the auto trait behavior

eddyb (Sep 13 2019 at 14:43, on Zulip):

wait you don't have Copy in there. so it's not the whole story

gnzlbg (Sep 13 2019 at 14:48, on Zulip):

@eddyb https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=411c333b1681a2893d187a847364c4bb

eddyb (Sep 13 2019 at 14:49, on Zulip):

yeah sure I think that's fine, the problem is that a non-Copy type wrapping a Copy type, needs to be !NeedsDrop

eddyb (Sep 13 2019 at 14:49, on Zulip):

so like Cell<T> where T: Copy

eddyb (Sep 13 2019 at 14:50, on Zulip):

your version would work if you knew the type fully, I guess?

gnzlbg (Sep 13 2019 at 14:50, on Zulip):

one can only call needs_drop will a full type

eddyb (Sep 13 2019 at 14:51, on Zulip):

well, yes, but what is being run on the compiler doesn't need to be fully concrete

eddyb (Sep 13 2019 at 14:51, on Zulip):

it's how we avoid generating drops for locals in MIR

eddyb (Sep 13 2019 at 14:51, on Zulip):

having two computations seems risky

gnzlbg (Sep 13 2019 at 14:52, on Zulip):

Ah gotcha

gnzlbg (Sep 13 2019 at 14:53, on Zulip):

Copy is kind of Copy: !NeedsDrop

eddyb (Sep 13 2019 at 14:53, on Zulip):

also, pretty sure miri can evaluate and constant-fold needs_drop already (cc @oli)

gnzlbg (Sep 13 2019 at 14:53, on Zulip):

yes needs_drop is const fn

eddyb (Sep 13 2019 at 14:53, on Zulip):

even when the type is generic

eddyb (Sep 13 2019 at 14:53, on Zulip):

actually I can test this

gnzlbg (Sep 13 2019 at 14:54, on Zulip):

ah wow

gnzlbg (Sep 13 2019 at 14:54, on Zulip):

in all cases ?

gnzlbg (Sep 13 2019 at 14:54, on Zulip):

or only if the type is copy ?

eddyb (Sep 13 2019 at 14:55, on Zulip):

oh wait maybe I'm wrong

gnzlbg (Sep 13 2019 at 14:55, on Zulip):

The needs_drop in

fn foo<T: Copy>() -> bool { needs_drop::<T>() }

can always be folded to false.

gnzlbg (Sep 13 2019 at 14:55, on Zulip):

but without the T: Copy bound I don't think one can do anything

eddyb (Sep 13 2019 at 14:55, on Zulip):

it certainly could but it's not obvious that the answer is only guaranteed if it's false

eddyb (Sep 13 2019 at 14:56, on Zulip):

if it's true the real answer might be false. so we're missing an explicit "unknowable" result

eddyb (Sep 13 2019 at 14:56, on Zulip):

the trait system has a way to represent "not sure"

eddyb (Sep 13 2019 at 14:56, on Zulip):

so does layout_of (Err(LayoutError::Unknown(_)))

gnzlbg (Sep 13 2019 at 14:56, on Zulip):

well sure

gnzlbg (Sep 13 2019 at 14:57, on Zulip):

if we had a NeedsDrop trait we could constant fold it to true (T: NeedsDrop) or false (T: !NeedsDrop) or maybe (T - no bounds)

gnzlbg (Sep 13 2019 at 14:58, on Zulip):

Maybe is just an unknown that is resolved later if the function is ever monomorphized

gnzlbg (Sep 13 2019 at 14:59, on Zulip):

Ah i think I see the problem now

gnzlbg (Sep 13 2019 at 15:00, on Zulip):

How does this work for Send and Sync ?

nagisa (Sep 13 2019 at 16:25, on Zulip):

@eddyb can we reliably compute needs_drop for unsized trait objects?

nagisa (Sep 13 2019 at 16:25, on Zulip):

(to me it soulds like it will have to return true regardless of the concrete type behind the object)

rkruppe (Sep 13 2019 at 16:33, on Zulip):

Yes but that's not really an inaccuracy. The trait object does have drop glue (stored in the vtable), it just happens to be trivial for some values of that type. Not entirely unlike how Option<T> needs_drop if T does but dropping None does nothing.

RalfJ (Sep 15 2019 at 12:50, on Zulip):

we probably need a new "drop-like" trait for const anyway... something to attach const to to say "dropping this type is possible in const context"

RalfJ (Sep 15 2019 at 12:50, on Zulip):

I wanted to repurpose Drop for this but most likely it is way too late for this... we should not have stabilized Drop trait bounds :/

gnzlbg (Sep 15 2019 at 19:12, on Zulip):

why not?

gnzlbg (Sep 15 2019 at 19:14, on Zulip):

We could say that, if a field of an aggregate implements Drop, and the aggregate has no user-provided Drop impl, the compiler auto-generates a Drop impl for you

gnzlbg (Sep 15 2019 at 19:14, on Zulip):

That is, a type with a field that is Drop is always Drop

gnzlbg (Sep 15 2019 at 19:14, on Zulip):

If the Drop impl for the field is const, the Drop impl for the aggregate might be able to be const as well

gnzlbg (Sep 15 2019 at 19:16, on Zulip):

This would mean that needs_drop<T> would just return whether a type is Drop

gnzlbg (Sep 15 2019 at 19:17, on Zulip):

(true if it is, false if it isn't, and in generic code a "maybe" until the answer is known)

RalfJ (Sep 15 2019 at 20:51, on Zulip):

We could say that, if a field of an aggregate implements Drop, and the aggregate has no user-provided Drop impl, the compiler auto-generates a Drop impl for you

that's not backwards-compatible: https://github.com/rust-lang/rfcs/pull/2632#issuecomment-528461395

gnzlbg (Sep 15 2019 at 21:47, on Zulip):

that's bad

RalfJ (Sep 16 2019 at 09:45, on Zulip):

yes :(

Last update: Nov 22 2019 at 00:25UTC