Skip to content

Consider whether the use of static muts in constant expressions should not require unsafe blocks #9852

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

Closed
bstrie opened this issue Oct 14, 2013 · 11 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints P-low Low priority

Comments

@bstrie
Copy link
Contributor

bstrie commented Oct 14, 2013

Take a look at this program, which fails to compile:

struct Foo { a: int }

static mut x: int = 3;
static mut f: Foo = Foo { a: x };  // error: use of mutable static requires unsafe function or block

fn main() {}

The failure is obviously because the rule is that static mut items have to be wrapped in an unsafe block to be used, which I presume would look like the following:

struct Foo { a: int }

static mut x: int = 3;
static mut f: Foo = unsafe { Foo { a: x } };  // error: constant contains unimplemented expression type

fn main() {}

...but as you can see, using unsafe blocks in constant expressions isn't implemented yet.

The question I want to raise here is whether the unsafe block should be required at all. Currently, constant expressions cannot mutate anything, so x might as well be just static in this case. But if we ever expand our constant expressions in the future to include mutation, allowing people to omit them here might present a backwards-compat hazard.

@bstrie
Copy link
Contributor Author

bstrie commented Oct 14, 2013

Nominating for P-backcompat-lang.

@glaebhoerl
Copy link
Contributor

I think both C++ and D agree (for good reason) that anything evaluated at compile time has to be a pure function, i.e. definitely no mutation of global variables. So I don't think this would be much of a hazard.

@pnkfelix
Copy link
Member

I'm not sure I follow what is gained by making a special case here for constant expressions.

Why not write the code so that the constant expression refers to a non-mut static (and then initialize the mut static from the newly introduced non-mut static binding)?

@bstrie
Copy link
Contributor Author

bstrie commented Oct 14, 2013

Indeed there exists a workaround, but the question here is concerned with whether it's worth an exception to the rule in order to keep from diluting the utility of the unsafe keyword by requiring it in cases that can never ever be unsafe, unless we happen to one day add both mutation and multithreading to constant expressions (which seems unlikely).

@bstrie
Copy link
Contributor Author

bstrie commented Oct 14, 2013

However, if we decide that the workaround is sufficient for all cases, then perhaps we'd be able to get away with just resolving to never implement unsafe for constant expressions (which doesn't have an intuitive meaning to me in the first place).

If that's the case, then we'd have to modify the error report to no longer suggest an unsafe block in this scenario, and also not report unsafe-in-constants as merely "unimplemented".

@pnkfelix
Copy link
Member

My naive intuition is that one should be able to cut-and-paste a constant expression into a more general context (i.e. a spot in the code that allows non-constant expressions), without injecting new errors from the compiler.

If we make a special case here where you could refer to static muts in constant expressions, then the naive intuition above would not hold.

(It could well be that I'm overlooking some other reason why this intuition does not hold. I just wanted to explain why I am concerned about putting in a special case for const expressions here. I would be perfectly comfortable if the error message were updated to say "you cannot reference a static mut from a constant expression, which I think is part of what bstrie is suggesting in the preceding comment.)

@LeoTestard
Copy link
Contributor

And what if the static mut expression I want to refer to looks like :

static mut array: [SomeStruct, ..SIZE] = [SomeStruct { ... }, ..SIZE];

If I declare such a thing using the workaround mentioned above, I would get something like :

static array: [SomeStruct, ..SIZE] = [SomeStruct { ... }, ..SIZE];
static mut a: [SomeStruct, ..SIZE] = array;

a and array obviously don't refer to the same array. Therefore, if I have a static constant-expression that refer to the first array, it won't be affected by modifications made to its mutable copy.

This was more or less what wanted to achieve when I asked bstrie on IRC (which led to this bug report)
But I'm quite a beginner in Rust and maybe I'm missing some important point...

EDIT: well, in fact, I'm realizing there's nothing specific with arrays here. There'is the same problem with any type providen that some static expression refers to another by pointer. Should'nt it be possible for the pointed value to be declared as mutable and modified, so that modifications will affect other static expressions pointing to it ?

@huonw
Copy link
Member

huonw commented Oct 14, 2013

What about, say, (assuming it is valid)

static mut FOO: int = 0;
static PTR: &'static mut int = &mut FOO;

I think this use should definitely be unsafe, otherwise one can write a segfaulting/memory-unsafe program with no unsafe blocks.

Personally I agree with @pnkfelix: statics shouldn't special-case the unsafe rules.

@catamorphism
Copy link
Contributor

We're not going to change this, but we will improve the error message. Not a 1.0 blocker

@erickt
Copy link
Contributor

erickt commented Sep 22, 2014

This change would require a RFC to make this semantic change, so I'm closing this issue. I've filed a separate bug report #17450 to track enabling the ability to assign one static mut to another static mut.

@rust-highfive
Copy link
Contributor

This issue has been moved to the RFCs repo: rust-lang/rfcs#298

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints P-low Low priority
Projects
None yet
Development

No branches or pull requests

8 participants