Clean up condition evaluation system
This commit is contained in:
parent
653463731a
commit
ae38533ed7
@ -454,6 +454,15 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
|
|||||||
sess.first_attr_value_str_by_name(attrs, sym::crate_name)
|
sess.first_attr_value_str_by_name(attrs, sym::crate_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Condition {
|
||||||
|
pub name: Symbol,
|
||||||
|
pub name_span: Span,
|
||||||
|
pub value: Option<Symbol>,
|
||||||
|
pub value_span: Option<Span>,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
/// Tests if a cfg-pattern matches the cfg set
|
/// Tests if a cfg-pattern matches the cfg set
|
||||||
pub fn cfg_matches(
|
pub fn cfg_matches(
|
||||||
cfg: &ast::MetaItem,
|
cfg: &ast::MetaItem,
|
||||||
@ -462,70 +471,42 @@ pub fn cfg_matches(
|
|||||||
features: Option<&Features>,
|
features: Option<&Features>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||||
try_gate_cfg(cfg, sess, features);
|
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||||
let error = |span, msg| {
|
if let Some(names_valid) = &sess.check_config.names_valid {
|
||||||
sess.span_diagnostic.span_err(span, msg);
|
if !names_valid.contains(&cfg.name) {
|
||||||
true
|
sess.buffer_lint_with_diagnostic(
|
||||||
};
|
UNEXPECTED_CFGS,
|
||||||
if cfg.path.segments.len() != 1 {
|
cfg.span,
|
||||||
return error(cfg.path.span, "`cfg` predicate key must be an identifier");
|
lint_node_id,
|
||||||
}
|
"unexpected `cfg` condition name",
|
||||||
match &cfg.kind {
|
BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None),
|
||||||
MetaItemKind::List(..) => {
|
|
||||||
error(cfg.span, "unexpected parentheses after `cfg` predicate key")
|
|
||||||
}
|
|
||||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
|
||||||
handle_errors(
|
|
||||||
sess,
|
|
||||||
lit.span,
|
|
||||||
AttrError::UnsupportedLiteral(
|
|
||||||
"literal in `cfg` predicate value must be a string",
|
|
||||||
lit.kind.is_bytestr(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
true
|
|
||||||
}
|
|
||||||
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
|
|
||||||
let ident = cfg.ident().expect("multi-segment cfg predicate");
|
|
||||||
let name = ident.name;
|
|
||||||
let value = cfg.value_str();
|
|
||||||
if let Some(names_valid) = &sess.check_config.names_valid {
|
|
||||||
if !names_valid.contains(&name) {
|
|
||||||
sess.buffer_lint_with_diagnostic(
|
|
||||||
UNEXPECTED_CFGS,
|
|
||||||
cfg.span,
|
|
||||||
lint_node_id,
|
|
||||||
"unexpected `cfg` condition name",
|
|
||||||
BuiltinLintDiagnostics::UnexpectedCfg((name, ident.span), None),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(value) = value {
|
|
||||||
if let Some(values) = &sess.check_config.values_valid.get(&name) {
|
|
||||||
if !values.contains(&value) {
|
|
||||||
sess.buffer_lint_with_diagnostic(
|
|
||||||
UNEXPECTED_CFGS,
|
|
||||||
cfg.span,
|
|
||||||
lint_node_id,
|
|
||||||
"unexpected `cfg` condition value",
|
|
||||||
BuiltinLintDiagnostics::UnexpectedCfg(
|
|
||||||
(name, ident.span),
|
|
||||||
Some((value, cfg.name_value_literal_span().unwrap())),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sess.config.contains(&(name, value))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(value) = cfg.value {
|
||||||
|
if let Some(values) = &sess.check_config.values_valid.get(&cfg.name) {
|
||||||
|
if !values.contains(&value) {
|
||||||
|
sess.buffer_lint_with_diagnostic(
|
||||||
|
UNEXPECTED_CFGS,
|
||||||
|
cfg.span,
|
||||||
|
lint_node_id,
|
||||||
|
"unexpected `cfg` condition value",
|
||||||
|
BuiltinLintDiagnostics::UnexpectedCfg(
|
||||||
|
(cfg.name, cfg.name_span),
|
||||||
|
cfg.value_span.map(|vs| (value, vs)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sess.config.contains(&(cfg.name, cfg.value))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_gate_cfg(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) {
|
fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
|
||||||
let gate = find_gated_cfg(|sym| cfg.has_name(sym));
|
let gate = find_gated_cfg(|sym| sym == name);
|
||||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||||
gate_cfg(&gated_cfg, cfg.span, sess, feats);
|
gate_cfg(&gated_cfg, span, sess, feats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,11 +544,11 @@ pub fn eval_condition(
|
|||||||
cfg: &ast::MetaItem,
|
cfg: &ast::MetaItem,
|
||||||
sess: &ParseSess,
|
sess: &ParseSess,
|
||||||
features: Option<&Features>,
|
features: Option<&Features>,
|
||||||
eval: &mut impl FnMut(&ast::MetaItem) -> bool,
|
eval: &mut impl FnMut(Condition) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match cfg.kind {
|
match cfg.kind {
|
||||||
ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
|
ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
|
||||||
try_gate_cfg(cfg, sess, features);
|
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||||
let (min_version, span) = match &mis[..] {
|
let (min_version, span) = match &mis[..] {
|
||||||
[NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
[NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||||
(sym, span)
|
(sym, span)
|
||||||
@ -662,7 +643,32 @@ pub fn eval_condition(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => eval(cfg),
|
ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
|
||||||
|
sess.span_diagnostic
|
||||||
|
.span_err(cfg.path.span, "`cfg` predicate key must be an identifier");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
|
||||||
|
handle_errors(
|
||||||
|
sess,
|
||||||
|
lit.span,
|
||||||
|
AttrError::UnsupportedLiteral(
|
||||||
|
"literal in `cfg` predicate value must be a string",
|
||||||
|
lit.kind.is_bytestr(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
|
||||||
|
let ident = cfg.ident().expect("multi-segment cfg predicate");
|
||||||
|
eval(Condition {
|
||||||
|
name: ident.name,
|
||||||
|
name_span: ident.span,
|
||||||
|
value: cfg.value_str(),
|
||||||
|
value_span: cfg.name_value_literal_span(),
|
||||||
|
span: cfg.span,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +89,8 @@ impl<'tcx> OnUnimplementedDirective {
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
|
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
|
||||||
if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
|
if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
|
||||||
errored = Some(guar);
|
errored = Some(guar);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@ -226,14 +226,12 @@ impl<'tcx> OnUnimplementedDirective {
|
|||||||
condition,
|
condition,
|
||||||
&tcx.sess.parse_sess,
|
&tcx.sess.parse_sess,
|
||||||
Some(tcx.features()),
|
Some(tcx.features()),
|
||||||
&mut |c| {
|
&mut |cfg| {
|
||||||
c.ident().map_or(false, |ident| {
|
let value = cfg.value.map(|v| {
|
||||||
let value = c.value_str().map(|s| {
|
OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
|
||||||
OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
|
});
|
||||||
});
|
|
||||||
|
|
||||||
options.contains(&(ident.name, value))
|
options.contains(&(cfg.name, value))
|
||||||
})
|
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
debug!("evaluate: skipping {:?} due to condition", command);
|
debug!("evaluate: skipping {:?} due to condition", command);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user