Migrate parts of rustc_expand to session diagnostics
This migrates everything but the `mbe` and `proc_macro` modules. It also contains a few cleanups and drive-by/accidental diagnostic improvements which can be seen in the diff for the UI tests.
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
//! Conditional compilation stripping.
|
||||
|
||||
use crate::errors::{
|
||||
FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg,
|
||||
MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported,
|
||||
};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
|
||||
@@ -10,7 +14,6 @@ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
|
||||
use rustc_feature::{Feature, Features, State as FeatureState};
|
||||
use rustc_feature::{
|
||||
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
|
||||
@@ -33,18 +36,12 @@ pub struct StripUnconfigured<'a> {
|
||||
pub lint_node_id: NodeId,
|
||||
}
|
||||
|
||||
fn get_features(
|
||||
sess: &Session,
|
||||
span_handler: &Handler,
|
||||
krate_attrs: &[ast::Attribute],
|
||||
) -> Features {
|
||||
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
|
||||
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
|
||||
err.span_label(span, "feature has been removed");
|
||||
if let Some(reason) = reason {
|
||||
err.note(reason);
|
||||
}
|
||||
err.emit();
|
||||
fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
|
||||
fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
|
||||
sess.emit_err(FeatureRemoved {
|
||||
span,
|
||||
reason: reason.map(|reason| FeatureRemovedReason { reason }),
|
||||
});
|
||||
}
|
||||
|
||||
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
|
||||
@@ -117,34 +114,34 @@ fn get_features(
|
||||
continue;
|
||||
};
|
||||
|
||||
let bad_input = |span| {
|
||||
struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
|
||||
};
|
||||
|
||||
for mi in list {
|
||||
let name = match mi.ident() {
|
||||
Some(ident) if mi.is_word() => ident.name,
|
||||
Some(ident) => {
|
||||
bad_input(mi.span())
|
||||
.span_suggestion(
|
||||
mi.span(),
|
||||
"expected just one word",
|
||||
ident.name,
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
sess.emit_err(MalformedFeatureAttribute {
|
||||
span: mi.span(),
|
||||
help: MalformedFeatureAttributeHelp::Suggestion {
|
||||
span: mi.span(),
|
||||
suggestion: ident.name,
|
||||
},
|
||||
});
|
||||
continue;
|
||||
}
|
||||
None => {
|
||||
bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
|
||||
sess.emit_err(MalformedFeatureAttribute {
|
||||
span: mi.span(),
|
||||
help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(edition) = edition_enabled_features.get(&name) {
|
||||
let msg =
|
||||
&format!("the feature `{}` is included in the Rust {} edition", name, edition);
|
||||
span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
|
||||
if let Some(&edition) = edition_enabled_features.get(&name) {
|
||||
sess.emit_warning(FeatureIncludedInEdition {
|
||||
span: mi.span(),
|
||||
feature: name,
|
||||
edition,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -159,7 +156,7 @@ fn get_features(
|
||||
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
|
||||
state
|
||||
{
|
||||
feature_removed(span_handler, mi.span(), *reason);
|
||||
feature_removed(sess, mi.span(), *reason);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -173,14 +170,7 @@ fn get_features(
|
||||
|
||||
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
|
||||
if allowed.iter().all(|f| name.as_str() != f) {
|
||||
struct_span_err!(
|
||||
span_handler,
|
||||
mi.span(),
|
||||
E0725,
|
||||
"the feature `{}` is not in the list of allowed features",
|
||||
name
|
||||
)
|
||||
.emit();
|
||||
sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -221,7 +211,7 @@ pub fn features(
|
||||
}
|
||||
Some(attrs) => {
|
||||
krate.attrs = attrs;
|
||||
let features = get_features(sess, diag, &krate.attrs);
|
||||
let features = get_features(sess, &krate.attrs);
|
||||
if err_count == diag.err_count() {
|
||||
// Avoid reconfiguring malformed `cfg_attr`s.
|
||||
strip_unconfigured.features = Some(&features);
|
||||
@@ -503,8 +493,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||
// N.B., this is intentionally not part of the visit_expr() function
|
||||
// in order for filter_map_expr() to be able to avoid this check
|
||||
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
|
||||
let msg = "removing an expression is not supported in this position";
|
||||
self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
|
||||
self.sess.emit_err(RemoveExprNotSupported { span: attr.span });
|
||||
}
|
||||
|
||||
self.process_cfg_attrs(expr);
|
||||
@@ -513,27 +502,26 @@ impl<'a> StripUnconfigured<'a> {
|
||||
}
|
||||
|
||||
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
|
||||
let error = |span, msg, suggestion: &str| {
|
||||
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
|
||||
if !suggestion.is_empty() {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"expected syntax is",
|
||||
suggestion,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
None
|
||||
};
|
||||
let span = meta_item.span;
|
||||
match meta_item.meta_item_list() {
|
||||
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
|
||||
Some([]) => error(span, "`cfg` predicate is not specified", ""),
|
||||
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
|
||||
None => {
|
||||
sess.emit_err(InvalidCfg::NotFollowedByParens { span });
|
||||
None
|
||||
}
|
||||
Some([]) => {
|
||||
sess.emit_err(InvalidCfg::NoPredicate { span });
|
||||
None
|
||||
}
|
||||
Some([_, .., l]) => {
|
||||
sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
|
||||
None
|
||||
}
|
||||
Some([single]) => match single.meta_item() {
|
||||
Some(meta_item) => Some(meta_item),
|
||||
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
|
||||
None => {
|
||||
sess.emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user