Skip to content

Commit ac1f9f7

Browse files
committed
Add sanity check for inconsistent soft usage on soft-unstable items
It doesn't make sense for something to be partially soft, and allowing inconsistent softness markers would risk an item accidentally becoming properly unstable as its features stabilize.
1 parent de1fbaf commit ac1f9f7

File tree

5 files changed

+46
-5
lines changed

5 files changed

+46
-5
lines changed

compiler/rustc_attr/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ attr_rustc_const_stable_indirect_pairing =
100100
attr_rustc_promotable_pairing =
101101
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
102102
103+
attr_soft_inconsistent =
104+
`soft` must be present on either none or all of an item's `unstable` attributes
105+
103106
attr_soft_no_args =
104107
`soft` should not have any arguments
105108

compiler/rustc_attr/src/builtin.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -502,10 +502,17 @@ fn add_level(
502502
.emit_err(session_diagnostics::MultipleUnstableReasons { span: attr.span });
503503
}
504504
}
505-
// Make the unstability soft if any unstable attributes are marked 'soft'; if an
506-
// unstable item is allowed in stable rust, another attribute shouldn't break that.
507-
// FIXME(dianne): should there be a check that all unstables are soft if any are?
508-
*is_soft |= new_soft;
505+
// If any unstable attributes are marked 'soft', all should be. This keeps soft-unstable
506+
// items from accidentally being made properly unstable as attributes are removed.
507+
if *is_soft != new_soft {
508+
let spans = stab_spans
509+
.iter()
510+
.filter(|(stab, _)| stab.is_unstable())
511+
.map(|&(_, sp)| sp)
512+
.chain([attr.span])
513+
.collect();
514+
sess.dcx().emit_err(session_diagnostics::SoftInconsistent { spans });
515+
}
509516
}
510517
// an item with some stable and some unstable features is unstable
511518
(Some(Unstable { .. }), Stable { .. }) => {}

compiler/rustc_attr/src/session_diagnostics.rs

+7
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,13 @@ pub(crate) struct SoftNoArgs {
407407
pub span: Span,
408408
}
409409

410+
#[derive(Diagnostic)]
411+
#[diag(attr_soft_inconsistent)]
412+
pub(crate) struct SoftInconsistent {
413+
#[primary_span]
414+
pub spans: Vec<Span>,
415+
}
416+
410417
#[derive(Diagnostic)]
411418
#[diag(attr_unknown_version_literal)]
412419
pub(crate) struct UnknownVersionLiteral {

tests/ui/stability-attribute/multiple-stability-attribute-sanity.rs

+8
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,12 @@ fn f1() { }
1313
#[unstable(feature = "c", issue = "none", reason = "reason 3")] //~ ERROR multiple reasons provided for unstability
1414
fn f2() { }
1515

16+
#[unstable(feature = "a", issue = "none")] //~ ERROR `soft` must be present on either none or all of an item's `unstable` attributes
17+
#[unstable(feature = "b", issue = "none", soft)]
18+
fn f3() { }
19+
20+
#[unstable(feature = "a", issue = "none", soft)] //~ ERROR `soft` must be present on either none or all of an item's `unstable` attributes
21+
#[unstable(feature = "b", issue = "none")]
22+
fn f4() { }
23+
1624
fn main() { }

tests/ui/stability-attribute/multiple-stability-attribute-sanity.stderr

+17-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,21 @@ error: multiple reasons provided for unstability
1616
LL | #[unstable(feature = "c", issue = "none", reason = "reason 3")]
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

19-
error: aborting due to 3 previous errors
19+
error: `soft` must be present on either none or all of an item's `unstable` attributes
20+
--> $DIR/multiple-stability-attribute-sanity.rs:16:1
21+
|
22+
LL | #[unstable(feature = "a", issue = "none")]
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
LL | #[unstable(feature = "b", issue = "none", soft)]
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26+
27+
error: `soft` must be present on either none or all of an item's `unstable` attributes
28+
--> $DIR/multiple-stability-attribute-sanity.rs:20:1
29+
|
30+
LL | #[unstable(feature = "a", issue = "none", soft)]
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
LL | #[unstable(feature = "b", issue = "none")]
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
35+
error: aborting due to 5 previous errors
2036

0 commit comments

Comments
 (0)