Skip to content

Commit 4134a4a

Browse files
authored
Rollup merge of #66299 - rossmacarthur:fix-41260-avoid-issue-0, r=varkor
support issue = "none" in unstable attributes This works towards fixing #41260. This PR allows the use of `issue = "none"` in unstable attributes and makes changes to internally store the issue number as an `Option<NonZeroU32>`. For example: ```rust #[unstable(feature = "unstable_test_feature", issue = "none")] fn unstable_issue_none() {} ``` It was not made optional because feedback seen here #60860 suggested that people might forget the issue field if it was optional. I could not remove the current uses of `issue = "0"` (of which there are a lot) because the stage 0 compiler expects the old syntax. Once this is available in the stage 0 compiler we can replace all uses of `"0"` with `"none"` and no longer allow `"0"`. This is my first time contributing, so I'm not sure what the protocol is with two-part things like this, so some guidance would be appreciated. r? @varkor
2 parents 6bdd1be + 3ba8257 commit 4134a4a

File tree

9 files changed

+82
-39
lines changed

9 files changed

+82
-39
lines changed

src/librustc/middle/stability.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ use syntax::attr::{self, Stability, Deprecation, RustcDeprecation};
2222
use crate::ty::{self, TyCtxt};
2323
use crate::util::nodemap::{FxHashSet, FxHashMap};
2424

25-
use std::mem::replace;
2625
use std::cmp::Ordering;
26+
use std::mem::replace;
27+
use std::num::NonZeroU32;
2728

2829
#[derive(PartialEq, Clone, Copy, Debug)]
2930
pub enum StabilityLevel {
@@ -441,7 +442,7 @@ impl<'tcx> Index<'tcx> {
441442
let stability = tcx.intern_stability(Stability {
442443
level: attr::StabilityLevel::Unstable {
443444
reason: Some(Symbol::intern(reason)),
444-
issue: 27812,
445+
issue: NonZeroU32::new(27812),
445446
is_soft: false,
446447
},
447448
feature: sym::rustc_private,
@@ -488,7 +489,7 @@ pub fn report_unstable(
488489
sess: &Session,
489490
feature: Symbol,
490491
reason: Option<Symbol>,
491-
issue: u32,
492+
issue: Option<NonZeroU32>,
492493
is_soft: bool,
493494
span: Span,
494495
soft_handler: impl FnOnce(&'static lint::Lint, Span, &str),
@@ -520,7 +521,7 @@ pub fn report_unstable(
520521
soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg)
521522
} else {
522523
emit_feature_err(
523-
&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
524+
&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg
524525
);
525526
}
526527
}
@@ -637,7 +638,7 @@ pub enum EvalResult {
637638
Deny {
638639
feature: Symbol,
639640
reason: Option<Symbol>,
640-
issue: u32,
641+
issue: Option<NonZeroU32>,
641642
is_soft: bool,
642643
},
643644
/// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
@@ -758,7 +759,7 @@ impl<'tcx> TyCtxt<'tcx> {
758759
// the `-Z force-unstable-if-unmarked` flag present (we're
759760
// compiling a compiler crate), then let this missing feature
760761
// annotation slide.
761-
if feature == sym::rustc_private && issue == 27812 {
762+
if feature == sym::rustc_private && issue == NonZeroU32::new(27812) {
762763
if self.sess.opts.debugging_opts.force_unstable_if_unmarked {
763764
return EvalResult::Allow;
764765
}

src/librustc/session/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use std::cell::{self, RefCell};
4141
use std::env;
4242
use std::fmt;
4343
use std::io::Write;
44+
use std::num::NonZeroU32;
4445
use std::path::PathBuf;
4546
use std::time::Duration;
4647
use std::sync::Arc;
@@ -183,7 +184,7 @@ enum DiagnosticBuilderMethod {
183184
pub enum DiagnosticMessageId {
184185
ErrorId(u16), // EXXXX error code as integer
185186
LintId(lint::LintId),
186-
StabilityId(u32), // issue number
187+
StabilityId(Option<NonZeroU32>), // issue number
187188
}
188189

189190
impl From<&'static lint::Lint> for DiagnosticMessageId {

src/librustdoc/clean/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use std::fmt;
3939
use std::hash::{Hash, Hasher};
4040
use std::default::Default;
4141
use std::{mem, slice, vec};
42+
use std::num::NonZeroU32;
4243
use std::iter::FromIterator;
4344
use std::rc::Rc;
4445
use std::cell::RefCell;
@@ -4399,7 +4400,7 @@ pub struct Stability {
43994400
pub since: String,
44004401
pub deprecation: Option<Deprecation>,
44014402
pub unstable_reason: Option<String>,
4402-
pub issue: Option<u32>,
4403+
pub issue: Option<NonZeroU32>,
44034404
}
44044405

44054406
#[derive(Clone, Debug)]
@@ -4428,7 +4429,7 @@ impl Clean<Stability> for attr::Stability {
44284429
_ => None,
44294430
},
44304431
issue: match self.level {
4431-
attr::Unstable {issue, ..} => Some(issue),
4432+
attr::Unstable {issue, ..} => issue,
44324433
_ => None,
44334434
}
44344435
}

src/libsyntax/attr/builtin.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::print::pprust;
66
use crate::sess::ParseSess;
77

88
use errors::{Applicability, Handler};
9+
use std::num::NonZeroU32;
910
use syntax_pos::hygiene::Transparency;
1011
use syntax_pos::{symbol::Symbol, symbol::sym, Span};
1112

@@ -157,7 +158,7 @@ pub struct Stability {
157158
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
158159
pub enum StabilityLevel {
159160
// Reason for the current stability level and the relevant rust-lang issue
160-
Unstable { reason: Option<Symbol>, issue: u32, is_soft: bool },
161+
Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
161162
Stable { since: Symbol },
162163
}
163164

@@ -394,18 +395,28 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
394395

395396
match (feature, reason, issue) {
396397
(Some(feature), reason, Some(issue)) => {
398+
let issue = match &*issue.as_str() {
399+
// FIXME(rossmacarthur): remove "0" because "none" should be used
400+
// See #41260
401+
"none" | "0" => None,
402+
issue => {
403+
if let Ok(num) = issue.parse() {
404+
NonZeroU32::new(num)
405+
} else {
406+
span_err!(
407+
diagnostic,
408+
attr.span,
409+
E0545,
410+
"incorrect 'issue'"
411+
);
412+
continue
413+
}
414+
}
415+
};
397416
stab = Some(Stability {
398417
level: Unstable {
399418
reason,
400-
issue: {
401-
if let Ok(issue) = issue.as_str().parse() {
402-
issue
403-
} else {
404-
span_err!(diagnostic, attr.span, E0545,
405-
"incorrect 'issue'");
406-
continue
407-
}
408-
},
419+
issue,
409420
is_soft,
410421
},
411422
feature,

src/libsyntax/feature_gate/active.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,10 @@ declare_features! (
207207
/// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
208208
(active, allocator_internals, "1.20.0", None, None),
209209

210-
// no-tracking-issue-end
211-
212210
/// Added for testing E0705; perma-unstable.
213-
(active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)),
211+
(active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
212+
213+
// no-tracking-issue-end
214214

215215
// -------------------------------------------------------------------------
216216
// feature-group-end: internal feature gates

src/libsyntax/feature_gate/check.rs

+16-15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
1818
use log::debug;
1919

2020
use std::env;
21+
use std::num::NonZeroU32;
2122

2223
#[derive(Copy, Clone, Debug)]
2324
pub enum Stability {
@@ -55,25 +56,28 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features:
5556
PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
5657
}
5758

58-
fn find_lang_feature_issue(feature: Symbol) -> Option<u32> {
59+
fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
5960
if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
6061
// FIXME (#28244): enforce that active features have issue numbers
61-
// assert!(info.issue.is_some())
62-
info.issue
62+
// assert!(info.issue().is_some())
63+
info.issue()
6364
} else {
6465
// search in Accepted, Removed, or Stable Removed features
65-
let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
66+
let found = ACCEPTED_FEATURES
67+
.iter()
68+
.chain(REMOVED_FEATURES)
69+
.chain(STABLE_REMOVED_FEATURES)
6670
.find(|t| t.name == feature);
6771
match found {
68-
Some(&Feature { issue, .. }) => issue,
69-
None => panic!("Feature `{}` is not declared anywhere", feature),
72+
Some(found) => found.issue(),
73+
None => panic!("feature `{}` is not declared anywhere", feature),
7074
}
7175
}
7276
}
7377

7478
pub enum GateIssue {
7579
Language,
76-
Library(Option<u32>)
80+
Library(Option<NonZeroU32>)
7781
}
7882

7983
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -126,14 +130,11 @@ fn leveled_feature_err<'a, S: Into<MultiSpan>>(
126130
GateStrength::Soft => diag.struct_span_warn(span, explain),
127131
};
128132

129-
match issue {
130-
None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility
131-
Some(n) => {
132-
err.note(&format!(
133-
"for more information, see https://github.com/rust-lang/rust/issues/{}",
134-
n,
135-
));
136-
}
133+
if let Some(n) = issue {
134+
err.note(&format!(
135+
"for more information, see https://github.com/rust-lang/rust/issues/{}",
136+
n,
137+
));
137138
}
138139

139140
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable

src/libsyntax/feature_gate/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ mod active;
1818
mod builtin_attrs;
1919
mod check;
2020

21-
use std::fmt;
2221
use crate::{edition::Edition, symbol::Symbol};
22+
use std::fmt;
23+
use std::num::NonZeroU32;
2324
use syntax_pos::Span;
2425

2526
#[derive(Clone, Copy)]
@@ -46,11 +47,17 @@ pub struct Feature {
4647
state: State,
4748
name: Symbol,
4849
since: &'static str,
49-
issue: Option<u32>,
50+
issue: Option<u32>, // FIXME: once #58732 is done make this an Option<NonZeroU32>
5051
edition: Option<Edition>,
5152
description: &'static str,
5253
}
5354

55+
impl Feature {
56+
fn issue(&self) -> Option<NonZeroU32> {
57+
self.issue.and_then(|i| NonZeroU32::new(i))
58+
}
59+
}
60+
5461
pub use active::{Features, INCOMPLETE_FEATURES};
5562
pub use builtin_attrs::{
5663
AttributeGate, AttributeType, GatedCfg,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Check that an issue value can be explicitly set to "none" instead of "0"
2+
#![crate_type = "lib"]
3+
#![feature(staged_api)]
4+
#![stable(feature = "stable_test_feature", since = "1.0.0")]
5+
6+
#[unstable(feature = "unstable_test_feature", issue = "0")]
7+
fn unstable_issue_0() {}
8+
9+
#[unstable(feature = "unstable_test_feature", issue = "none")]
10+
fn unstable_issue_none() {}
11+
12+
#[unstable(feature = "unstable_test_feature", issue = "something")] //~ ERROR incorrect 'issue'
13+
fn unstable_issue_not_allowed() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error[E0545]: incorrect 'issue'
2+
--> $DIR/unstable-attribute-allow-issue-none.rs:12:1
3+
|
4+
LL | #[unstable(feature = "unstable_test_feature", issue = "something")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)