Reenable early feature-gates as future-compat warnings
This commit is contained in:
parent
e9e46c95ce
commit
767239f740
@ -2,10 +2,10 @@
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
|
||||
use rustc_ast::{PatKind, RangeEnd, VariantData};
|
||||
use rustc_errors::{struct_span_err, Applicability};
|
||||
use rustc_errors::{struct_span_err, Applicability, StashKey};
|
||||
use rustc_feature::Features;
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_feature::{Features, GateIssue};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue};
|
||||
use rustc_session::parse::{feature_err, feature_warn};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -20,9 +20,7 @@ macro_rules! gate_feature_fn {
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
|
||||
.help(help)
|
||||
.emit();
|
||||
feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit();
|
||||
}
|
||||
}};
|
||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
@ -31,8 +29,19 @@ macro_rules! gate_feature_fn {
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
|
||||
.emit();
|
||||
feature_err(&visitor.sess.parse_sess, name, span, explain).emit();
|
||||
}
|
||||
}};
|
||||
(future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
let (visitor, has_feature, span, name, explain) =
|
||||
(&*$visitor, $has_feature, $span, $name, $explain);
|
||||
let has_feature: bool = has_feature(visitor.features);
|
||||
debug!(
|
||||
"gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)",
|
||||
name, span, has_feature
|
||||
);
|
||||
if !has_feature && !span.allows_unstable($name) {
|
||||
feature_warn(&visitor.sess.parse_sess, name, span, explain);
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -44,6 +53,9 @@ macro_rules! gate_feature_post {
|
||||
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||
};
|
||||
(future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
|
||||
@ -588,11 +600,10 @@ fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
|
||||
{
|
||||
// When we encounter a statement of the form `foo: Ty = val;`, this will emit a type
|
||||
// ascription error, but the likely intention was to write a `let` statement. (#78907).
|
||||
feature_err_issue(
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::type_ascription,
|
||||
lhs.span,
|
||||
GateIssue::Language,
|
||||
"type ascription is experimental",
|
||||
).span_suggestion_verbose(
|
||||
lhs.span.shrink_to_lo(),
|
||||
@ -615,15 +626,22 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
);
|
||||
}
|
||||
ast::ExprKind::Type(..) => {
|
||||
// To avoid noise about type ascription in common syntax errors, only emit if it
|
||||
// is the *only* error.
|
||||
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
// only emit if it is the *only* error.
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
type_ascription,
|
||||
e.span,
|
||||
"type ascription is experimental"
|
||||
);
|
||||
} else {
|
||||
// And if it isn't, cancel the early-pass warning.
|
||||
self.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.steal_diagnostic(e.span, StashKey::EarlySyntaxWarning)
|
||||
.map(|err| err.cancel());
|
||||
}
|
||||
}
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
@ -789,14 +807,12 @@ macro_rules! gate_all {
|
||||
|
||||
// All uses of `gate_all!` below this point were added in #65742,
|
||||
// and subsequently disabled (with the non-early gating readded).
|
||||
// We emit an early future-incompatible warning for these.
|
||||
// New syntax gates should go above here to get a hard error gate.
|
||||
macro_rules! gate_all {
|
||||
($gate:ident, $msg:literal) => {
|
||||
// FIXME(eddyb) do something more useful than always
|
||||
// disabling these uses of early feature-gatings.
|
||||
if false {
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_feature_post!(&visitor, $gate, *span, $msg);
|
||||
}
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -809,11 +825,7 @@ macro_rules! gate_all {
|
||||
gate_all!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all!(label_break_value, "labels on blocks are unstable");
|
||||
gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
// only emit if it is the *only* error. (Also check it last.)
|
||||
if sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
gate_all!(type_ascription, "type ascription is experimental");
|
||||
}
|
||||
gate_all!(type_ascription, "type ascription is experimental");
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
@ -458,6 +458,7 @@ struct HandlerInner {
|
||||
pub enum StashKey {
|
||||
ItemNoType,
|
||||
UnderscoreForArrayLengths,
|
||||
EarlySyntaxWarning,
|
||||
}
|
||||
|
||||
fn default_track_diagnostic(_: &Diagnostic) {}
|
||||
|
@ -3212,6 +3212,56 @@
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unstable_syntax_pre_expansion` lint detects the use of unstable
|
||||
/// syntax that is discarded during attribute expansion.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #[cfg(FALSE)]
|
||||
/// macro foo() {}
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The input to active attributes such as `#[cfg]` or procedural macro
|
||||
/// attributes is required to be valid syntax. Previously, the compiler only
|
||||
/// gated the use of unstable syntax features after resolving `#[cfg]` gates
|
||||
/// and expanding procedural macros.
|
||||
///
|
||||
/// To avoid relying on unstable syntax, move the use of unstable syntax
|
||||
/// into a position where the compiler does not parse the syntax, such as a
|
||||
/// functionlike macro.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![deny(unstable_syntax_pre_expansion)]
|
||||
///
|
||||
/// macro_rules! identity {
|
||||
/// ( $($tokens:tt)* ) => { $($tokens)* }
|
||||
/// }
|
||||
///
|
||||
/// #[cfg(FALSE)]
|
||||
/// identity! {
|
||||
/// macro foo() {}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This is a [future-incompatible] lint to transition this
|
||||
/// to a hard error in the future. See [issue #65860] for more details.
|
||||
///
|
||||
/// [issue #65860]: https://github.com/rust-lang/rust/issues/65860
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub UNSTABLE_SYNTAX_PRE_EXPANSION,
|
||||
Warn,
|
||||
"unstable syntax can change at any point in the future, causing a hard error!",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #65860 <https://github.com/rust-lang/rust/issues/65860>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass! {
|
||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||
/// that are used by other parts of the compiler.
|
||||
@ -3280,6 +3330,7 @@
|
||||
POINTER_STRUCTURAL_MATCH,
|
||||
NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
SOFT_UNSTABLE,
|
||||
UNSTABLE_SYNTAX_PRE_EXPANSION,
|
||||
INLINE_NO_SANITIZE,
|
||||
BAD_ASM_STYLE,
|
||||
ASM_SUB_REGISTER,
|
||||
|
@ -2,15 +2,17 @@
|
||||
//! It also serves as an input to the parser itself.
|
||||
|
||||
use crate::config::CheckCfg;
|
||||
use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
|
||||
use crate::lint::{
|
||||
builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
|
||||
};
|
||||
use crate::SessionDiagnostic;
|
||||
use rustc_ast::node_id::NodeId;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
|
||||
use rustc_errors::{
|
||||
error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder,
|
||||
DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
|
||||
DiagnosticMessage, ErrorGuaranteed, MultiSpan, StashKey,
|
||||
};
|
||||
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
|
||||
use rustc_span::edition::Edition;
|
||||
@ -101,11 +103,58 @@ pub fn feature_err_issue<'a>(
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let span = span.into();
|
||||
|
||||
// Cancel an earlier warning for this same error, if it exists.
|
||||
if let Some(span) = span.primary_span() {
|
||||
sess.span_diagnostic
|
||||
.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
|
||||
.map(|err| err.cancel());
|
||||
}
|
||||
|
||||
let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658));
|
||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
|
||||
err
|
||||
}
|
||||
|
||||
/// Construct a future incompatibility diagnostic for a feature gate.
|
||||
///
|
||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
||||
pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explain: &str) {
|
||||
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
|
||||
}
|
||||
|
||||
/// Construct a future incompatibility diagnostic for a feature gate.
|
||||
///
|
||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
||||
///
|
||||
/// This variant allows you to control whether it is a library or language feature.
|
||||
/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
|
||||
pub fn feature_warn_issue<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: Span,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) {
|
||||
let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
|
||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
|
||||
|
||||
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
|
||||
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
|
||||
let future_incompatible = lint.future_incompatible.as_ref().unwrap();
|
||||
err.code(DiagnosticId::Lint {
|
||||
name: lint.name_lower(),
|
||||
has_future_breakage: false,
|
||||
is_force_warn: false,
|
||||
});
|
||||
err.warn(lint.desc);
|
||||
err.note(format!("for more information, see {}", future_incompatible.reference));
|
||||
|
||||
// A later feature_err call can steal and cancel this warning.
|
||||
err.stash(span, StashKey::EarlySyntaxWarning);
|
||||
}
|
||||
|
||||
/// Adds the diagnostics for a feature to an existing error.
|
||||
pub fn add_feature_diagnostics<'a>(err: &mut Diagnostic, sess: &'a ParseSess, feature: Symbol) {
|
||||
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language);
|
||||
|
@ -3,11 +3,18 @@
|
||||
// compile-flags: --test
|
||||
|
||||
#![feature(async_closure)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(generators)]
|
||||
#![feature(half_open_range_patterns)]
|
||||
#![feature(label_break_value)]
|
||||
#![feature(more_qualified_paths)]
|
||||
#![feature(raw_ref_op)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(type_ascription)]
|
||||
#![deny(unused_macros)]
|
||||
|
||||
macro_rules! stringify_block {
|
||||
|
@ -7,7 +7,7 @@ fn main() {}
|
||||
|
||||
// Test the `pat` macro fragment parser:
|
||||
macro_rules! accept_pat {
|
||||
($p:pat) => {}
|
||||
($p:pat) => {};
|
||||
}
|
||||
|
||||
accept_pat!((p | q));
|
||||
@ -21,28 +21,28 @@ macro_rules! accept_pat {
|
||||
#[cfg(FALSE)]
|
||||
fn or_patterns() {
|
||||
// Top level of `let`:
|
||||
let (| A | B);
|
||||
let (A | B);
|
||||
let (A | B);
|
||||
let (A | B): u8;
|
||||
let (A | B) = 0;
|
||||
let (A | B): u8 = 0;
|
||||
|
||||
// Top level of `for`:
|
||||
for | A | B in 0 {}
|
||||
for A | B in 0 {}
|
||||
for A | B in 0 {}
|
||||
|
||||
// Top level of `while`:
|
||||
while let | A | B = 0 {}
|
||||
while let A | B = 0 {}
|
||||
while let A | B = 0 {}
|
||||
|
||||
// Top level of `if`:
|
||||
if let | A | B = 0 {}
|
||||
if let A | B = 0 {}
|
||||
if let A | B = 0 {}
|
||||
|
||||
// Top level of `match` arms:
|
||||
match 0 {
|
||||
| A | B => {},
|
||||
A | B => {},
|
||||
A | B => {}
|
||||
A | B => {}
|
||||
}
|
||||
|
||||
// Functions:
|
||||
@ -68,6 +68,8 @@ fn fun((A | B): _) {}
|
||||
|
||||
// These bind as `(prefix p) | q` as opposed to `prefix (p | q)`:
|
||||
let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
|
||||
//~^ WARN box pattern syntax is experimental
|
||||
//~| WARN unstable syntax
|
||||
let (&0 | 1);
|
||||
let (&mut 0 | 1);
|
||||
let (x @ 0 | 1);
|
||||
|
13
src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr
Normal file
13
src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
warning: box pattern syntax is experimental
|
||||
--> $DIR/or-patterns-syntactic-pass.rs:70:10
|
||||
|
|
||||
LL | let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -3,7 +3,11 @@
|
||||
#[cfg(FALSE)]
|
||||
fn syntax() {
|
||||
foo::<T = u8, T: Ord, String>();
|
||||
//~^ WARN associated type bounds are unstable
|
||||
//~| WARN unstable syntax
|
||||
foo::<T = u8, 'a, T: Ord>();
|
||||
//~^ WARN associated type bounds are unstable
|
||||
//~| WARN unstable syntax
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -0,0 +1,24 @@
|
||||
warning: associated type bounds are unstable
|
||||
--> $DIR/constraints-before-generic-args-syntactic-pass.rs:5:19
|
||||
|
|
||||
LL | foo::<T = u8, T: Ord, String>();
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: associated type bounds are unstable
|
||||
--> $DIR/constraints-before-generic-args-syntactic-pass.rs:8:23
|
||||
|
|
||||
LL | foo::<T = u8, 'a, T: Ord>();
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -19,6 +19,8 @@ fn foo(..: u8) {}
|
||||
|
||||
// Box patterns:
|
||||
let box ..;
|
||||
//~^ WARN box pattern syntax is experimental
|
||||
//~| WARN unstable syntax
|
||||
|
||||
// In or-patterns:
|
||||
match x {
|
||||
@ -57,7 +59,7 @@ fn foo(..: u8) {}
|
||||
.. |
|
||||
[
|
||||
(
|
||||
box ..,
|
||||
box .., //~ WARN box pattern syntax is experimental
|
||||
&(..),
|
||||
&mut ..,
|
||||
x @ ..
|
||||
@ -67,4 +69,5 @@ fn foo(..: u8) {}
|
||||
ref mut x @ ..
|
||||
=> {}
|
||||
}
|
||||
//~| WARN unstable syntax
|
||||
}
|
||||
|
24
src/test/ui/pattern/rest-pat-syntactic.stderr
Normal file
24
src/test/ui/pattern/rest-pat-syntactic.stderr
Normal file
@ -0,0 +1,24 @@
|
||||
warning: box pattern syntax is experimental
|
||||
--> $DIR/rest-pat-syntactic.rs:21:9
|
||||
|
|
||||
LL | let box ..;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: box pattern syntax is experimental
|
||||
--> $DIR/rest-pat-syntactic.rs:62:17
|
||||
|
|
||||
LL | box ..,
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
Loading…
Reference in New Issue
Block a user