"serde",
"serde_json",
"time",
- "toml 0.4.10",
+ "toml",
]
[[package]]
version = "0.1.0"
dependencies = [
"serde",
- "toml 0.4.10",
+ "toml",
]
[[package]]
"tar",
"tempfile",
"termcolor",
- "toml 0.5.3",
+ "toml",
"unicode-width",
"url 2.1.0",
"walkdir",
"semver",
"serde",
"smallvec",
- "toml 0.5.3",
+ "toml",
"unicode-normalization",
"url 2.1.0",
]
version = "0.0.0"
dependencies = [
"rustdoc",
+ "walkdir",
]
[[package]]
"serde_json",
"shlex",
"tempfile",
- "toml 0.5.3",
+ "toml",
"toml-query",
]
"tokio",
"tokio-process",
"tokio-timer",
- "toml 0.5.3",
+ "toml",
"url 1.7.2",
"walkdir",
]
"serde_json",
"structopt",
"term 0.6.0",
- "toml 0.5.3",
+ "toml",
"unicode-segmentation",
"unicode-width",
"unicode_categories",
"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"
"is-match",
"lazy_static 1.3.0",
"regex",
- "toml 0.5.3",
+ "toml",
"toml-query_derive",
]
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"
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);
}
);
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);
-Subproject commit c5da1e11915d3f28266168baaf55822f7e3fe999
+Subproject commit 432ca26686c11d396eed6a59499f93ce1bf2433c
-Subproject commit 8a7d05615e5bc0a7fb961b4919c44f5221ee54da
+Subproject commit 38b9a76bc8b59ac862663807fc51c9b757337fd6
-Subproject commit b4b3536839042a6743fc76f0d9ad2a812020aeaa
+Subproject commit d191a0cdd3b92648e0f1e53b13140a14677cc65b
-Subproject commit f2c15ba5ee89ae9469a2cf60494977749901d764
+Subproject commit 580839d90aacd537f0293697096fa8355bc4e673
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;
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
};
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,
}
}
+++ /dev/null
-//! 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?)
-}
use std::collections::BTreeMap;
-use std::env;
use crate::ast::{self, Ident, Name};
use crate::source_map;
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).
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| {
// 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
};
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,
#[macro_use]
pub mod macros;
pub mod plugin;
- pub mod metadata;
}
// N.B., this module needs to be declared first so diagnostics are
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)
}
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,
/// 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 {
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(),
}
}
}
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) {
};
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();
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());
}
|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))
}
self.is_keyword_ahead(1, &[
kw::Impl,
kw::Const,
+ kw::Async,
kw::Fn,
kw::Unsafe,
kw::Extern,
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)))
}
--- /dev/null
+// 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() {}
+}
edition = "2018"
[dependencies]
-toml = "0.4"
+toml = "0.5"
serde = { version = "1.0", features = ["derive"] }
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"
--- /dev/null
+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();
+}
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),
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,
}
}
-/// 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>> {
}
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)?,
panic!("{}", e.description());
}
}
+
+include!(concat!(env!("OUT_DIR"), "/error_codes.rs"));