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

Stabilization error E0658 is trivially bypassed #90912

Closed
Diggsey opened this issue Nov 14, 2021 · 6 comments
Closed

Stabilization error E0658 is trivially bypassed #90912

Diggsey opened this issue Nov 14, 2021 · 6 comments
Labels
A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. C-bug Category: This is a bug.

Comments

@Diggsey
Copy link
Contributor

Diggsey commented Nov 14, 2021

trait IsMagic {}

const fn foo<T>() where T: IsMagic {} // Does not compile
const fn bar<T>() where (T,): IsMagic {} // Compiles
error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable

I already have code unintentionally relying on this, so please don't break it 😅

The first case should probably just be stabilized, since you can already rely on it.

Also, the stabilization issue the error message references doesn't actually mention this error, so it's not clear what work is left to do on it.

@Diggsey Diggsey added the C-bug Category: This is a bug. label Nov 14, 2021
@Diggsey Diggsey changed the title Stabilization error E0659 is trivially bypassed Stabilization error E0658 is trivially bypassed Nov 14, 2021
@workingjubilee workingjubilee added the A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. label Nov 14, 2021
@RalfJung
Copy link
Member

Cc @rust-lang/wg-const-eval more holes in our guard against trait bounds...

@fee1-dead
Copy link
Member

I'm inclined to just remove the const_fn_trait_bound feature altogether. It doesn't error for Newtype<T> and not even (T,). IMO it doesn't have anything meaningful use for how we should design const_trait_impl, and we should just use something like ~const.

@oli-obk
Copy link
Contributor

oli-obk commented Dec 24, 2021

We got "preliminary lang team approval" to just allow trait bounds, trait objects and fn ptrs in const fn, but not allow using them in any const way beyond accessing associated consts. So no method calls or anything. I think the right way forward would be to split the feature gates, but tbh, I think it would be totally fine to just open a PR that stabilizes trait bounds, trait objects and fn ptrs and then FCP that PR

@fee1-dead
Copy link
Member

fee1-dead commented Dec 24, 2021

I would rather use the term "remove" than to "stabilize" here, but could it be confusing to users on whether the restriction was lifted or remained an error just like without the feature gate enabled?

@oli-obk
Copy link
Contributor

oli-obk commented Dec 24, 2021

Yea, the terminology is weird. How about "removing an unnecessary and circumventable feature gate", wordy but doesn't suggest we get const trait bounds

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 7, 2022
…r=wesleywiser

Stabilize const_fn_fn_ptr_basics, const_fn_trait_bound, and const_impl_trait

# Stabilization Report

This PR serves as a request for stabilization for three const evaluation features:

1. `const_fn_fn_ptr_basics`
2. `const_fn_trait_bound`
3. `const_impl_trait`

These are being stabilized together because they are relatively minor and related updates to existing functionality.

## `const_fn_fn_ptr_basics`

Allows creating, passing, and casting function pointers in a `const fn`.

The following is an example of what is now allowed:

```rust
const fn get_function() -> fn() {
    fn foo() {
        println!("Hello, World!");
    }

    foo
}
```

Casts between function pointer types are allowed, as well as transmuting from integers:

```rust
const fn get_function() -> fn() {
    unsafe {
        std::mem::transmute(0x1234usize)
    }
}
```

However, casting from a function pointer to an integer is not allowed:

```rust
const fn fn_to_usize(f: fn()) -> usize {
    f as usize  //~ pointers cannot be cast to integers during const eval
}
```

Calling function pointers is also not allowed.

```rust
const fn call_fn_ptr(f: fn()) {
    f() //~ function pointers are not allowed in const fn
}
```

### Test Coverage

The following tests include code that exercises this feature:

- `src/test/ui/consts/issue-37550.rs`
- `src/test/ui/consts/issue-46553.rs`
- `src/test/ui/consts/issue-56164.rs`
- `src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs`
- `src/test/ui/consts/min_const_fn/cast_fn.rs`
- `src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs`

## `const_fn_trait_bound`

Allows trait bounds in `const fn`. Additionally, this feature allows creating and passing `dyn Trait` objects.

Examples such as the following are allowed by this feature:

```rust
const fn do_thing<T: Foo>(_x: &T) {
    // ...
}
```

Previously only `Sized` was allowed as a trait bound.

There is no way to call methods from the trait because trait methods cannot currently be marked as const. Allowing trait bounds in const functions does allow the const function to use the trait's associated types and constants.

This feature also allowes `dyn Trait` types. These work equivalently to non-const code. Similar to other pointers in const code, the value of a `dyn Trait` pointer cannot be observed.

Note that due to rust-lang#90912, it was already possible to do the example above as follows:

```rust
const fn do_thing<T>(_x: &T) where (T,): Foo {
    // ...
}
```

### Test Coverage

The following tests include code that exercises `const_fn_trait_bound`:

- `src/test/ui/consts/const-fn.rs`
- `src/test/ui/consts/issue-88071.rs`
- `src/test/ui/consts/min_const_fn/min_const_fn.rs`
- `src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs`
- `src/test/ui/nll/issue-55825-const-fn.rs`
- Many of the tests in `src/test/ui/rfc-2632-const-trait-impl/` also exercise this feature.

## `const_impl_trait`

Allows argument and return position `impl Trait` in a `const fn`, such as in the following example:

```rust
const fn do_thing(x: impl Foo) -> impl Foo {
    x
}
```

Similar to generic parameters and function pointers, this allows the creation of such opaque types, but not doing anything with them beyond accessing associated types and constants.

### Test Coverage

The following tests exercise this feature:

- `src/test/ui/type-alias-impl-trait/issue-53096.rs`
- `src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs`

## Documentation

These features are documented along with the other const evaluation features in the Rust Reference at https://doc.rust-lang.org/stable/reference/const_eval.html.

There is a PR that updates this documentation to reflect the capabilities enabled by these features at rust-lang/reference#1166.

Tracking issues: rust-lang#57563, rust-lang#63997, rust-lang#93706
@jplatte
Copy link
Contributor

jplatte commented Mar 22, 2022

#93827 removed this stabilization error, so maybe this could be closed? However, I'd really prefer if we could take a step back, revert that stabilization and consider an edition-based flow for getting ?const instead of ~const afterall... #93706 (comment)

@oli-obk oli-obk closed this as completed Mar 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

6 participants