Skip to content

Commit 8f2d906

Browse files
committed
Implementation of incompatible features error
If two features are defined as incompatible, using them together would result in an error
1 parent 08deb86 commit 8f2d906

File tree

5 files changed

+60
-1
lines changed

5 files changed

+60
-1
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+34
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
608608

609609
pub fn check_crate(krate: &ast::Crate, sess: &Session) {
610610
maybe_stage_features(sess, krate);
611+
check_incompatible_features(sess);
611612
let mut visitor = PostExpansionVisitor { sess, features: &sess.features_untracked() };
612613

613614
let spans = sess.parse_sess.gated_spans.spans.borrow();
@@ -677,3 +678,36 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
677678
}
678679
}
679680
}
681+
682+
fn check_incompatible_features(sess: &Session) {
683+
let features = sess.features_untracked();
684+
685+
let declared_features = features
686+
.declared_lang_features
687+
.iter()
688+
.copied()
689+
.map(|(name, span, _)| (name, span))
690+
.chain(features.declared_lib_features.iter().copied());
691+
692+
for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
693+
.iter()
694+
.filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2))
695+
{
696+
if let Some((f1_name, f1_span)) = declared_features.clone().find(|(name, _)| name == f1) {
697+
if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2)
698+
{
699+
let spans = vec![f1_span, f2_span];
700+
sess.struct_span_err(
701+
spans.clone(),
702+
&format!(
703+
"features `{}` and `{}` are incompatible, using them at the same time \
704+
is not allowed",
705+
f1_name, f2_name
706+
),
707+
)
708+
.help("remove one of these features")
709+
.emit();
710+
}
711+
}
712+
}
713+
}

compiler/rustc_feature/src/active.rs

+5
Original file line numberDiff line numberDiff line change
@@ -605,3 +605,8 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
605605
sym::lazy_normalization_consts,
606606
sym::specialization,
607607
];
608+
609+
/// Some features are not allowed to be used together at the same time, if
610+
/// the two are present, produce an error
611+
pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] =
612+
&[(sym::const_generics, sym::min_const_generics)];

compiler/rustc_feature/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU3
131131
}
132132

133133
pub use accepted::ACCEPTED_FEATURES;
134-
pub use active::{Features, ACTIVE_FEATURES, INCOMPLETE_FEATURES};
134+
pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES, INCOMPLETE_FEATURES};
135135
pub use builtin_attrs::{
136136
deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate,
137137
AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(const_generics)]
2+
//~^ ERROR features `const_generics` and `min_const_generics` are incompatible
3+
#![allow(incomplete_features)]
4+
#![feature(min_const_generics)]
5+
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: features `const_generics` and `min_const_generics` are incompatible, using them at the same time is not allowed
2+
--> $DIR/min-and-full-same-time.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
...
7+
LL | #![feature(min_const_generics)]
8+
| ^^^^^^^^^^^^^^^^^^
9+
|
10+
= help: remove one of these features
11+
12+
error: aborting due to previous error
13+

0 commit comments

Comments
 (0)