Skip to content

Commit a47fee5

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 rust-lang#81370.
1 parent bcd0683 commit a47fee5

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
@@ -911,16 +911,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
911911
// regular stability.
912912
feature == sym::rustc_private
913913
&& issue == NonZero::new(27812)
914-
&& self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
914+
&& tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
915915
};
916916
// Even if the feature is enabled, we still need check_op to double-check
917917
// this if the callee is not safe to expose on stable.
918918
if !feature_enabled || !callee_safe_to_expose_on_stable {
919+
let suggestion_span =
920+
tcx.hir_crate_items(()).definitions().next().and_then(|id| {
921+
tcx.crate_level_attribute_injection_span(
922+
tcx.local_def_id_to_hir_id(id),
923+
)
924+
});
919925
self.check_op(ops::FnCallUnstable {
920926
def_id: callee,
921927
feature,
922928
feature_enabled,
923929
safe_to_expose_on_stable: callee_safe_to_expose_on_stable,
930+
suggestion_span,
924931
});
925932
}
926933
}

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;
@@ -388,6 +388,7 @@ pub(crate) struct FnCallUnstable {
388388
/// expose on stable.
389389
pub feature_enabled: bool,
390390
pub safe_to_expose_on_stable: bool,
391+
pub suggestion_span: Option<Span>,
391392
}
392393

393394
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
@@ -407,8 +408,18 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
407408
def_path: ccx.tcx.def_path_str(self.def_id),
408409
});
409410
// FIXME: make this translatable
411+
let msg = format!("add `#![feature({})]` to the crate attributes to enable", self.feature);
410412
#[allow(rustc::untranslatable_diagnostic)]
411-
err.help(format!("add `#![feature({})]` to the crate attributes to enable", self.feature));
413+
if let Some(span) = self.suggestion_span {
414+
err.span_suggestion_verbose(
415+
span,
416+
msg,
417+
format!("#![feature({})]\n", self.feature),
418+
Applicability::MachineApplicable,
419+
);
420+
} else {
421+
err.help(msg);
422+
}
412423

413424
err
414425
}

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)