Skip to content

Commit ed56c58

Browse files
committed
Structured suggestion for "missing feature in unstable fn call"
When encountering a call corresponding to an item marked as unstable behind a feature flag, provide a structured suggestion pointing at where in the crate the `#![feature(..)]` needs to be written. ``` error: `foobar` is not yet stable as a const fn --> $DIR/const-stability-attribute-implies-no-feature.rs:12:5 | LL | foobar(); | ^^^^^^^^ | help: add `#![feature(const_foobar)]` to the crate attributes to enable | LL + #![feature(const_foobar)] | ``` Fix #81370.
1 parent 3c1e750 commit ed56c58

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

compiler/rustc_const_eval/src/check_consts/check.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -891,16 +891,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
891891
// regular stability.
892892
feature == sym::rustc_private
893893
&& issue == NonZero::new(27812)
894-
&& self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
894+
&& tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
895895
};
896896
// Even if the feature is enabled, we still need check_op to double-check
897897
// this if the callee is not safe to expose on stable.
898898
if !feature_enabled || !callee_safe_to_expose_on_stable {
899+
let suggestion_span =
900+
tcx.hir_crate_items(()).definitions().next().and_then(|id| {
901+
tcx.crate_level_attribute_injection_span(
902+
tcx.local_def_id_to_hir_id(id),
903+
)
904+
});
899905
self.check_op(ops::FnCallUnstable {
900906
def_id: callee,
901907
feature,
902908
feature_enabled,
903909
safe_to_expose_on_stable: callee_safe_to_expose_on_stable,
910+
suggestion_span,
904911
});
905912
}
906913
}

compiler/rustc_const_eval/src/check_consts/ops.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
33
use hir::{ConstContext, LangItem};
4-
use rustc_errors::Diag;
54
use rustc_errors::codes::*;
5+
use rustc_errors::{Applicability, Diag};
66
use rustc_hir as hir;
77
use rustc_hir::def_id::DefId;
88
use rustc_infer::infer::TyCtxtInferExt;
@@ -335,6 +335,7 @@ pub(crate) struct FnCallUnstable {
335335
/// expose on stable.
336336
pub feature_enabled: bool,
337337
pub safe_to_expose_on_stable: bool,
338+
pub suggestion_span: Option<Span>,
338339
}
339340

340341
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
@@ -354,8 +355,18 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
354355
def_path: ccx.tcx.def_path_str(self.def_id),
355356
});
356357
// FIXME: make this translatable
358+
let msg = format!("add `#![feature({})]` to the crate attributes to enable", self.feature);
357359
#[allow(rustc::untranslatable_diagnostic)]
358-
err.help(format!("add `#![feature({})]` to the crate attributes to enable", self.feature));
360+
if let Some(span) = self.suggestion_span {
361+
err.span_suggestion_verbose(
362+
span,
363+
msg,
364+
format!("#![feature({})]\n", self.feature),
365+
Applicability::MachineApplicable,
366+
);
367+
} else {
368+
err.help(msg);
369+
}
359370

360371
err
361372
}

tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error: `foobar` is not yet stable as a const fn
44
LL | foobar();
55
| ^^^^^^^^
66
|
7-
= help: add `#![feature(const_foobar)]` to the crate attributes to enable
7+
help: add `#![feature(const_foobar)]` to the crate attributes to enable
8+
|
9+
LL + #![feature(const_foobar)]
10+
|
811

912
error: aborting due to 1 previous error
1013

0 commit comments

Comments
 (0)