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

#[allow_internal_unstable] does not allow unstable library features when applied on functions #69399

Closed
kennytm opened this issue Feb 23, 2020 · 15 comments · Fixed by #78208
Closed
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-stability Area: `#[stable]`, `#[unstable]` etc. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@kennytm
Copy link
Member

kennytm commented Feb 23, 2020

The #[allow_internal_unstable] attribute can only enable compiler features. Library features cannot be enabled.

Examples:

#![feature(allow_internal_unstable)]
// #![feature(wrapping_next_power_of_two, const_transmute)]

#[allow_internal_unstable(wrapping_next_power_of_two)]
fn g(a: u64) -> u64 {
    a.wrapping_next_power_of_two()
}

#[allow_internal_unstable(const_transmute)]
const fn h(a: u64) -> i64 {
    unsafe { std::mem::transmute(a) }
}
  • Expected: can be built without errors.
  • Actual: still complains about missing #![feature]s.

Rustc version = 1.43.0-nightly (2020-02-22 436494b8f8008b600d64)

@kennytm kennytm added A-stability Area: `#[stable]`, `#[unstable]` etc. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Feb 23, 2020
@RalfJung RalfJung added the A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. label Feb 23, 2020
@eddyb
Copy link
Member

eddyb commented Feb 24, 2020

allow_internal_unstable is a macro attribute, the only bug here is that it doesn't complain when you put it on a non-macro.

@kennytm kennytm added the A-attributes Area: Attributes (`#[…]`, `#![…]`) label Feb 24, 2020
@ecstatic-morse
Copy link
Contributor

@eddyb This was changed as part of #63770.

@eddyb
Copy link
Member

eddyb commented Feb 25, 2020

Ugh, that's an unprincipled hack, and the attribute is still not checked correctly. I had this example where it doesn't do anything without errors.

I can now see how it's used in libcore, but it should be named #[rustc_allow_const_fn_unstable(...)] or something, and be properly checked.

@eddyb
Copy link
Member

eddyb commented Feb 25, 2020

Also, do we need that anymore? Given that we're starting to add more and more const fns.

@RalfJung
Copy link
Member

Also, do we need that anymore? Given that we're starting to add more and more const fns.

The point of this is that we don't want to stabilize const fn that use unstable features (to avoid de-facto stabilizing unstable features of the const-eval engine). I think that is still very much needed.

@kennytm
Copy link
Member Author

kennytm commented Feb 25, 2020

cc @Centril @oli-obk for use of #[allow_internal_unstable] around const fn. https://github.com/rust-lang/rustc-guide/blob/master/src/stability.md#allow_internal_unstable.

@ecstatic-morse
Copy link
Contributor

The fix for this is described in #69373 (comment).

@kennytm kennytm changed the title #[allow_internal_unstable] does not allow unstable library features #[allow_internal_unstable] does not allow unstable library features when applied on functions Feb 27, 2020
@varkor varkor added the E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. label Sep 28, 2020
@liketechnik
Copy link
Contributor

liketechnik commented Oct 19, 2020

I would like to tackle this issue, but I'm not 100% sure how to go forward. If I understood correctly, I would just need to follow the instructions in the above fix.
This would mean I'd add the described check at the described line, right?

@oli-obk
Copy link
Contributor

oli-obk commented Oct 20, 2020

I believe that should indeed suffice to fix the issue, but I may have overlooked larger things

@liketechnik
Copy link
Contributor

I don't think I'll be able to fix this issue on my own, I'm afraid.

I'm not familiar enough with the internal workings and the fix linked above cannot really be used like that anymore, if I understood the code correctly.

@oli-obk
Copy link
Contributor

oli-obk commented Oct 20, 2020

if let Some(gate) = is_unstable_const_fn(tcx, callee) {
if self.span.allows_unstable(gate) {
return;
}
// Calling an unstable function *always* requires that the corresponding gate
// be enabled, even if the function has `#[allow_internal_unstable(the_gate)]`.
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
}
// If this crate is not using stability attributes, or the caller is not claiming to be a
// stable `const fn`, that is all that is required.
if !self.ccx.is_const_stable_const_fn() {
return;
}
// Otherwise, we are something const-stable calling a const-unstable fn.
if super::allow_internal_unstable(tcx, caller, gate) {
return;
}
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
}
is what handles this now.

So I guess we'll need to just remove

// Calling an unstable function *always* requires that the corresponding gate
// be enabled, even if the function has `#[allow_internal_unstable(the_gate)]`.
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
}

@liketechnik
Copy link
Contributor

liketechnik commented Oct 20, 2020

I applied that change locally and it didn't fix the issue.

I think the error lies elsewhere, because compiling the above code with -Z treat-err-as-bug=1 and RUST_BACKTRACE=full creates a backtrace where the error seems to be created in rustc_middle::middle::stability::check_optional_stability (here's a gist with the code and the backtrace).

Edit:

pub fn check_optional_stability(
self,
def_id: DefId,
id: Option<HirId>,
span: Span,
unmarked: impl FnOnce(Span, DefId) -> (),
) {
let soft_handler = |lint, span, msg: &_| {
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
lint.build(msg).emit()
})
};
match self.eval_stability(def_id, id, span) {
EvalResult::Allow => {}
EvalResult::Deny { feature, reason, issue, is_soft } => {
report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler)
}
EvalResult::Unmarked => unmarked(span, def_id),
}
}

@oli-obk oli-obk removed the E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. label Oct 20, 2020
@oli-obk
Copy link
Contributor

oli-obk commented Oct 20, 2020

oh.. oof. This means it's part of

pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> EvalResult {
which... we don't really want to touch. That would allow us to allow allow arbitrary library features. I now realize that this issue was created for non-const-fn, I always thought this was about const fn and relevant features.

Yea, I don't think we should change anything here and keep requiring the feature on the entire crate.

So the only change left from this issue that I think we should address is to rename the attribute on functions to rustc_allow_const_fn_unstable and not have the same name as the attribute for macros.

@liketechnik
Copy link
Contributor

My current understanding of what needs to be done to address the renaming:

(Note: If somebody more experienced than me should rather deal with this, please tell me. I'm really enjoying working on this so far, but I also understand if I'm too much of a burden with that many (simple) questions...)

@oli-obk
Copy link
Contributor

oli-obk commented Oct 21, 2020

(Note: If somebody more experienced than me should rather deal with this, please tell me. I'm really enjoying working on this so far, but I also understand if I'm too much of a burden with that many (simple) questions...)

From my end it looks like you are approaching this in a well-organized manner, and not at all a burden!

* Include feature names from both (either) `allow_internal_unstable` and `rustc_allow_const_fn_unstable`

I would make that function private and take a Symbol argument that gets checked and reported instead. Then you can add public wrappers for both allow_internal_unstable and rustc_allow_const_fn_unstable that fill in that new argument with the appropriate symbol. This way we don't mix the two functions while still deduplicating their implementation.

  • Make sure that allow_internal_unstable can only be applied to macros (which would happen in compiler/rustc_passes/src/check_attr.rs?)

  • Make sure that rustc_allow_const_fn_unstable can only be applied to functions

Yes, both of these can be checked similarly to
https://github.com/rust-lang/rust/blob/master/compiler/rustc_passes/src/check_attr.rs#L86-L87

liketechnik added a commit to liketechnik/rust that referenced this issue Oct 21, 2020
allow_internal_unstable is currently used
to side-step feature gate and stability checks.
While it was originally only meant to be used
only on macros, its use was expanded to
const functions.

This commit prepares stricter checks for the usage of allow_internal_unstable (only on macros)
and introduces the rustc_allow_const_fn_unstable attribute for usage on functions.

See rust-lang#69399
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-stability Area: `#[stable]`, `#[unstable]` etc. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
7 participants