Skip to content

Rollup of 5 pull requests #67291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0f47327
Remove i686-unknown-dragonfly target
tuxillo Dec 12, 2019
641ccd5
Fix signature of `__wasilibc_find_relpath`
alexcrichton Dec 12, 2019
8f3021b
Get active features dynamically by their `Symbol`
ecstatic-morse Dec 10, 2019
57959b2
Add feature gate for `const_loop`
ecstatic-morse Dec 10, 2019
8f59902
Put MIR checks for loops behind the feature flag
ecstatic-morse Dec 10, 2019
ee233c0
Restructue HIR const-checker to handle features with multiple gates
ecstatic-morse Dec 10, 2019
99e132d
Extend control flow basics tests with loops
ecstatic-morse Dec 11, 2019
1122404
Add qualif smoke tests for const loops
ecstatic-morse Dec 11, 2019
caa7c99
Bless unrelated tests with new help message
ecstatic-morse Dec 11, 2019
3325671
Bless modified tests
ecstatic-morse Dec 11, 2019
2add77d
Improve message when active feature indexing panics
ecstatic-morse Dec 11, 2019
a8e997c
Improve comment
ecstatic-morse Dec 11, 2019
a2a0774
Look for "unstable feature" error code in test
ecstatic-morse Dec 11, 2019
b3aecd0
Fix grammar in test description
ecstatic-morse Dec 11, 2019
2b5ae1c
Apply suggestions from review
ecstatic-morse Dec 11, 2019
80581be
Replace `Index` impl with `enabled` method
ecstatic-morse Dec 11, 2019
34ce0ba
Use better name for local containing required feature gates
ecstatic-morse Dec 11, 2019
598bed6
Ensure test actually uses dataflow, not simulation
ecstatic-morse Dec 11, 2019
029725f
Use correct nightly version for feature
ecstatic-morse Dec 11, 2019
0f0bfc9
Document `Features::enabled`
ecstatic-morse Dec 12, 2019
faa52d1
Correctly mark things as `min_const_fn`
ecstatic-morse Dec 13, 2019
b65c6ec
Fix incorrect example code of OpenOptions::open
pjw91 Dec 13, 2019
f5e9bda
doc comments: Less attribute mimicking
petrochenkov Dec 7, 2019
d720440
Rollup merge of #67151 - petrochenkov:docomm, r=estebank
Centril Dec 14, 2019
0e2fb73
Rollup merge of #67216 - ecstatic-morse:const-loop, r=oli-obk
Centril Dec 14, 2019
393ddd6
Rollup merge of #67255 - tuxillo:remove-i686-unknown-dragonfly, r=ale…
Centril Dec 14, 2019
18cbf24
Rollup merge of #67267 - alexcrichton:update-wasi-libc, r=Dylan-DPC
Centril Dec 14, 2019
389aa5f
Rollup merge of #67282 - pjw91:patch-1, r=Dylan-DPC
Centril Dec 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes/E0744.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Control-flow expressions are not allowed inside a const context.
At the moment, `if` and `match`, as well as the looping constructs `for`,
`while`, and `loop`, are forbidden inside a `const`, `static`, or `const fn`.

```compile_fail,E0744
```compile_fail,E0658
const _: i32 = {
let mut x = 0;
loop {
Expand Down
14 changes: 14 additions & 0 deletions src/librustc_feature/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ macro_rules! declare_features {
pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) {
$(f(stringify!($feature), self.$feature);)+
}

/// Is the given feature enabled?
///
/// Panics if the symbol doesn't correspond to a declared feature.
pub fn enabled(&self, feature: Symbol) -> bool {
match feature {
$( sym::$feature => self.$feature, )*

_ => panic!("`{}` was not listed in `declare_features`", feature),
}
}
}
};
}
Expand Down Expand Up @@ -526,6 +537,9 @@ declare_features! (
/// Allows using `&mut` in constant functions.
(active, const_mut_refs, "1.41.0", Some(57349), None),

/// Allows the use of `loop` and `while` in constants.
(active, const_loop, "1.41.0", Some(52000), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ pub struct MissingDoc {
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);

fn has_doc(attr: &ast::Attribute) -> bool {
if attr.is_doc_comment() {
return true;
}

if !attr.check_name(sym::doc) {
return false;
}
Expand Down Expand Up @@ -751,7 +755,7 @@ impl UnusedDocComment {

let span = sugared_span.take().unwrap_or_else(|| attr.span);

if attr.check_name(sym::doc) {
if attr.is_doc_comment() || attr.check_name(sym::doc) {
let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment");

err.span_label(
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
debug!("checking attribute: {:?}", attr);

if attr.is_doc_comment() {
return;
}

let attr_info = attr.ident().and_then(|ident| self.builtin_attributes.get(&ident.name));

if let Some(&&(name, ty, ..)) = attr_info {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_mir/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ impl NonConstOp for LiveDrop {
#[derive(Debug)]
pub struct Loop;
impl NonConstOp for Loop {
fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
Some(tcx.features().const_loop)
}

fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
// This should be caught by the HIR const-checker.
item.tcx.sess.delay_span_bug(
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_mir/transform/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,12 @@ fn check_terminator(
cleanup: _,
} => check_operand(tcx, cond, span, def_id, body),

| TerminatorKind::FalseUnwind { .. }
if feature_allowed(tcx, def_id, sym::const_loop)
=> Ok(()),

TerminatorKind::FalseUnwind { .. } => {
Err((span, "loops are not allowed in const fn".into()))
},
}
}
}
39 changes: 19 additions & 20 deletions src/librustc_parse/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ use crate::parse_in;

use rustc_errors::{PResult, Applicability};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
use syntax::attr::mk_name_value_item_str;
use syntax::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
use syntax::tokenstream::DelimSpan;
use syntax::sess::ParseSess;
use syntax_pos::{Symbol, sym};

pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
if attr.is_doc_comment() {
return;
}

let attr_info =
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);

Expand All @@ -28,25 +31,21 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
}

pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
Ok(match attr.kind {
AttrKind::Normal(ref item) => MetaItem {
span: attr.span,
path: item.path.clone(),
kind: match &attr.get_normal_item().args {
MacArgs::Empty => MetaItemKind::Word,
MacArgs::Eq(_, t) => {
let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
MetaItemKind::NameValue(v)
}
MacArgs::Delimited(dspan, delim, t) => {
check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
MetaItemKind::List(nmis)
}
let item = attr.get_normal_item();
Ok(MetaItem {
span: attr.span,
path: item.path.clone(),
kind: match &item.args {
MacArgs::Empty => MetaItemKind::Word,
MacArgs::Eq(_, t) => {
let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
MetaItemKind::NameValue(v)
}
MacArgs::Delimited(dspan, delim, t) => {
check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
MetaItemKind::List(nmis)
}
},
AttrKind::DocComment(comment) => {
mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
}
})
}
Expand Down
87 changes: 68 additions & 19 deletions src/librustc_passes/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ use rustc::hir::map::Map;
use rustc::hir;
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
use rustc_feature::Features;
use rustc::session::config::nightly_options;
use syntax::ast::Mutability;
use syntax::feature_gate::feature_err;
use syntax::span_err;
use syntax_pos::{sym, Span};
use syntax_pos::{sym, Span, Symbol};
use rustc_error_codes::*;

use std::fmt;
Expand All @@ -37,18 +37,31 @@ impl NonConstExpr {
}
}

/// Returns `true` if all feature gates required to enable this expression are turned on, or
/// `None` if there is no feature gate corresponding to this expression.
fn is_feature_gate_enabled(self, features: &Features) -> Option<bool> {
fn required_feature_gates(self) -> Option<&'static [Symbol]> {
use hir::MatchSource::*;
match self {
use hir::LoopSource::*;

let gates: &[_] = match self {
| Self::Match(Normal)
| Self::Match(IfDesugar { .. })
| Self::Match(IfLetDesugar { .. })
=> Some(features.const_if_match),
=> &[sym::const_if_match],

_ => None,
}
| Self::Loop(Loop)
=> &[sym::const_loop],

| Self::Loop(While)
| Self::Loop(WhileLet)
| Self::Match(WhileDesugar)
| Self::Match(WhileLetDesugar)
=> &[sym::const_loop, sym::const_if_match],

// A `for` loop's desugaring contains a call to `IntoIterator::into_iter`,
// so they are not yet allowed with `#![feature(const_loop)]`.
_ => return None,
};

Some(gates)
}
}

Expand Down Expand Up @@ -120,11 +133,15 @@ impl<'tcx> CheckConstVisitor<'tcx> {

/// Emits an error when an unsupported expression is found in a const context.
fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
match expr.is_feature_gate_enabled(self.tcx.features()) {
let features = self.tcx.features();
let required_gates = expr.required_feature_gates();
match required_gates {
// Don't emit an error if the user has enabled the requisite feature gates.
Some(true) => return,
Some(gates) if gates.iter().all(|&g| features.enabled(g)) => return,

// Users of `-Zunleash-the-miri-inside-of-you` must use feature gates when possible.
// `-Zunleash-the-miri-inside-of-you` only works for expressions that don't have a
// corresponding feature gate. This encourages nightly users to use feature gates when
// possible.
None if self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you => {
self.tcx.sess.span_warn(span, "skipping const checks");
return;
Expand All @@ -135,15 +152,47 @@ impl<'tcx> CheckConstVisitor<'tcx> {

let const_kind = self.const_kind
.expect("`const_check_violated` may only be called inside a const context");

let msg = format!("`{}` is not allowed in a `{}`", expr.name(), const_kind);
match expr {
| NonConstExpr::Match(hir::MatchSource::Normal)
| NonConstExpr::Match(hir::MatchSource::IfDesugar { .. })
| NonConstExpr::Match(hir::MatchSource::IfLetDesugar { .. })
=> feature_err(&self.tcx.sess.parse_sess, sym::const_if_match, span, &msg).emit(),

_ => span_err!(self.tcx.sess, span, E0744, "{}", msg),
let required_gates = required_gates.unwrap_or(&[]);
let missing_gates: Vec<_> = required_gates
.iter()
.copied()
.filter(|&g| !features.enabled(g))
.collect();

match missing_gates.as_slice() {
&[] => span_err!(self.tcx.sess, span, E0744, "{}", msg),

// If the user enabled `#![feature(const_loop)]` but not `#![feature(const_if_match)]`,
// explain why their `while` loop is being rejected.
&[gate @ sym::const_if_match] if required_gates.contains(&sym::const_loop) => {
feature_err(&self.tcx.sess.parse_sess, gate, span, &msg)
.note("`#![feature(const_loop)]` alone is not sufficient, \
since this loop expression contains an implicit conditional")
.emit();
}

&[missing_primary, ref missing_secondary @ ..] => {
let mut err = feature_err(&self.tcx.sess.parse_sess, missing_primary, span, &msg);

// If multiple feature gates would be required to enable this expression, include
// them as help messages. Don't emit a separate error for each missing feature gate.
//
// FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This
// is a pretty narrow case, however.
if nightly_options::is_nightly_build() {
for gate in missing_secondary {
let note = format!(
"add `#![feature({})]` to the crate attributes to enable",
gate,
);
err.help(&note);
}
}

err.emit();
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc_passes/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(slice_patterns)]

#![recursion_limit="256"]

Expand Down
18 changes: 9 additions & 9 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -883,15 +883,15 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
let mut result = String::new();

for attr in attrs {
if attr.check_name(sym::doc) {
if let Some(val) = attr.value_str() {
if attr.is_doc_comment() {
result.push_str(&strip_doc_comment_decoration(&val.as_str()));
} else {
result.push_str(&val.as_str());
}
result.push('\n');
} else if let Some(meta_list) = attr.meta_item_list() {
if let Some(val) = attr.doc_str() {
if attr.is_doc_comment() {
result.push_str(&strip_doc_comment_decoration(&val.as_str()));
} else {
result.push_str(&val.as_str());
}
result.push('\n');
} else if attr.check_name(sym::doc) {
if let Some(meta_list) = attr.meta_item_list() {
meta_list.into_iter()
.filter(|it| it.check_name(sym::include))
.filter_map(|it| it.meta_item_list().map(|l| l.to_owned()))
Expand Down
23 changes: 0 additions & 23 deletions src/librustc_target/spec/i686_unknown_dragonfly.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,6 @@ supported_targets! {
("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
("x86_64-unknown-freebsd", x86_64_unknown_freebsd),

("i686-unknown-dragonfly", i686_unknown_dragonfly),
("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),

("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
Expand Down
Loading