Auto merge of #65399 - Centril:rollup-6lzj0w5, r=Centril

Rollup of 7 pull requests

Successful merges:

 - #65215 (Add long error explanation for E0697)
 - #65292 (Print lifetimes with backticks)
 - #65362 (syntax: consolidate function parsing in item.rs)
 - #65363 (Remove implicit dependencies on syntax::pprust)
 - #65379 (refactor session::config::build_session_options_and_crate_config)
 - #65392 (Move `Nonterminal::to_tokenstream` to parser & don't rely directly on parser in lowering)
 - #65395 (Add some tests for fixed ICEs)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-10-14 10:00:51 +00:00
commit 446e5e57b6
152 changed files with 1454 additions and 1175 deletions

View file

@ -2005,6 +2005,24 @@ a (non-transparent) struct containing a single float, while `Grams` is a
transparent wrapper around a float. This can make a difference for the ABI.
"##,
E0697: r##"
A closure has been used as `static`.
Erroneous code example:
```compile_fail,E0697
fn main() {
static || {}; // used as `static`
}
```
Closures cannot be used as `static`. They "save" the environment,
and as such a static closure would save only a static environment
which would consist only of variables with a static lifetime. Given
this it would be better to use a proper function. The easiest fix
is to remove the `static` keyword.
"##,
E0698: r##"
When using generators (or async) all type variables must be bound so a
generator can be constructed.
@ -2191,7 +2209,6 @@ See [RFC 2091] for details on this and other limitations.
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
E0697, // closures cannot be static
// E0707, // multiple elided lifetimes used in arguments of `async fn`
E0708, // `async` non-`move` closures with parameters are not currently
// supported

View file

@ -70,7 +70,8 @@ use syntax::print::pprust;
use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
use syntax::symbol::{kw, sym, Symbol};
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::parse::token::{self, Token};
use syntax::parse::token::{self, Nonterminal, Token};
use syntax::parse::ParseSess;
use syntax::visit::{self, Visitor};
use syntax_pos::Span;
@ -86,6 +87,11 @@ pub struct LoweringContext<'a> {
resolver: &'a mut dyn Resolver,
/// HACK(Centril): there is a cyclic dependency between the parser and lowering
/// if we don't have this function pointer. To avoid that dependency so that
/// librustc is independent of the parser, we use dynamic dispatch here.
nt_to_tokenstream: NtToTokenstream,
/// The items being lowered are collected here.
items: BTreeMap<hir::HirId, hir::Item>,
@ -180,6 +186,8 @@ pub trait Resolver {
fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool;
}
type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
/// and if so, what meaning it has.
#[derive(Debug)]
@ -236,6 +244,7 @@ pub fn lower_crate(
dep_graph: &DepGraph,
krate: &Crate,
resolver: &mut dyn Resolver,
nt_to_tokenstream: NtToTokenstream,
) -> hir::Crate {
// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
@ -249,6 +258,7 @@ pub fn lower_crate(
sess,
cstore,
resolver,
nt_to_tokenstream,
items: BTreeMap::new(),
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
@ -1022,7 +1032,7 @@ impl<'a> LoweringContext<'a> {
fn lower_token(&mut self, token: Token) -> TokenStream {
match token.kind {
token::Interpolated(nt) => {
let tts = nt.to_tokenstream(&self.sess.parse_sess, token.span);
let tts = (self.nt_to_tokenstream)(&nt, &self.sess.parse_sess, token.span);
self.lower_token_stream(tts)
}
_ => TokenTree::Token(token).into(),

View file

@ -200,7 +200,7 @@ impl<'tcx> TyCtxt<'tcx> {
{
sp = param.span;
}
(format!("the lifetime {} as defined on", br.name), sp)
(format!("the lifetime `{}` as defined on", br.name), sp)
}
ty::ReFree(ty::FreeRegion {
bound_region: ty::BoundRegion::BrNamed(_, name),
@ -213,7 +213,7 @@ impl<'tcx> TyCtxt<'tcx> {
{
sp = param.span;
}
(format!("the lifetime {} as defined on", name), sp)
(format!("the lifetime `{}` as defined on", name), sp)
}
ty::ReFree(ref fr) => match fr.bound_region {
ty::BrAnon(idx) => (
@ -221,7 +221,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.hir().span(node),
),
_ => (
format!("the lifetime {} as defined on", region),
format!("the lifetime `{}` as defined on", region),
cm.def_span(self.hir().span(node)),
),
},

View file

@ -12,6 +12,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHa
use syntax::ast;
use syntax::attr;
use syntax::feature_gate;
use syntax::print::pprust;
use syntax::source_map::MultiSpan;
use syntax::symbol::{Symbol, sym};
@ -285,7 +286,7 @@ impl<'a> LintLevelsBuilder<'a> {
tool_ident.span,
E0710,
"an unknown tool name found in scoped lint: `{}`",
meta_item.path
pprust::path_to_string(&meta_item.path),
);
continue;
}

View file

@ -2038,11 +2038,7 @@ pub fn parse_error_format(
return error_format;
}
pub fn build_session_options_and_crate_config(
matches: &getopts::Matches,
) -> (Options, FxHashSet<(String, Option<String>)>) {
let color = parse_color(matches);
fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
let edition = match matches.opt_str("edition") {
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_|
early_error(
@ -2069,19 +2065,14 @@ pub fn build_session_options_and_crate_config(
)
}
let (json_rendered, json_artifact_notifications) = parse_json(matches);
let error_format = parse_error_format(matches, color, json_rendered);
let unparsed_crate_types = matches.opt_strs("crate-type");
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
.unwrap_or_else(|e| early_error(error_format, &e[..]));
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
let mut debugging_opts = build_debugging_options(matches, error_format);
edition
}
fn check_debug_option_stability(
debugging_opts: &DebuggingOptions,
error_format: ErrorOutputType,
json_rendered: HumanReadableErrorType,
) {
if !debugging_opts.unstable_options {
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
early_error(
@ -2097,7 +2088,13 @@ pub fn build_session_options_and_crate_config(
);
}
}
}
fn parse_output_types(
debugging_opts: &DebuggingOptions,
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> OutputTypes {
let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
@ -2122,14 +2119,19 @@ pub fn build_session_options_and_crate_config(
if output_types.is_empty() {
output_types.insert(OutputType::Exe, None);
}
OutputTypes(output_types)
}
let mut cg = build_codegen_options(matches, error_format);
let mut codegen_units = cg.codegen_units;
fn should_override_cgus_and_disable_thinlto(
output_types: &OutputTypes,
matches: &getopts::Matches,
error_format: ErrorOutputType,
mut codegen_units: Option<usize>,
) -> (bool, Option<usize>) {
let mut disable_thinlto = false;
// Issue #30063: if user requests LLVM-related output to one
// particular path, disable codegen-units.
let incompatible: Vec<_> = output_types
let incompatible: Vec<_> = output_types.0
.iter()
.map(|ot_path| ot_path.0)
.filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
@ -2161,6 +2163,17 @@ pub fn build_session_options_and_crate_config(
}
}
if codegen_units == Some(0) {
early_error(
error_format,
"value for codegen units must be a positive non-zero integer",
);
}
(disable_thinlto, codegen_units)
}
fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutputType) {
if debugging_opts.threads == 0 {
early_error(
error_format,
@ -2174,16 +2187,15 @@ pub fn build_session_options_and_crate_config(
"optimization fuel is incompatible with multiple threads",
);
}
}
if codegen_units == Some(0) {
early_error(
error_format,
"value for codegen units must be a positive non-zero integer",
);
}
let incremental = match (&debugging_opts.incremental, &cg.incremental) {
(&Some(ref path1), &Some(ref path2)) => {
fn select_incremental_path(
debugging_opts: &DebuggingOptions,
cg: &CodegenOptions,
error_format: ErrorOutputType,
) -> Option<PathBuf> {
match (&debugging_opts.incremental, &cg.incremental) {
(Some(path1), Some(path2)) => {
if path1 != path2 {
early_error(
error_format,
@ -2197,25 +2209,19 @@ pub fn build_session_options_and_crate_config(
Some(path1)
}
}
(&Some(ref path), &None) => Some(path),
(&None, &Some(ref path)) => Some(path),
(&None, &None) => None,
}.map(|m| PathBuf::from(m));
if debugging_opts.profile && incremental.is_some() {
early_error(
error_format,
"can't instrument with gcov profiling when compiling incrementally",
);
}
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
early_error(
error_format,
"options `-C profile-generate` and `-C profile-use` are exclusive",
);
}
(Some(path), None) => Some(path),
(None, Some(path)) => Some(path),
(None, None) => None,
}.map(|m| PathBuf::from(m))
}
fn collect_print_requests(
cg: &mut CodegenOptions,
dopts: &mut DebuggingOptions,
matches: &getopts::Matches,
is_unstable_enabled: bool,
error_format: ErrorOutputType,
) -> Vec<PrintRequest> {
let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::TargetCPUs);
@ -2233,72 +2239,105 @@ pub fn build_session_options_and_crate_config(
prints.push(PrintRequest::CodeModels);
cg.code_model = None;
}
if debugging_opts
if dopts
.tls_model
.as_ref()
.map_or(false, |s| s == "help")
{
prints.push(PrintRequest::TlsModels);
debugging_opts.tls_model = None;
dopts.tls_model = None;
}
let cg = cg;
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
"crate-name" => PrintRequest::CrateName,
"file-names" => PrintRequest::FileNames,
"sysroot" => PrintRequest::Sysroot,
"cfg" => PrintRequest::Cfg,
"target-list" => PrintRequest::TargetList,
"target-cpus" => PrintRequest::TargetCPUs,
"target-features" => PrintRequest::TargetFeatures,
"relocation-models" => PrintRequest::RelocationModels,
"code-models" => PrintRequest::CodeModels,
"tls-models" => PrintRequest::TlsModels,
"native-static-libs" => PrintRequest::NativeStaticLibs,
"target-spec-json" => {
if is_unstable_enabled {
PrintRequest::TargetSpec
} else {
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to \
enable the target-spec-json print option",
);
}
}
req => early_error(error_format, &format!("unknown print request `{}`", req)),
}));
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
let target_triple = if let Some(target) = matches.opt_str("target") {
if target.ends_with(".json") {
prints
}
fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType) -> TargetTriple {
match matches.opt_str("target") {
Some(target) if target.ends_with(".json") => {
let path = Path::new(&target);
TargetTriple::from_path(&path).unwrap_or_else(|_|
early_error(error_format, &format!("target file {:?} does not exist", path)))
} else {
TargetTriple::TargetTriple(target)
}
Some(target) => TargetTriple::TargetTriple(target),
_ => TargetTriple::from_triple(host_triple()),
}
}
fn parse_opt_level(
matches: &getopts::Matches,
cg: &CodegenOptions,
error_format: ErrorOutputType,
) -> OptLevel {
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
// to use them interchangeably. However, because they're technically different flags,
// we need to work out manually which should take precedence if both are supplied (i.e.
// the rightmost flag). We do this by finding the (rightmost) position of both flags and
// comparing them. Note that if a flag is not found, its position will be `None`, which
// always compared less than `Some(_)`.
let max_o = matches.opt_positions("O").into_iter().max();
let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| {
if let Some("opt-level") = s.splitn(2, '=').next() {
Some(i)
} else {
None
}
}).max();
if max_o > max_c {
OptLevel::Default
} else {
TargetTriple::from_triple(host_triple())
};
let opt_level = {
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
// to use them interchangeably. However, because they're technically different flags,
// we need to work out manually which should take precedence if both are supplied (i.e.
// the rightmost flag). We do this by finding the (rightmost) position of both flags and
// comparing them. Note that if a flag is not found, its position will be `None`, which
// always compared less than `Some(_)`.
let max_o = matches.opt_positions("O").into_iter().max();
let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| {
if let Some("opt-level") = s.splitn(2, '=').next() {
Some(i)
} else {
None
}
}).max();
if max_o > max_c {
OptLevel::Default
} else {
match cg.opt_level.as_ref().map(String::as_ref) {
None => OptLevel::No,
Some("0") => OptLevel::No,
Some("1") => OptLevel::Less,
Some("2") => OptLevel::Default,
Some("3") => OptLevel::Aggressive,
Some("s") => OptLevel::Size,
Some("z") => OptLevel::SizeMin,
Some(arg) => {
early_error(
error_format,
&format!(
"optimization level needs to be \
between 0-3, s or z (instead was `{}`)",
arg
),
);
}
match cg.opt_level.as_ref().map(String::as_ref) {
None => OptLevel::No,
Some("0") => OptLevel::No,
Some("1") => OptLevel::Less,
Some("2") => OptLevel::Default,
Some("3") => OptLevel::Aggressive,
Some("s") => OptLevel::Size,
Some("z") => OptLevel::SizeMin,
Some(arg) => {
early_error(
error_format,
&format!(
"optimization level needs to be \
between 0-3, s or z (instead was `{}`)",
arg
),
);
}
}
};
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
// for more details.
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
}
}
fn select_debuginfo(
matches: &getopts::Matches,
cg: &CodegenOptions,
error_format: ErrorOutputType,
) -> DebugInfo {
let max_g = matches.opt_positions("g").into_iter().max();
let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| {
if let Some("debuginfo") = s.splitn(2, '=').next() {
@ -2307,7 +2346,7 @@ pub fn build_session_options_and_crate_config(
None
}
}).max();
let debuginfo = if max_g > max_c {
if max_g > max_c {
DebugInfo::Full
} else {
match cg.debuginfo {
@ -2325,14 +2364,14 @@ pub fn build_session_options_and_crate_config(
);
}
}
};
let mut search_paths = vec![];
for s in &matches.opt_strs("L") {
search_paths.push(SearchPath::from_cli_opt(&s[..], error_format));
}
}
let libs = matches
fn parse_libs(
matches: &getopts::Matches,
error_format: ErrorOutputType,
) -> Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> {
matches
.opt_strs("l")
.into_iter()
.map(|s| {
@ -2371,52 +2410,23 @@ pub fn build_session_options_and_crate_config(
let new_name = name_parts.next();
(name.to_owned(), new_name.map(|n| n.to_owned()), kind)
})
.collect();
.collect()
}
let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
let test = matches.opt_present("test");
let is_unstable_enabled = nightly_options::is_unstable_enabled(matches);
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
"crate-name" => PrintRequest::CrateName,
"file-names" => PrintRequest::FileNames,
"sysroot" => PrintRequest::Sysroot,
"cfg" => PrintRequest::Cfg,
"target-list" => PrintRequest::TargetList,
"target-cpus" => PrintRequest::TargetCPUs,
"target-features" => PrintRequest::TargetFeatures,
"relocation-models" => PrintRequest::RelocationModels,
"code-models" => PrintRequest::CodeModels,
"tls-models" => PrintRequest::TlsModels,
"native-static-libs" => PrintRequest::NativeStaticLibs,
"target-spec-json" => {
if is_unstable_enabled {
PrintRequest::TargetSpec
} else {
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to \
enable the target-spec-json print option",
);
}
}
req => early_error(error_format, &format!("unknown print request `{}`", req)),
}));
let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) {
fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) -> BorrowckMode {
match dopts.borrowck.as_ref().map(|s| &s[..]) {
None | Some("migrate") => BorrowckMode::Migrate,
Some("mir") => BorrowckMode::Mir,
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
};
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
early_warn(
error_format,
"-C remark requires \"-C debuginfo=n\" to show source locations",
);
}
}
fn parse_externs(
matches: &getopts::Matches,
debugging_opts: &DebuggingOptions,
error_format: ErrorOutputType,
is_unstable_enabled: bool,
) -> Externs {
if matches.opt_present("extern-private") && !debugging_opts.unstable_options {
early_error(
ErrorOutputType::default(),
@ -2457,10 +2467,14 @@ pub fn build_session_options_and_crate_config(
// flag
entry.is_private_dep |= private;
}
Externs(externs)
}
let crate_name = matches.opt_str("crate-name");
let remap_path_prefix = matches
fn parse_remap_path_prefix(
matches: &getopts::Matches,
error_format: ErrorOutputType
) -> Vec<(PathBuf, PathBuf)> {
matches
.opt_strs("remap-path-prefix")
.into_iter()
.map(|remap| {
@ -2475,42 +2489,130 @@ pub fn build_session_options_and_crate_config(
),
}
})
.collect();
.collect()
}
(
Options {
crate_types,
optimize: opt_level,
debuginfo,
lint_opts,
lint_cap,
describe_lints,
output_types: OutputTypes(output_types),
search_paths,
maybe_sysroot: sysroot_opt,
target_triple,
test,
incremental,
debugging_opts,
prints,
borrowck_mode,
cg,
pub fn build_session_options(matches: &getopts::Matches) -> Options {
let color = parse_color(matches);
let edition = parse_crate_edition(matches);
let (json_rendered, json_artifact_notifications) = parse_json(matches);
let error_format = parse_error_format(matches, color, json_rendered);
let unparsed_crate_types = matches.opt_strs("crate-type");
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
.unwrap_or_else(|e| early_error(error_format, &e[..]));
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
let mut debugging_opts = build_debugging_options(matches, error_format);
check_debug_option_stability(&debugging_opts, error_format, json_rendered);
let output_types = parse_output_types(&debugging_opts, matches, error_format);
let mut cg = build_codegen_options(matches, error_format);
let (disable_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
&output_types,
matches,
error_format,
cg.codegen_units,
);
check_thread_count(&debugging_opts, error_format);
let incremental = select_incremental_path(&debugging_opts, &cg, error_format);
if debugging_opts.profile && incremental.is_some() {
early_error(
error_format,
externs: Externs(externs),
crate_name,
alt_std_name: None,
libs,
unstable_features: UnstableFeatures::from_environment(),
debug_assertions,
actually_rustdoc: false,
cli_forced_codegen_units: codegen_units,
cli_forced_thinlto_off: disable_thinlto,
remap_path_prefix,
edition,
json_artifact_notifications,
},
cfg,
)
"can't instrument with gcov profiling when compiling incrementally",
);
}
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
early_error(
error_format,
"options `-C profile-generate` and `-C profile-use` are exclusive",
);
}
let is_unstable_enabled = nightly_options::is_unstable_enabled(matches);
let prints = collect_print_requests(
&mut cg,
&mut debugging_opts,
matches,
is_unstable_enabled,
error_format,
);
let cg = cg;
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
let target_triple = parse_target_triple(matches, error_format);
let opt_level = parse_opt_level(matches, &cg, error_format);
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
// for more details.
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
let debuginfo = select_debuginfo(matches, &cg, error_format);
let mut search_paths = vec![];
for s in &matches.opt_strs("L") {
search_paths.push(SearchPath::from_cli_opt(&s[..], error_format));
}
let libs = parse_libs(matches, error_format);
let test = matches.opt_present("test");
let borrowck_mode = parse_borrowck_mode(&debugging_opts, error_format);
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
early_warn(
error_format,
"-C remark requires \"-C debuginfo=n\" to show source locations",
);
}
let externs = parse_externs(matches, &debugging_opts, error_format, is_unstable_enabled);
let crate_name = matches.opt_str("crate-name");
let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
Options {
crate_types,
optimize: opt_level,
debuginfo,
lint_opts,
lint_cap,
describe_lints,
output_types,
search_paths,
maybe_sysroot: sysroot_opt,
target_triple,
test,
incremental,
debugging_opts,
prints,
borrowck_mode,
cg,
error_format,
externs,
crate_name,
alt_std_name: None,
libs,
unstable_features: UnstableFeatures::from_environment(),
debug_assertions,
actually_rustdoc: false,
cli_forced_codegen_units: codegen_units,
cli_forced_thinlto_off: disable_thinlto,
remap_path_prefix,
edition,
json_artifact_notifications,
}
}
pub fn make_crate_type_option() -> RustcOptGroup {

View file

@ -3,8 +3,9 @@ use crate::lint;
use crate::middle::cstore;
use crate::session::config::{
build_configuration,
build_session_options_and_crate_config,
to_crate_config
build_session_options,
to_crate_config,
parse_cfgspecs,
};
use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry};
use crate::session::build_session;
@ -18,6 +19,16 @@ use syntax::symbol::sym;
use syntax::edition::{Edition, DEFAULT_EDITION};
use syntax;
use super::Options;
use rustc_data_structures::fx::FxHashSet;
pub fn build_session_options_and_crate_config(
matches: &getopts::Matches,
) -> (Options, FxHashSet<(String, Option<String>)>) {
(
build_session_options(matches),
parse_cfgspecs(matches.opt_strs("cfg")),
)
}
impl ExternEntry {
fn new_public<S: Into<String>,