Auto merge of #63779 - Centril:rollup-sx96dli, r=Centril
Rollup of 7 pull requests Successful merges: - #63721 (Do not emit JSON dumps of diagnostic codes) - #63753 (Bump toml dependency.) - #63755 (Use dedicated type for spans in pre-expansion gating.) - #63759 (Allow 'default async fn' to parse.) - #63760 (Update books) - #63762 (`async_await` was stabilized in 1.39.0, not 1.38.0.) - #63766 (Remove some duplication when resolving constants) Failed merges: r? @ghost
This commit is contained in:
commit
7b0085a613
24 changed files with 177 additions and 239 deletions
26
Cargo.lock
26
Cargo.lock
|
|
@ -185,7 +185,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"time",
|
||||
"toml 0.4.10",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -202,7 +202,7 @@ name = "build-manifest"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"toml 0.4.10",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -316,7 +316,7 @@ dependencies = [
|
|||
"tar",
|
||||
"tempfile",
|
||||
"termcolor",
|
||||
"toml 0.5.3",
|
||||
"toml",
|
||||
"unicode-width",
|
||||
"url 2.1.0",
|
||||
"walkdir",
|
||||
|
|
@ -442,7 +442,7 @@ dependencies = [
|
|||
"semver",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"toml 0.5.3",
|
||||
"toml",
|
||||
"unicode-normalization",
|
||||
"url 2.1.0",
|
||||
]
|
||||
|
|
@ -946,6 +946,7 @@ name = "error_index_generator"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustdoc",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1785,7 +1786,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"shlex",
|
||||
"tempfile",
|
||||
"toml 0.5.3",
|
||||
"toml",
|
||||
"toml-query",
|
||||
]
|
||||
|
||||
|
|
@ -2760,7 +2761,7 @@ dependencies = [
|
|||
"tokio",
|
||||
"tokio-process",
|
||||
"tokio-timer",
|
||||
"toml 0.5.3",
|
||||
"toml",
|
||||
"url 1.7.2",
|
||||
"walkdir",
|
||||
]
|
||||
|
|
@ -3590,7 +3591,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"structopt",
|
||||
"term 0.6.0",
|
||||
"toml 0.5.3",
|
||||
"toml",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
"unicode_categories",
|
||||
|
|
@ -4382,15 +4383,6 @@ dependencies = [
|
|||
"tokio-reactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.3"
|
||||
|
|
@ -4411,7 +4403,7 @@ dependencies = [
|
|||
"is-match",
|
||||
"lazy_static 1.3.0",
|
||||
"regex",
|
||||
"toml 0.5.3",
|
||||
"toml",
|
||||
"toml-query_derive",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ cc = "1.0.35"
|
|||
libc = "0.2"
|
||||
serde = { version = "1.0.8", features = ["derive"] }
|
||||
serde_json = "1.0.2"
|
||||
toml = "0.4"
|
||||
toml = "0.5"
|
||||
lazy_static = "1.3.0"
|
||||
time = "0.1"
|
||||
petgraph = "0.4.13"
|
||||
|
|
|
|||
|
|
@ -825,8 +825,7 @@ impl Step for ErrorIndex {
|
|||
index.arg(crate::channel::CFG_RELEASE_NUM);
|
||||
|
||||
// FIXME: shouldn't have to pass this env var
|
||||
index.env("CFG_BUILD", &builder.config.build)
|
||||
.env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir());
|
||||
index.env("CFG_BUILD", &builder.config.build);
|
||||
|
||||
builder.run(&mut index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1535,8 +1535,7 @@ impl Step for ErrorIndex {
|
|||
);
|
||||
tool.arg("markdown")
|
||||
.arg(&output)
|
||||
.env("CFG_BUILD", &builder.config.build)
|
||||
.env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir());
|
||||
.env("CFG_BUILD", &builder.config.build);
|
||||
|
||||
builder.info(&format!("Testing error-index stage{}", compiler.stage));
|
||||
let _time = util::timeit(&builder);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit c5da1e11915d3f28266168baaf55822f7e3fe999
|
||||
Subproject commit 432ca26686c11d396eed6a59499f93ce1bf2433c
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 8a7d05615e5bc0a7fb961b4919c44f5221ee54da
|
||||
Subproject commit 38b9a76bc8b59ac862663807fc51c9b757337fd6
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit b4b3536839042a6743fc76f0d9ad2a812020aeaa
|
||||
Subproject commit d191a0cdd3b92648e0f1e53b13140a14677cc65b
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f2c15ba5ee89ae9469a2cf60494977749901d764
|
||||
Subproject commit 580839d90aacd537f0293697096fa8355bc4e673
|
||||
|
|
@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
|
|||
use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::error::{ExpectedFound, TypeError};
|
||||
use crate::mir::interpret::{ConstValue, Scalar, GlobalId};
|
||||
use crate::mir::interpret::{ConstValue, Scalar};
|
||||
use std::rc::Rc;
|
||||
use std::iter;
|
||||
use rustc_target::spec::abi;
|
||||
|
|
@ -551,26 +551,8 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
|||
let tcx = relation.tcx();
|
||||
|
||||
let eagerly_eval = |x: &'tcx ty::Const<'tcx>| {
|
||||
if let ConstValue::Unevaluated(def_id, substs) = x.val {
|
||||
// FIXME(eddyb) get the right param_env.
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
if !substs.has_local_value() {
|
||||
let instance = ty::Instance::resolve(
|
||||
tcx.global_tcx(),
|
||||
param_env,
|
||||
def_id,
|
||||
substs,
|
||||
);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
if let Ok(ct) = tcx.const_eval(param_env.and(cid)) {
|
||||
return ct.val;
|
||||
}
|
||||
}
|
||||
}
|
||||
if !x.val.has_local_value() {
|
||||
return x.eval(tcx, relation.param_env()).val;
|
||||
}
|
||||
x.val
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2299,23 +2299,33 @@ impl<'tcx> Const<'tcx> {
|
|||
assert_eq!(self.ty, ty);
|
||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
||||
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
|
||||
self.eval(tcx, param_env).val.try_to_bits(size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn eval(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
) -> &Const<'tcx> {
|
||||
// FIXME(const_generics): this doesn't work right now,
|
||||
// because it tries to relate an `Infer` to a `Param`.
|
||||
match self.val {
|
||||
// FIXME(const_generics): this doesn't work right now,
|
||||
// because it tries to relate an `Infer` to a `Param`.
|
||||
ConstValue::Unevaluated(did, substs) => {
|
||||
// if `substs` has no unresolved components, use and empty param_env
|
||||
let (param_env, substs) = param_env.with_reveal_all().and(substs).into_parts();
|
||||
// try to resolve e.g. associated constants to their definition on an impl
|
||||
let instance = ty::Instance::resolve(tcx, param_env, did, substs)?;
|
||||
let instance = match ty::Instance::resolve(tcx, param_env, did, substs) {
|
||||
Some(instance) => instance,
|
||||
None => return self,
|
||||
};
|
||||
let gid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
let evaluated = tcx.const_eval(param_env.and(gid)).ok()?;
|
||||
evaluated.val.try_to_bits(size)
|
||||
tcx.const_eval(param_env.and(gid)).unwrap_or(self)
|
||||
},
|
||||
// otherwise just extract a `ConstValue`'s bits if possible
|
||||
_ => self.val.try_to_bits(size),
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
//! This module contains utilities for outputting metadata for diagnostic errors.
|
||||
//!
|
||||
//! Each set of errors is mapped to a metadata file by a name, which is
|
||||
//! currently always a crate name.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::env;
|
||||
use std::fs::{remove_file, create_dir_all, File};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::error::Error;
|
||||
use rustc_serialize::json::as_json;
|
||||
|
||||
use syntax_pos::{Span, FileName};
|
||||
|
||||
use crate::ext::base::ExtCtxt;
|
||||
use crate::diagnostics::plugin::{ErrorMap, ErrorInfo};
|
||||
|
||||
/// JSON encodable/decodable version of `ErrorInfo`.
|
||||
#[derive(PartialEq, RustcDecodable, RustcEncodable)]
|
||||
pub struct ErrorMetadata {
|
||||
pub description: Option<String>,
|
||||
pub use_site: Option<ErrorLocation>
|
||||
}
|
||||
|
||||
/// Mapping from error codes to metadata that can be (de)serialized.
|
||||
pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>;
|
||||
|
||||
/// JSON encodable error location type with filename and line number.
|
||||
#[derive(PartialEq, RustcDecodable, RustcEncodable)]
|
||||
pub struct ErrorLocation {
|
||||
pub filename: FileName,
|
||||
pub line: usize
|
||||
}
|
||||
|
||||
impl ErrorLocation {
|
||||
/// Creates an error location from a span.
|
||||
pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation {
|
||||
let loc = ecx.source_map().lookup_char_pos(sp.lo());
|
||||
ErrorLocation {
|
||||
filename: loc.file.name.clone(),
|
||||
line: loc.line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the directory where metadata for a given `prefix` should be stored.
|
||||
///
|
||||
/// See `output_metadata`.
|
||||
pub fn get_metadata_dir(prefix: &str) -> PathBuf {
|
||||
env::var_os("RUSTC_ERROR_METADATA_DST")
|
||||
.map(PathBuf::from)
|
||||
.expect("env var `RUSTC_ERROR_METADATA_DST` isn't set")
|
||||
.join(prefix)
|
||||
}
|
||||
|
||||
/// Map `name` to a path in the given directory: <directory>/<name>.json
|
||||
fn get_metadata_path(directory: PathBuf, name: &str) -> PathBuf {
|
||||
directory.join(format!("{}.json", name))
|
||||
}
|
||||
|
||||
/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `prefix/name`.
|
||||
///
|
||||
/// For our current purposes the prefix is the target architecture and the name is a crate name.
|
||||
/// If an error occurs steps will be taken to ensure that no file is created.
|
||||
pub fn output_metadata(ecx: &ExtCtxt<'_>, prefix: &str, name: &str, err_map: &ErrorMap)
|
||||
-> Result<(), Box<dyn Error>>
|
||||
{
|
||||
// Create the directory to place the file in.
|
||||
let metadata_dir = get_metadata_dir(prefix);
|
||||
create_dir_all(&metadata_dir)?;
|
||||
|
||||
// Open the metadata file.
|
||||
let metadata_path = get_metadata_path(metadata_dir, name);
|
||||
let mut metadata_file = File::create(&metadata_path)?;
|
||||
|
||||
// Construct a serializable map.
|
||||
let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| {
|
||||
let key = k.as_str().to_string();
|
||||
let value = ErrorMetadata {
|
||||
description: description.map(|n| n.as_str().to_string()),
|
||||
use_site: use_site.map(|sp| ErrorLocation::from_span(ecx, sp))
|
||||
};
|
||||
(key, value)
|
||||
}).collect::<ErrorMetadataMap>();
|
||||
|
||||
// Write the data to the file, deleting it if the write fails.
|
||||
let result = write!(&mut metadata_file, "{}", as_json(&json_map));
|
||||
if result.is_err() {
|
||||
remove_file(&metadata_path)?;
|
||||
}
|
||||
Ok(result?)
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::env;
|
||||
|
||||
use crate::ast::{self, Ident, Name};
|
||||
use crate::source_map;
|
||||
|
|
@ -12,8 +11,6 @@ use crate::tokenstream::{TokenTree};
|
|||
use smallvec::smallvec;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use crate::diagnostics::metadata::output_metadata;
|
||||
|
||||
pub use errors::*;
|
||||
|
||||
// Maximum width of any line in an extended error description (inclusive).
|
||||
|
|
@ -127,36 +124,13 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>,
|
|||
token_tree: &[TokenTree])
|
||||
-> Box<dyn MacResult+'cx> {
|
||||
assert_eq!(token_tree.len(), 3);
|
||||
let (crate_name, ident) = match (&token_tree[0], &token_tree[2]) {
|
||||
(
|
||||
// Crate name.
|
||||
&TokenTree::Token(Token { kind: token::Ident(crate_name, _), .. }),
|
||||
// DIAGNOSTICS ident.
|
||||
&TokenTree::Token(Token { kind: token::Ident(name, _), span })
|
||||
) => (crate_name, Ident::new(name, span)),
|
||||
let ident = match &token_tree[2] {
|
||||
// DIAGNOSTICS ident.
|
||||
&TokenTree::Token(Token { kind: token::Ident(name, _), span })
|
||||
=> Ident::new(name, span),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
// Output error metadata to `tmp/extended-errors/<target arch>/<crate name>.json`
|
||||
if let Ok(target_triple) = env::var("CFG_COMPILER_HOST_TRIPLE") {
|
||||
ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| {
|
||||
if let Err(e) = output_metadata(ecx,
|
||||
&target_triple,
|
||||
&crate_name.as_str(),
|
||||
diagnostics) {
|
||||
ecx.span_bug(span, &format!(
|
||||
"error writing metadata for triple `{}` and crate `{}`, error: {}, \
|
||||
cause: {:?}",
|
||||
target_triple, crate_name, e.description(), e.source()
|
||||
));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ecx.span_err(span, &format!(
|
||||
"failed to write metadata for crate `{}` because $CFG_COMPILER_HOST_TRIPLE is not set",
|
||||
crate_name));
|
||||
}
|
||||
|
||||
// Construct the output expression.
|
||||
let (count, expr) =
|
||||
ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| {
|
||||
|
|
|
|||
|
|
@ -855,7 +855,7 @@ declare_features! (
|
|||
// Allows `const _: TYPE = VALUE`.
|
||||
(accepted, underscore_const_names, "1.37.0", Some(54912), None),
|
||||
// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
|
||||
(accepted, async_await, "1.38.0", Some(50547), None),
|
||||
(accepted, async_await, "1.39.0", Some(50547), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: accepted features
|
||||
|
|
@ -2423,16 +2423,19 @@ pub fn check_crate(krate: &ast::Crate,
|
|||
};
|
||||
|
||||
macro_rules! gate_all {
|
||||
($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); };
|
||||
($spans:ident, $gate:ident, $msg:literal) => {
|
||||
for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); }
|
||||
for span in &*sess.gated_spans.$spans.borrow() {
|
||||
gate_feature!(&ctx, $gate, *span, $msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable");
|
||||
gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental");
|
||||
gate_all!(async_closure_spans, async_closure, "async closures are unstable");
|
||||
gate_all!(yield_spans, generators, "yield syntax is experimental");
|
||||
gate_all!(or_pattern_spans, or_patterns, "or-patterns syntax is experimental");
|
||||
gate_all!(param_attrs, "attributes on function parameters are unstable");
|
||||
gate_all!(let_chains, "`let` expressions in this position are experimental");
|
||||
gate_all!(async_closure, "async closures are unstable");
|
||||
gate_all!(yields, generators, "yield syntax is experimental");
|
||||
gate_all!(or_patterns, "or-patterns syntax is experimental");
|
||||
|
||||
let visitor = &mut PostExpansionVisitor {
|
||||
context: &ctx,
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ pub mod diagnostics {
|
|||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod plugin;
|
||||
pub mod metadata;
|
||||
}
|
||||
|
||||
// N.B., this module needs to be declared first so diagnostics are
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
|
|||
impl<'a> Parser<'a> {
|
||||
crate fn parse_arg_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
attrs.iter().for_each(|a|
|
||||
self.sess.param_attr_spans.borrow_mut().push(a.span)
|
||||
);
|
||||
self.sess.gated_spans.param_attrs.borrow_mut()
|
||||
.extend(attrs.iter().map(|a| a.span));
|
||||
Ok(attrs)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,22 @@ crate mod unescape_error_reporting;
|
|||
|
||||
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
|
||||
|
||||
/// Collected spans during parsing for places where a certain feature was
|
||||
/// used and should be feature gated accordingly in `check_crate`.
|
||||
#[derive(Default)]
|
||||
pub struct GatedSpans {
|
||||
/// Spans collected for gating `param_attrs`, e.g. `fn foo(#[attr] x: u8) {}`.
|
||||
pub param_attrs: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`.
|
||||
pub let_chains: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `async_closure`, e.g. `async || ..`.
|
||||
pub async_closure: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `yield e?` expressions (`generators` gate).
|
||||
pub yields: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`.
|
||||
pub or_patterns: Lock<Vec<Span>>,
|
||||
}
|
||||
|
||||
/// Info about a parsing session.
|
||||
pub struct ParseSess {
|
||||
pub span_diagnostic: Handler,
|
||||
|
|
@ -58,16 +74,8 @@ pub struct ParseSess {
|
|||
/// operation token that followed it, but that the parser cannot identify without further
|
||||
/// analysis.
|
||||
pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
|
||||
pub param_attr_spans: Lock<Vec<Span>>,
|
||||
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
|
||||
pub let_chains_spans: Lock<Vec<Span>>,
|
||||
// Places where `async || ..` exprs were used and should be feature gated.
|
||||
pub async_closure_spans: Lock<Vec<Span>>,
|
||||
// Places where `yield e?` exprs were used and should be feature gated.
|
||||
pub yield_spans: Lock<Vec<Span>>,
|
||||
pub injected_crate_name: Once<Symbol>,
|
||||
// Places where or-patterns e.g. `Some(Foo | Bar)` were used and should be feature gated.
|
||||
pub or_pattern_spans: Lock<Vec<Span>>,
|
||||
pub gated_spans: GatedSpans,
|
||||
}
|
||||
|
||||
impl ParseSess {
|
||||
|
|
@ -93,12 +101,8 @@ impl ParseSess {
|
|||
buffered_lints: Lock::new(vec![]),
|
||||
edition: ExpnId::root().expn_data().edition,
|
||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||
param_attr_spans: Lock::new(Vec::new()),
|
||||
let_chains_spans: Lock::new(Vec::new()),
|
||||
async_closure_spans: Lock::new(Vec::new()),
|
||||
yield_spans: Lock::new(Vec::new()),
|
||||
injected_crate_name: Once::new(),
|
||||
or_pattern_spans: Lock::new(Vec::new()),
|
||||
gated_spans: GatedSpans::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -999,7 +999,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
let span = lo.to(hi);
|
||||
self.sess.yield_spans.borrow_mut().push(span);
|
||||
self.sess.gated_spans.yields.borrow_mut().push(span);
|
||||
} else if self.eat_keyword(kw::Let) {
|
||||
return self.parse_let_expr(attrs);
|
||||
} else if is_span_rust_2018 && self.eat_keyword(kw::Await) {
|
||||
|
|
@ -1111,7 +1111,7 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
if asyncness.is_async() {
|
||||
// Feature gate `async ||` closures.
|
||||
self.sess.async_closure_spans.borrow_mut().push(self.prev_span);
|
||||
self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span);
|
||||
}
|
||||
|
||||
let capture_clause = self.parse_capture_clause();
|
||||
|
|
@ -1234,7 +1234,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if let ExprKind::Let(..) = cond.node {
|
||||
// Remove the last feature gating of a `let` expression since it's stable.
|
||||
let last = self.sess.let_chains_spans.borrow_mut().pop();
|
||||
let last = self.sess.gated_spans.let_chains.borrow_mut().pop();
|
||||
debug_assert_eq!(cond.span, last.unwrap());
|
||||
}
|
||||
|
||||
|
|
@ -1252,7 +1252,7 @@ impl<'a> Parser<'a> {
|
|||
|this| this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
|
||||
)?;
|
||||
let span = lo.to(expr.span);
|
||||
self.sess.let_chains_spans.borrow_mut().push(span);
|
||||
self.sess.gated_spans.let_chains.borrow_mut().push(span);
|
||||
Ok(self.mk_expr(span, ExprKind::Let(pats, expr), attrs))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -825,6 +825,7 @@ impl<'a> Parser<'a> {
|
|||
self.is_keyword_ahead(1, &[
|
||||
kw::Impl,
|
||||
kw::Const,
|
||||
kw::Async,
|
||||
kw::Fn,
|
||||
kw::Unsafe,
|
||||
kw::Extern,
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let or_pattern_span = lo.to(self.prev_span);
|
||||
|
||||
self.sess.or_pattern_spans.borrow_mut().push(or_pattern_span);
|
||||
self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span);
|
||||
|
||||
Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
|
||||
}
|
||||
|
|
|
|||
14
src/test/ui/specialization/issue-63716-parse-async.rs
Normal file
14
src/test/ui/specialization/issue-63716-parse-async.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Ensure that `default async fn` will parse.
|
||||
// See issue #63716 for details.
|
||||
|
||||
// check-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(specialization)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
impl Foo for Bar {
|
||||
default async fn baz() {}
|
||||
}
|
||||
|
|
@ -5,5 +5,5 @@ authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
toml = "0.4"
|
||||
toml = "0.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@ authors = ["The Rust Project Developers"]
|
|||
name = "error_index_generator"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
rustdoc = { path = "../../librustdoc" }
|
||||
|
||||
[build-dependencies]
|
||||
walkdir = "2"
|
||||
|
||||
[[bin]]
|
||||
name = "error_index_generator"
|
||||
path = "main.rs"
|
||||
|
|
|
|||
64
src/tools/error_index_generator/build.rs
Normal file
64
src/tools/error_index_generator/build.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use walkdir::WalkDir;
|
||||
use std::path::PathBuf;
|
||||
use std::{env, fs};
|
||||
|
||||
fn main() {
|
||||
// The src directory (we are in src/tools/error_index_generator)
|
||||
// Note that we could skip one of the .. but this ensures we at least loosely find the right
|
||||
// directory.
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
let dest = out_dir.join("error_codes.rs");
|
||||
let mut idx = 0;
|
||||
for entry in WalkDir::new("../../../src") {
|
||||
let entry = entry.unwrap();
|
||||
if entry.file_name() == "error_codes.rs" {
|
||||
println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap());
|
||||
let file = fs::read_to_string(entry.path()).unwrap()
|
||||
.replace("use syntax::{register_diagnostics, register_long_diagnostics};", "")
|
||||
.replace("use syntax::register_diagnostics;", "")
|
||||
.replace("use syntax::register_long_diagnostics;", "");
|
||||
let contents = format!("(|| {{\n{}\n}})();", file);
|
||||
|
||||
fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap();
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut all = String::new();
|
||||
all.push_str("fn register_all() -> Vec<(&'static str, Option<&'static str>)> {\n");
|
||||
all.push_str("let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();\n");
|
||||
all.push_str(r#"
|
||||
macro_rules! register_diagnostics {
|
||||
($($code:tt),*) => {{
|
||||
long_codes.extend([$(
|
||||
stringify!($code),
|
||||
)*].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());
|
||||
}};
|
||||
($($code:tt),*,) => {{
|
||||
long_codes.extend([$(
|
||||
stringify!($code),
|
||||
)*].iter().cloned().map(|s| (s, None)));
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! register_long_diagnostics {
|
||||
($($code:tt: $description:tt),*) => {
|
||||
{long_codes.extend([$(
|
||||
(stringify!($code), Some(stringify!($description))),
|
||||
)*].iter());}
|
||||
};
|
||||
($($code:tt: $description:tt),*,) => {
|
||||
{long_codes.extend([$(
|
||||
(stringify!($code), Some(stringify!($description))),
|
||||
)*].iter());}
|
||||
}
|
||||
}"#);
|
||||
for idx in 0..idx {
|
||||
all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx));
|
||||
}
|
||||
all.push_str("\nlong_codes\n");
|
||||
all.push_str("}\n");
|
||||
|
||||
fs::write(&dest, all).unwrap();
|
||||
}
|
||||
|
|
@ -2,22 +2,26 @@
|
|||
|
||||
extern crate env_logger;
|
||||
extern crate syntax;
|
||||
extern crate serialize as rustc_serialize;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fs::{self, read_dir, File};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use syntax::edition::DEFAULT_EDITION;
|
||||
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
|
||||
|
||||
use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, Playground};
|
||||
use rustc_serialize::json;
|
||||
|
||||
pub struct ErrorMetadata {
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
/// Mapping from error codes to metadata that can be (de)serialized.
|
||||
pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>;
|
||||
|
||||
enum OutputFormat {
|
||||
HTML(HTMLFormatter),
|
||||
|
|
@ -80,11 +84,7 @@ impl Formatter for HTMLFormatter {
|
|||
Some(_) => "error-described",
|
||||
None => "error-undescribed",
|
||||
};
|
||||
let use_desc = match info.use_site {
|
||||
Some(_) => "error-used",
|
||||
None => "error-unused",
|
||||
};
|
||||
write!(output, "<div class=\"{} {}\">", desc_desc, use_desc)?;
|
||||
write!(output, "<div class=\"{}\">", desc_desc)?;
|
||||
|
||||
// Error title (with self-link).
|
||||
write!(output,
|
||||
|
|
@ -199,25 +199,6 @@ impl Formatter for MarkdownFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
/// Loads all the metadata files from `metadata_dir` into an in-memory map.
|
||||
fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<dyn Error>> {
|
||||
let mut all_errors = BTreeMap::new();
|
||||
|
||||
for entry in read_dir(metadata_dir)? {
|
||||
let path = entry?.path();
|
||||
|
||||
let metadata_str = fs::read_to_string(&path)?;
|
||||
|
||||
let some_errors: ErrorMetadataMap = json::decode(&metadata_str)?;
|
||||
|
||||
for (err_code, info) in some_errors {
|
||||
all_errors.insert(err_code, info);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_errors)
|
||||
}
|
||||
|
||||
/// Output an HTML page for the errors in `err_map` to `output_path`.
|
||||
fn render_error_page<T: Formatter>(err_map: &ErrorMetadataMap, output_path: &Path,
|
||||
formatter: T) -> Result<(), Box<dyn Error>> {
|
||||
|
|
@ -234,9 +215,13 @@ fn render_error_page<T: Formatter>(err_map: &ErrorMetadataMap, output_path: &Pat
|
|||
}
|
||||
|
||||
fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
|
||||
let build_arch = env::var("CFG_BUILD")?;
|
||||
let metadata_dir = get_metadata_dir(&build_arch);
|
||||
let err_map = load_all_errors(&metadata_dir)?;
|
||||
let long_codes = register_all();
|
||||
let mut err_map = BTreeMap::new();
|
||||
for (code, desc) in long_codes {
|
||||
err_map.insert(code.to_string(), ErrorMetadata {
|
||||
description: desc.map(String::from),
|
||||
});
|
||||
}
|
||||
match format {
|
||||
OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
|
||||
OutputFormat::HTML(h) => render_error_page(&err_map, dst, h)?,
|
||||
|
|
@ -272,3 +257,5 @@ fn main() {
|
|||
panic!("{}", e.description());
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/error_codes.rs"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue