|
1 | 1 | use std::num::NonZero; |
2 | 2 |
|
3 | 3 | use rustc_errors::ErrorGuaranteed; |
| 4 | +use rustc_feature::ACCEPTED_LANG_FEATURES; |
4 | 5 | use rustc_hir::target::GenericParamKind; |
5 | 6 | use rustc_hir::{ |
6 | 7 | DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel, |
@@ -366,7 +367,7 @@ pub(crate) fn parse_stability<S: Stage>( |
366 | 367 | } |
367 | 368 | } |
368 | 369 |
|
369 | | -// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable` |
| 370 | +/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable` |
370 | 371 | /// attribute, and return the feature name and its stability information. |
371 | 372 | pub(crate) fn parse_unstability<S: Stage>( |
372 | 373 | cx: &AcceptContext<'_, '_, S>, |
@@ -451,6 +452,16 @@ pub(crate) fn parse_unstability<S: Stage>( |
451 | 452 |
|
452 | 453 | match (feature, issue) { |
453 | 454 | (Ok(feature), Ok(_)) => { |
| 455 | + // Stable *language* features shouldn't be used as unstable library features. |
| 456 | + // (Not doing this for stable library features is checked by tidy.) |
| 457 | + if ACCEPTED_LANG_FEATURES.iter().any(|f| f.name == feature) { |
| 458 | + cx.emit_err(session_diagnostics::UnstableAttrForAlreadyStableFeature { |
| 459 | + attr_span: cx.attr_span, |
| 460 | + item_span: cx.target_span, |
| 461 | + }); |
| 462 | + return None; |
| 463 | + } |
| 464 | + |
454 | 465 | let level = StabilityLevel::Unstable { |
455 | 466 | reason: UnstableReason::from_opt_reason(reason), |
456 | 467 | issue: issue_num, |
|
0 commit comments