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:
commit
446e5e57b6
152 changed files with 1454 additions and 1175 deletions
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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)),
|
||||
),
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,30 +2239,61 @@ 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)
|
||||
}
|
||||
} else {
|
||||
TargetTriple::from_triple(host_triple())
|
||||
};
|
||||
let opt_level = {
|
||||
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.
|
||||
|
@ -2294,11 +2331,13 @@ pub fn build_session_options_and_crate_config(
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// 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,9 +2489,99 @@ pub fn build_session_options_and_crate_config(
|
|||
),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
.collect()
|
||||
}
|
||||
|
||||
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,
|
||||
"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,
|
||||
|
@ -2485,7 +2589,7 @@ pub fn build_session_options_and_crate_config(
|
|||
lint_opts,
|
||||
lint_cap,
|
||||
describe_lints,
|
||||
output_types: OutputTypes(output_types),
|
||||
output_types,
|
||||
search_paths,
|
||||
maybe_sysroot: sysroot_opt,
|
||||
target_triple,
|
||||
|
@ -2496,7 +2600,7 @@ pub fn build_session_options_and_crate_config(
|
|||
borrowck_mode,
|
||||
cg,
|
||||
error_format,
|
||||
externs: Externs(externs),
|
||||
externs,
|
||||
crate_name,
|
||||
alt_std_name: None,
|
||||
libs,
|
||||
|
@ -2508,9 +2612,7 @@ pub fn build_session_options_and_crate_config(
|
|||
remap_path_prefix,
|
||||
edition,
|
||||
json_artifact_notifications,
|
||||
},
|
||||
cfg,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_crate_type_option() -> RustcOptGroup {
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -166,7 +166,8 @@ pub fn run_compiler(
|
|||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
|
||||
let sopts = config::build_session_options(&matches);
|
||||
let cfg = config::parse_cfgspecs(matches.opt_strs("cfg"));
|
||||
|
||||
let mut dummy_config = |sopts, cfg, diagnostic_output| {
|
||||
let mut config = interface::Config {
|
||||
|
|
|
@ -541,7 +541,8 @@ pub fn lower_to_hir(
|
|||
) -> Result<hir::map::Forest> {
|
||||
// Lower AST to HIR.
|
||||
let hir_forest = time(sess, "lowering AST -> HIR", || {
|
||||
let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver);
|
||||
let nt_to_tokenstream = syntax::parse::nt_to_tokenstream;
|
||||
let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, nt_to_tokenstream);
|
||||
|
||||
if sess.opts.debugging_opts.hir_stats {
|
||||
hir_stats::print_hir_stats(&hir_crate);
|
||||
|
|
|
@ -45,7 +45,7 @@ use syntax::feature_gate::{Stability, deprecated_attributes};
|
|||
use syntax_pos::{BytePos, Span};
|
||||
use syntax::symbol::{Symbol, kw, sym};
|
||||
use syntax::errors::{Applicability, DiagnosticBuilder};
|
||||
use syntax::print::pprust::expr_to_string;
|
||||
use syntax::print::pprust::{self, expr_to_string};
|
||||
use syntax::visit::FnKind;
|
||||
|
||||
use rustc::hir::{self, GenericParamKind, PatKind};
|
||||
|
@ -701,7 +701,8 @@ impl EarlyLintPass for DeprecatedAttr {
|
|||
}
|
||||
}
|
||||
if attr.check_name(sym::no_start) || attr.check_name(sym::crate_id) {
|
||||
let msg = format!("use of deprecated attribute `{}`: no longer used.", attr.path);
|
||||
let path_str = pprust::path_to_string(&attr.path);
|
||||
let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str);
|
||||
lint_deprecated_attr(cx, attr, &msg, None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use syntax::ast::{self, MetaItem};
|
||||
use syntax::print::pprust;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
|
||||
use rustc_index::bit_set::{BitSet, HybridBitSet};
|
||||
|
@ -159,9 +160,8 @@ where
|
|||
if let Some(s) = item.value_str() {
|
||||
return Some(s.to_string())
|
||||
} else {
|
||||
sess.span_err(
|
||||
item.span,
|
||||
&format!("{} attribute requires a path", item.path));
|
||||
let path = pprust::path_to_string(&item.path);
|
||||
sess.span_err(item.span, &format!("{} attribute requires a path", path));
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,7 +263,8 @@ impl<'a> AstValidator<'a> {
|
|||
let mut err = self.err_handler().struct_span_err(poly.span,
|
||||
&format!("`?Trait` is not permitted in {}", where_));
|
||||
if is_trait {
|
||||
err.note(&format!("traits are `?{}` by default", poly.trait_ref.path));
|
||||
let path_str = pprust::path_to_string(&poly.trait_ref.path);
|
||||
err.note(&format!("traits are `?{}` by default", path_str));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ use syntax::ext::expand::AstFragment;
|
|||
use syntax::ext::hygiene::ExpnId;
|
||||
use syntax::feature_gate::is_builtin_attr;
|
||||
use syntax::parse::token::{self, Token};
|
||||
use syntax::print::pprust;
|
||||
use syntax::{span_err, struct_span_err};
|
||||
use syntax::source_map::{respan, Spanned};
|
||||
use syntax::symbol::{kw, sym};
|
||||
|
@ -228,7 +229,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
.span_suggestion(
|
||||
path.span,
|
||||
"try",
|
||||
format!("crate::{}", path),
|
||||
format!("crate::{}", pprust::path_to_string(&path)),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
|
|
|
@ -38,6 +38,7 @@ use rustc_metadata::cstore::CStore;
|
|||
use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
|
||||
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
|
||||
use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
|
||||
use syntax::print::pprust;
|
||||
use syntax::symbol::{kw, sym};
|
||||
|
||||
use syntax::visit::{self, Visitor};
|
||||
|
@ -2011,13 +2012,13 @@ impl<'a> Resolver<'a> {
|
|||
let mut candidates =
|
||||
self.lookup_import_candidates(ident, TypeNS, is_mod);
|
||||
candidates.sort_by_cached_key(|c| {
|
||||
(c.path.segments.len(), c.path.to_string())
|
||||
(c.path.segments.len(), pprust::path_to_string(&c.path))
|
||||
});
|
||||
if let Some(candidate) = candidates.get(0) {
|
||||
(
|
||||
String::from("unresolved import"),
|
||||
Some((
|
||||
vec![(ident.span, candidate.path.to_string())],
|
||||
vec![(ident.span, pprust::path_to_string(&candidate.path))],
|
||||
String::from("a similar path exists"),
|
||||
Applicability::MaybeIncorrect,
|
||||
)),
|
||||
|
|
|
@ -21,6 +21,7 @@ use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind};
|
|||
use syntax::ext::compile_declarative_macro;
|
||||
use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
|
||||
use syntax::feature_gate::GateIssue;
|
||||
use syntax::print::pprust;
|
||||
use syntax::symbol::{Symbol, kw, sym};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
|
@ -324,7 +325,8 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
Ok(if ext.macro_kind() != kind {
|
||||
let expected = kind.descr_expected();
|
||||
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
|
||||
let path_str = pprust::path_to_string(path);
|
||||
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
|
||||
self.session.struct_span_err(path.span, &msg)
|
||||
.span_label(path.span, format!("not {} {}", kind.article(), expected))
|
||||
.emit();
|
||||
|
@ -805,14 +807,16 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
if let Some(depr) = &stability.rustc_depr {
|
||||
let (message, lint) = stability::rustc_deprecation_message(depr, &path.to_string());
|
||||
let path = pprust::path_to_string(path);
|
||||
let (message, lint) = stability::rustc_deprecation_message(depr, &path);
|
||||
stability::early_report_deprecation(
|
||||
self.session, &message, depr.suggestion, lint, span
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(depr) = &ext.deprecation {
|
||||
let (message, lint) = stability::deprecation_message(depr, &path.to_string());
|
||||
let path = pprust::path_to_string(&path);
|
||||
let (message, lint) = stability::deprecation_message(depr, &path);
|
||||
stability::early_report_deprecation(self.session, &message, None, lint, span);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ use serialize::json::{ToJson, Json, as_json};
|
|||
use syntax::ast;
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::print::pprust;
|
||||
use syntax::source_map::FileName;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
|
@ -2957,7 +2958,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
|
|||
}
|
||||
|
||||
fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
|
||||
let path = attr.path.to_string();
|
||||
let path = pprust::path_to_string(&attr.path);
|
||||
|
||||
if attr.is_word() {
|
||||
Some(path)
|
||||
|
|
|
@ -7,7 +7,6 @@ pub use crate::util::parser::ExprPrecedence;
|
|||
|
||||
use crate::ext::hygiene::ExpnId;
|
||||
use crate::parse::token::{self, DelimToken};
|
||||
use crate::print::pprust;
|
||||
use crate::ptr::P;
|
||||
use crate::source_map::{dummy_spanned, respan, Spanned};
|
||||
use crate::symbol::{kw, sym, Symbol};
|
||||
|
@ -70,7 +69,7 @@ impl fmt::Display for Lifetime {
|
|||
/// along with a bunch of supporting information.
|
||||
///
|
||||
/// E.g., `std::cmp::PartialEq`.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Path {
|
||||
pub span: Span,
|
||||
/// The segments in the path: the things separated by `::`.
|
||||
|
@ -86,18 +85,6 @@ impl PartialEq<Symbol> for Path {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Path {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "path({})", pprust::path_to_string(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Path {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", pprust::path_to_string(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
// Convert a span and an identifier to the corresponding
|
||||
// one-segment path.
|
||||
|
@ -507,19 +494,13 @@ pub struct Block {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Pat {
|
||||
pub id: NodeId,
|
||||
pub kind: PatKind,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Pat {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Pat {
|
||||
/// Attempt reparsing the pattern as a type.
|
||||
/// This is intended for use by diagnostics.
|
||||
|
@ -831,7 +812,7 @@ impl UnOp {
|
|||
}
|
||||
|
||||
/// A statement
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Stmt {
|
||||
pub id: NodeId,
|
||||
pub kind: StmtKind,
|
||||
|
@ -865,18 +846,7 @@ impl Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Stmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"stmt({}: {})",
|
||||
self.id.to_string(),
|
||||
pprust::stmt_to_string(self)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum StmtKind {
|
||||
/// A local (let) binding.
|
||||
Local(P<Local>),
|
||||
|
@ -973,7 +943,7 @@ pub struct AnonConst {
|
|||
}
|
||||
|
||||
/// An expression.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Expr {
|
||||
pub id: NodeId,
|
||||
pub kind: ExprKind,
|
||||
|
@ -1100,12 +1070,6 @@ impl Expr {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Expr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self))
|
||||
}
|
||||
}
|
||||
|
||||
/// Limit types of a range (inclusive or exclusive)
|
||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum RangeLimits {
|
||||
|
@ -1660,19 +1624,13 @@ pub enum AssocTyConstraintKind {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Ty {
|
||||
pub id: NodeId,
|
||||
pub kind: TyKind,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Ty {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "type({})", pprust::ty_to_string(self))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct BareFnTy {
|
||||
pub unsafety: Unsafety,
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::early_buffered_lints::BufferedEarlyLintId;
|
|||
use crate::ext::base::ExtCtxt;
|
||||
use crate::feature_gate::{Features, GatedCfg};
|
||||
use crate::parse::ParseSess;
|
||||
use crate::print::pprust;
|
||||
|
||||
use errors::{Applicability, Handler};
|
||||
use syntax_pos::hygiene::Transparency;
|
||||
|
@ -243,7 +244,11 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
let meta = meta.as_ref().unwrap();
|
||||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(sess, meta.span, AttrError::MultipleItem(meta.path.to_string()));
|
||||
handle_errors(
|
||||
sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
|
@ -271,7 +276,10 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
handle_errors(
|
||||
sess,
|
||||
mi.span,
|
||||
AttrError::UnknownMetaItem(mi.path.to_string(), expected),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
expected,
|
||||
),
|
||||
);
|
||||
continue 'outer
|
||||
}
|
||||
|
@ -362,7 +370,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
mi.path.to_string(),
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "reason", "issue", "soft"]
|
||||
),
|
||||
);
|
||||
|
@ -434,7 +442,8 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||
sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
mi.path.to_string(), &["since", "note"],
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["since", "note"],
|
||||
),
|
||||
);
|
||||
continue 'outer
|
||||
|
@ -597,8 +606,11 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
|
|||
!eval_condition(mis[0].meta_item().unwrap(), sess, eval)
|
||||
},
|
||||
_ => {
|
||||
span_err!(sess.span_diagnostic, cfg.span, E0537,
|
||||
"invalid predicate `{}`", cfg.path);
|
||||
span_err!(
|
||||
sess.span_diagnostic, cfg.span, E0537,
|
||||
"invalid predicate `{}`",
|
||||
pprust::path_to_string(&cfg.path)
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +665,9 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess,
|
|||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
sess, meta.span, AttrError::MultipleItem(meta.path.to_string())
|
||||
sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false
|
||||
}
|
||||
|
@ -691,8 +705,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess,
|
|||
handle_errors(
|
||||
sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(mi.path.to_string(),
|
||||
&["since", "note"]),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["since", "note"],
|
||||
),
|
||||
);
|
||||
continue 'outer
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use crate::mut_visit::*;
|
|||
use crate::parse::{DirectoryOwnership, PResult, ParseSess};
|
||||
use crate::parse::token;
|
||||
use crate::parse::parser::Parser;
|
||||
use crate::print::pprust;
|
||||
use crate::ptr::P;
|
||||
use crate::symbol::{sym, Symbol};
|
||||
use crate::tokenstream::{TokenStream, TokenTree};
|
||||
|
@ -388,7 +389,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
"`derive` may only be applied to structs, enums and unions");
|
||||
if let ast::AttrStyle::Inner = attr.style {
|
||||
let trait_list = derives.iter()
|
||||
.map(|t| t.to_string()).collect::<Vec<_>>();
|
||||
.map(|t| pprust::path_to_string(t))
|
||||
.collect::<Vec<_>>();
|
||||
let suggestion = format!("#[derive({})]", trait_list.join(", "));
|
||||
err.span_suggestion(
|
||||
span, "try an outer attribute", suggestion,
|
||||
|
@ -587,8 +589,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
let result = if let Some(result) = fragment_kind.make_from(tok_result) {
|
||||
result
|
||||
} else {
|
||||
let msg = format!("non-{kind} macro in {kind} position: {path}",
|
||||
kind = fragment_kind.name(), path = mac.path);
|
||||
let msg = format!(
|
||||
"non-{kind} macro in {kind} position: {path}",
|
||||
kind = fragment_kind.name(),
|
||||
path = pprust::path_to_string(&mac.path),
|
||||
);
|
||||
self.cx.span_err(span, &msg);
|
||||
self.cx.trace_macros_diag();
|
||||
fragment_kind.dummy(span)
|
||||
|
@ -878,7 +883,7 @@ impl<'a> Parser<'a> {
|
|||
err.span_label(span, "caused by the macro expansion here");
|
||||
let msg = format!(
|
||||
"the usage of `{}!` is likely invalid in {} context",
|
||||
macro_path,
|
||||
pprust::path_to_string(¯o_path),
|
||||
kind_name,
|
||||
);
|
||||
err.note(&msg);
|
||||
|
|
|
@ -174,7 +174,8 @@ fn generic_extension<'cx>(
|
|||
rhses: &[mbe::TokenTree],
|
||||
) -> Box<dyn MacResult + 'cx> {
|
||||
if cx.trace_macros() {
|
||||
trace_macros_note(cx, sp, format!("expanding `{}! {{ {} }}`", name, arg));
|
||||
let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone()));
|
||||
trace_macros_note(cx, sp, msg);
|
||||
}
|
||||
|
||||
// Which arm's failure should we report? (the one furthest along)
|
||||
|
@ -212,7 +213,8 @@ fn generic_extension<'cx>(
|
|||
}
|
||||
|
||||
if cx.trace_macros() {
|
||||
trace_macros_note(cx, sp, format!("to `{}`", tts));
|
||||
let msg = format!("to `{}`", pprust::tts_to_string(tts.clone()));
|
||||
trace_macros_note(cx, sp, msg);
|
||||
}
|
||||
|
||||
let directory = Directory {
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::ast;
|
|||
use crate::ext::base::ExtCtxt;
|
||||
use crate::parse::{self, token, ParseSess};
|
||||
use crate::parse::lexer::comments;
|
||||
use crate::print::pprust;
|
||||
use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
|
||||
|
||||
use errors::Diagnostic;
|
||||
|
@ -174,7 +175,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
|
|||
}
|
||||
|
||||
Interpolated(nt) => {
|
||||
let stream = nt.to_tokenstream(sess, span);
|
||||
let stream = parse::nt_to_tokenstream(&nt, sess, span);
|
||||
TokenTree::Group(Group {
|
||||
delimiter: Delimiter::None,
|
||||
stream,
|
||||
|
@ -407,7 +408,7 @@ impl server::TokenStream for Rustc<'_> {
|
|||
)
|
||||
}
|
||||
fn to_string(&mut self, stream: &Self::TokenStream) -> String {
|
||||
stream.to_string()
|
||||
pprust::tts_to_string(stream.clone())
|
||||
}
|
||||
fn from_token_tree(
|
||||
&mut self,
|
||||
|
|
|
@ -856,7 +856,7 @@ impl<'a> Parser<'a> {
|
|||
// This is a best-effort recovery.
|
||||
path.span,
|
||||
"try",
|
||||
format!("<{}>::{}", ty_str, path),
|
||||
format!("<{}>::{}", ty_str, pprust::path_to_string(&path)),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
|
|
|
@ -4,10 +4,9 @@ use crate::ast::{self, CrateConfig, NodeId};
|
|||
use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
|
||||
use crate::source_map::{SourceMap, FilePathMapping};
|
||||
use crate::feature_gate::UnstableFeatures;
|
||||
use crate::parse::parser::Parser;
|
||||
use crate::parse::parser::emit_unclosed_delims;
|
||||
use crate::parse::token::TokenKind;
|
||||
use crate::tokenstream::{TokenStream, TokenTree};
|
||||
use crate::parse::parser::{Parser, emit_unclosed_delims};
|
||||
use crate::parse::token::{Nonterminal, TokenKind};
|
||||
use crate::tokenstream::{self, TokenStream, TokenTree};
|
||||
use crate::print::pprust;
|
||||
use crate::symbol::Symbol;
|
||||
|
||||
|
@ -24,6 +23,8 @@ use std::borrow::Cow;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
||||
use log::info;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
@ -407,3 +408,132 @@ impl SeqSep {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(Centril): The following probably shouldn't be here but it acknowledges the
|
||||
// fact that architecturally, we are using parsing (read on below to understand why).
|
||||
|
||||
pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream {
|
||||
// A `Nonterminal` is often a parsed AST item. At this point we now
|
||||
// need to convert the parsed AST to an actual token stream, e.g.
|
||||
// un-parse it basically.
|
||||
//
|
||||
// Unfortunately there's not really a great way to do that in a
|
||||
// guaranteed lossless fashion right now. The fallback here is to just
|
||||
// stringify the AST node and reparse it, but this loses all span
|
||||
// information.
|
||||
//
|
||||
// As a result, some AST nodes are annotated with the token stream they
|
||||
// came from. Here we attempt to extract these lossless token streams
|
||||
// before we fall back to the stringification.
|
||||
let tokens = match *nt {
|
||||
Nonterminal::NtItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtTraitItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtImplItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtIdent(ident, is_raw) => {
|
||||
Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
|
||||
}
|
||||
Nonterminal::NtLifetime(ident) => {
|
||||
Some(tokenstream::TokenTree::token(token::Lifetime(ident.name), ident.span).into())
|
||||
}
|
||||
Nonterminal::NtTT(ref tt) => {
|
||||
Some(tt.clone().into())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// FIXME(#43081): Avoid this pretty-print + reparse hack
|
||||
let source = pprust::nonterminal_to_string(nt);
|
||||
let filename = FileName::macro_expansion_source_code(&source);
|
||||
let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span));
|
||||
|
||||
// During early phases of the compiler the AST could get modified
|
||||
// directly (e.g., attributes added or removed) and the internal cache
|
||||
// of tokens my not be invalidated or updated. Consequently if the
|
||||
// "lossless" token stream disagrees with our actual stringification
|
||||
// (which has historically been much more battle-tested) then we go
|
||||
// with the lossy stream anyway (losing span information).
|
||||
//
|
||||
// Note that the comparison isn't `==` here to avoid comparing spans,
|
||||
// but it *also* is a "probable" equality which is a pretty weird
|
||||
// definition. We mostly want to catch actual changes to the AST
|
||||
// like a `#[cfg]` being processed or some weird `macro_rules!`
|
||||
// expansion.
|
||||
//
|
||||
// What we *don't* want to catch is the fact that a user-defined
|
||||
// literal like `0xf` is stringified as `15`, causing the cached token
|
||||
// stream to not be literal `==` token-wise (ignoring spans) to the
|
||||
// token stream we got from stringification.
|
||||
//
|
||||
// Instead the "probably equal" check here is "does each token
|
||||
// recursively have the same discriminant?" We basically don't look at
|
||||
// the token values here and assume that such fine grained token stream
|
||||
// modifications, including adding/removing typically non-semantic
|
||||
// tokens such as extra braces and commas, don't happen.
|
||||
if let Some(tokens) = tokens {
|
||||
if tokens.probably_equal_for_proc_macro(&tokens_for_real) {
|
||||
return tokens
|
||||
}
|
||||
info!("cached tokens found, but they're not \"probably equal\", \
|
||||
going with stringified version");
|
||||
}
|
||||
return tokens_for_real
|
||||
}
|
||||
|
||||
fn prepend_attrs(
|
||||
sess: &ParseSess,
|
||||
attrs: &[ast::Attribute],
|
||||
tokens: Option<&tokenstream::TokenStream>,
|
||||
span: syntax_pos::Span
|
||||
) -> Option<tokenstream::TokenStream> {
|
||||
let tokens = tokens?;
|
||||
if attrs.len() == 0 {
|
||||
return Some(tokens.clone())
|
||||
}
|
||||
let mut builder = tokenstream::TokenStreamBuilder::new();
|
||||
for attr in attrs {
|
||||
assert_eq!(attr.style, ast::AttrStyle::Outer,
|
||||
"inner attributes should prevent cached tokens from existing");
|
||||
|
||||
let source = pprust::attribute_to_string(attr);
|
||||
let macro_filename = FileName::macro_expansion_source_code(&source);
|
||||
if attr.is_sugared_doc {
|
||||
let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span));
|
||||
builder.push(stream);
|
||||
continue
|
||||
}
|
||||
|
||||
// synthesize # [ $path $tokens ] manually here
|
||||
let mut brackets = tokenstream::TokenStreamBuilder::new();
|
||||
|
||||
// For simple paths, push the identifier directly
|
||||
if attr.path.segments.len() == 1 && attr.path.segments[0].args.is_none() {
|
||||
let ident = attr.path.segments[0].ident;
|
||||
let token = token::Ident(ident.name, ident.as_str().starts_with("r#"));
|
||||
brackets.push(tokenstream::TokenTree::token(token, ident.span));
|
||||
|
||||
// ... and for more complicated paths, fall back to a reparse hack that
|
||||
// should eventually be removed.
|
||||
} else {
|
||||
let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span));
|
||||
brackets.push(stream);
|
||||
}
|
||||
|
||||
brackets.push(attr.tokens.clone());
|
||||
|
||||
// The span we list here for `#` and for `[ ... ]` are both wrong in
|
||||
// that it encompasses more than each token, but it hopefully is "good
|
||||
// enough" for now at least.
|
||||
builder.push(tokenstream::TokenTree::token(token::Pound, attr.span));
|
||||
let delim_span = tokenstream::DelimSpan::from_single(attr.span);
|
||||
builder.push(tokenstream::TokenTree::Delimited(
|
||||
delim_span, token::DelimToken::Bracket, brackets.build().into()));
|
||||
}
|
||||
builder.push(tokens.clone());
|
||||
Some(builder.build())
|
||||
}
|
||||
|
|
|
@ -9,20 +9,19 @@ mod path;
|
|||
pub use path::PathStyle;
|
||||
mod stmt;
|
||||
mod generics;
|
||||
use super::diagnostics::Error;
|
||||
|
||||
use crate::ast::{
|
||||
self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, Ident,
|
||||
IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility,
|
||||
VisibilityKind, Unsafety,
|
||||
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
|
||||
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
|
||||
};
|
||||
use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token};
|
||||
use crate::parse::diagnostics::{Error, dummy_arg};
|
||||
use crate::parse::lexer::UnmatchedBrace;
|
||||
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
|
||||
use crate::parse::token::{Token, TokenKind, DelimToken};
|
||||
use crate::print::pprust;
|
||||
use crate::ptr::P;
|
||||
use crate::source_map::{self, respan};
|
||||
use crate::source_map::respan;
|
||||
use crate::symbol::{kw, sym, Symbol};
|
||||
use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
|
||||
use crate::ThinVec;
|
||||
|
@ -56,17 +55,6 @@ crate enum BlockMode {
|
|||
Ignore,
|
||||
}
|
||||
|
||||
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
|
||||
struct ParamCfg {
|
||||
/// Is `self` is allowed as the first parameter?
|
||||
is_self_allowed: bool,
|
||||
/// Is `...` allowed as the tail of the parameter list?
|
||||
allow_c_variadic: bool,
|
||||
/// `is_name_required` decides if, per-parameter,
|
||||
/// the parameter must have a pattern or just a type.
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
}
|
||||
|
||||
/// Like `maybe_whole_expr`, but for things other than expressions.
|
||||
#[macro_export]
|
||||
macro_rules! maybe_whole {
|
||||
|
@ -1105,271 +1093,6 @@ impl<'a> Parser<'a> {
|
|||
res
|
||||
}
|
||||
|
||||
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
||||
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
|
||||
let sp = self.token.span;
|
||||
let is_trait_item = cfg.is_self_allowed;
|
||||
let mut c_variadic = false;
|
||||
// Parse the arguments, starting out with `self` being possibly allowed...
|
||||
let (params, _) = self.parse_paren_comma_seq(|p| {
|
||||
let param = p.parse_param_general(&cfg, is_trait_item);
|
||||
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||
cfg.is_self_allowed = false;
|
||||
|
||||
match param {
|
||||
Ok(param) => Ok(
|
||||
if let TyKind::CVarArgs = param.ty.kind {
|
||||
c_variadic = true;
|
||||
if p.token != token::CloseDelim(token::Paren) {
|
||||
p.span_err(
|
||||
p.token.span,
|
||||
"`...` must be the last argument of a C-variadic function",
|
||||
);
|
||||
// FIXME(eddyb) this should probably still push `CVarArgs`.
|
||||
// Maybe AST validation/HIR lowering should emit the above error?
|
||||
None
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
),
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
let span = lo.to(p.prev_span);
|
||||
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
|
||||
|
||||
// Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
|
||||
self.deduplicate_recovered_params_names(&mut params);
|
||||
|
||||
if c_variadic && params.len() <= 1 {
|
||||
self.span_err(
|
||||
sp,
|
||||
"C-variadic function must be declared with at least one named argument",
|
||||
);
|
||||
}
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
|
||||
/// error.
|
||||
/// This version of parse param doesn't necessarily require identifier names.
|
||||
fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> {
|
||||
let lo = self.token.span;
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
|
||||
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
|
||||
if let Some(mut param) = self.parse_self_param()? {
|
||||
param.attrs = attrs.into();
|
||||
return if cfg.is_self_allowed {
|
||||
Ok(param)
|
||||
} else {
|
||||
self.recover_bad_self_param(param, is_trait_item)
|
||||
};
|
||||
}
|
||||
|
||||
let is_name_required = match self.token.kind {
|
||||
token::DotDotDot => false,
|
||||
_ => (cfg.is_name_required)(&self.token),
|
||||
};
|
||||
let (pat, ty) = if is_name_required || self.is_named_param() {
|
||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
||||
|
||||
let pat = self.parse_fn_param_pat()?;
|
||||
if let Err(mut err) = self.expect(&token::Colon) {
|
||||
return if let Some(ident) = self.parameter_without_type(
|
||||
&mut err,
|
||||
pat,
|
||||
is_name_required,
|
||||
cfg.is_self_allowed,
|
||||
is_trait_item,
|
||||
) {
|
||||
err.emit();
|
||||
Ok(dummy_arg(ident))
|
||||
} else {
|
||||
Err(err)
|
||||
};
|
||||
}
|
||||
|
||||
self.eat_incorrect_doc_comment_for_param_type();
|
||||
(pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?)
|
||||
} else {
|
||||
debug!("parse_param_general ident_to_pat");
|
||||
let parser_snapshot_before_ty = self.clone();
|
||||
self.eat_incorrect_doc_comment_for_param_type();
|
||||
let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic);
|
||||
if ty.is_ok() && self.token != token::Comma &&
|
||||
self.token != token::CloseDelim(token::Paren) {
|
||||
// This wasn't actually a type, but a pattern looking like a type,
|
||||
// so we are going to rollback and re-parse for recovery.
|
||||
ty = self.unexpected();
|
||||
}
|
||||
match ty {
|
||||
Ok(ty) => {
|
||||
let ident = Ident::new(kw::Invalid, self.prev_span);
|
||||
let bm = BindingMode::ByValue(Mutability::Immutable);
|
||||
let pat = self.mk_pat_ident(ty.span, bm, ident);
|
||||
(pat, ty)
|
||||
}
|
||||
// If this is a C-variadic argument and we hit an error, return the error.
|
||||
Err(err) if self.token == token::DotDotDot => return Err(err),
|
||||
// Recover from attempting to parse the argument as a type without pattern.
|
||||
Err(mut err) => {
|
||||
err.cancel();
|
||||
mem::replace(self, parser_snapshot_before_ty);
|
||||
self.recover_arg_parse()?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let span = lo.to(self.token.span);
|
||||
|
||||
Ok(Param {
|
||||
attrs: attrs.into(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
is_placeholder: false,
|
||||
pat,
|
||||
span,
|
||||
ty,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the parsed optional self parameter and whether a self shortcut was used.
|
||||
///
|
||||
/// See `parse_self_param_with_attrs` to collect attributes.
|
||||
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
|
||||
// Extract an identifier *after* having confirmed that the token is one.
|
||||
let expect_self_ident = |this: &mut Self| {
|
||||
match this.token.kind {
|
||||
// Preserve hygienic context.
|
||||
token::Ident(name, _) => {
|
||||
let span = this.token.span;
|
||||
this.bump();
|
||||
Ident::new(name, span)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
// Is `self` `n` tokens ahead?
|
||||
let is_isolated_self = |this: &Self, n| {
|
||||
this.is_keyword_ahead(n, &[kw::SelfLower])
|
||||
&& this.look_ahead(n + 1, |t| t != &token::ModSep)
|
||||
};
|
||||
// Is `mut self` `n` tokens ahead?
|
||||
let is_isolated_mut_self = |this: &Self, n| {
|
||||
this.is_keyword_ahead(n, &[kw::Mut])
|
||||
&& is_isolated_self(this, n + 1)
|
||||
};
|
||||
// Parse `self` or `self: TYPE`. We already know the current token is `self`.
|
||||
let parse_self_possibly_typed = |this: &mut Self, m| {
|
||||
let eself_ident = expect_self_ident(this);
|
||||
let eself_hi = this.prev_span;
|
||||
let eself = if this.eat(&token::Colon) {
|
||||
SelfKind::Explicit(this.parse_ty()?, m)
|
||||
} else {
|
||||
SelfKind::Value(m)
|
||||
};
|
||||
Ok((eself, eself_ident, eself_hi))
|
||||
};
|
||||
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
|
||||
let recover_self_ptr = |this: &mut Self| {
|
||||
let msg = "cannot pass `self` by raw pointer";
|
||||
let span = this.token.span;
|
||||
this.struct_span_err(span, msg)
|
||||
.span_label(span, msg)
|
||||
.emit();
|
||||
|
||||
Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span))
|
||||
};
|
||||
|
||||
// Parse optional `self` parameter of a method.
|
||||
// Only a limited set of initial token sequences is considered `self` parameters; anything
|
||||
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||
let eself_lo = self.token.span;
|
||||
let (eself, eself_ident, eself_hi) = match self.token.kind {
|
||||
token::BinOp(token::And) => {
|
||||
let eself = if is_isolated_self(self, 1) {
|
||||
// `&self`
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Immutable)
|
||||
} else if is_isolated_mut_self(self, 1) {
|
||||
// `&mut self`
|
||||
self.bump();
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Mutable)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
|
||||
// `&'lt self`
|
||||
self.bump();
|
||||
let lt = self.expect_lifetime();
|
||||
SelfKind::Region(Some(lt), Mutability::Immutable)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) {
|
||||
// `&'lt mut self`
|
||||
self.bump();
|
||||
let lt = self.expect_lifetime();
|
||||
self.bump();
|
||||
SelfKind::Region(Some(lt), Mutability::Mutable)
|
||||
} else {
|
||||
// `¬_self`
|
||||
return Ok(None);
|
||||
};
|
||||
(eself, expect_self_ident(self), self.prev_span)
|
||||
}
|
||||
// `*self`
|
||||
token::BinOp(token::Star) if is_isolated_self(self, 1) => {
|
||||
self.bump();
|
||||
recover_self_ptr(self)?
|
||||
}
|
||||
// `*mut self` and `*const self`
|
||||
token::BinOp(token::Star) if
|
||||
self.look_ahead(1, |t| t.is_mutability())
|
||||
&& is_isolated_self(self, 2) =>
|
||||
{
|
||||
self.bump();
|
||||
self.bump();
|
||||
recover_self_ptr(self)?
|
||||
}
|
||||
// `self` and `self: TYPE`
|
||||
token::Ident(..) if is_isolated_self(self, 0) => {
|
||||
parse_self_possibly_typed(self, Mutability::Immutable)?
|
||||
}
|
||||
// `mut self` and `mut self: TYPE`
|
||||
token::Ident(..) if is_isolated_mut_self(self, 0) => {
|
||||
self.bump();
|
||||
parse_self_possibly_typed(self, Mutability::Mutable)?
|
||||
}
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
||||
let eself = source_map::respan(eself_lo.to(eself_hi), eself);
|
||||
Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
|
||||
}
|
||||
|
||||
fn is_named_param(&self) -> bool {
|
||||
let offset = match self.token.kind {
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
|
||||
_ => 0,
|
||||
}
|
||||
token::BinOp(token::And) | token::AndAnd => 1,
|
||||
_ if self.token.is_keyword(kw::Mut) => 1,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
self.look_ahead(offset, |t| t.is_ident()) &&
|
||||
self.look_ahead(offset + 1, |t| t == &token::Colon)
|
||||
}
|
||||
|
||||
fn is_crate_vis(&self) -> bool {
|
||||
self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
|
||||
}
|
||||
|
@ -1454,12 +1177,14 @@ impl<'a> Parser<'a> {
|
|||
`pub(super)`: visible only in the current module's parent
|
||||
`pub(in path::to::module)`: visible only on the specified path"##;
|
||||
|
||||
let path_str = pprust::path_to_string(&path);
|
||||
|
||||
struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg)
|
||||
.help(suggestion)
|
||||
.span_suggestion(
|
||||
path.span,
|
||||
&format!("make this visible only to module `{}` with `in`", path),
|
||||
format!("in {}", path),
|
||||
&format!("make this visible only to module `{}` with `in`", path_str),
|
||||
format!("in {}", path_str),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
|
|
|
@ -552,8 +552,11 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Report non-fatal diagnostics, keep `x as usize` as an expression
|
||||
// in AST and continue parsing.
|
||||
let msg = format!("`<` is interpreted as a start of generic \
|
||||
arguments for `{}`, not a {}", path, op_noun);
|
||||
let msg = format!(
|
||||
"`<` is interpreted as a start of generic arguments for `{}`, not a {}",
|
||||
pprust::path_to_string(&path),
|
||||
op_noun,
|
||||
);
|
||||
let span_after_type = parser_snapshot_after_type.token.span;
|
||||
let expr = mk_expr(self, P(Ty {
|
||||
span: path.span,
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode, ParamCfg};
|
||||
|
||||
use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode};
|
||||
use crate::maybe_whole;
|
||||
use crate::ptr::P;
|
||||
use crate::ast::{
|
||||
self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle,
|
||||
Item, ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind,
|
||||
UseTree, UseTreeKind, PathSegment,
|
||||
IsAuto, Constness, IsAsync, Unsafety, Defaultness,
|
||||
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block,
|
||||
ForeignItem, ForeignItemKind,
|
||||
Ty, TyKind, Generics, GenericBounds, TraitRef,
|
||||
EnumDef, VariantData, StructField, AnonConst,
|
||||
Mac, MacDelimiter,
|
||||
};
|
||||
use crate::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle, AnonConst, Item, ItemKind};
|
||||
use crate::ast::{ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
|
||||
use crate::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness};
|
||||
use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
||||
use crate::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField};
|
||||
use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfKind, Param};
|
||||
use crate::ext::base::DummyResult;
|
||||
use crate::parse::token;
|
||||
use crate::parse::parser::maybe_append;
|
||||
use crate::parse::diagnostics::Error;
|
||||
use crate::parse::diagnostics::{Error, dummy_arg};
|
||||
use crate::tokenstream::{TokenTree, TokenStream};
|
||||
use crate::source_map::{respan, Span};
|
||||
use crate::symbol::{kw, sym};
|
||||
use crate::source_map::{self, respan, Span};
|
||||
use crate::ThinVec;
|
||||
|
||||
use std::mem;
|
||||
use log::debug;
|
||||
use std::mem;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey};
|
||||
|
||||
|
@ -412,7 +407,7 @@ impl<'a> Parser<'a> {
|
|||
self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis)
|
||||
}
|
||||
|
||||
fn mk_item_with_info(
|
||||
pub(super) fn mk_item_with_info(
|
||||
&self,
|
||||
attrs: Vec<Attribute>,
|
||||
lo: Span,
|
||||
|
@ -425,16 +420,6 @@ impl<'a> Parser<'a> {
|
|||
Ok(Some(self.mk_item(span, ident, item, vis, attrs)))
|
||||
}
|
||||
|
||||
fn recover_first_param(&mut self) -> &'static str {
|
||||
match self.parse_outer_attributes()
|
||||
.and_then(|_| self.parse_self_param())
|
||||
.map_err(|mut e| e.cancel())
|
||||
{
|
||||
Ok(Some(_)) => "method",
|
||||
_ => "function",
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the fall-through for parsing items.
|
||||
fn parse_macro_use_or_failure(
|
||||
&mut self,
|
||||
|
@ -707,9 +692,11 @@ impl<'a> Parser<'a> {
|
|||
Ok(item)
|
||||
}
|
||||
|
||||
fn parse_impl_item_(&mut self,
|
||||
fn parse_impl_item_(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
|
||||
mut attrs: Vec<Attribute>,
|
||||
) -> PResult<'a, ImplItem> {
|
||||
let lo = self.token.span;
|
||||
let vis = self.parse_visibility(false)?;
|
||||
let defaultness = self.parse_defaultness();
|
||||
|
@ -722,8 +709,11 @@ impl<'a> Parser<'a> {
|
|||
(name, kind, generics)
|
||||
} else if self.is_const_item() {
|
||||
self.parse_impl_const()?
|
||||
} else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? {
|
||||
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
||||
(Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default())
|
||||
} else {
|
||||
let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?;
|
||||
let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?;
|
||||
attrs.extend(inner_attrs);
|
||||
(name, kind, generics)
|
||||
};
|
||||
|
@ -783,71 +773,6 @@ impl<'a> Parser<'a> {
|
|||
Ok((name, ImplItemKind::Const(typ, expr), Generics::default()))
|
||||
}
|
||||
|
||||
/// Parses a method or a macro invocation in a trait impl.
|
||||
fn parse_impl_method(
|
||||
&mut self,
|
||||
vis: &Visibility,
|
||||
at_end: &mut bool
|
||||
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ImplItemKind)> {
|
||||
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
||||
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
|
||||
// method macro
|
||||
Ok((Ident::invalid(), vec![], Generics::default(), ast::ImplItemKind::Macro(mac)))
|
||||
} else {
|
||||
let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the "signature", including the identifier, parameters, and generics
|
||||
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
|
||||
fn parse_method_sig(
|
||||
&mut self,
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
) -> PResult<'a, (Ident, MethodSig, Generics)> {
|
||||
let header = self.parse_fn_front_matter()?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: true,
|
||||
allow_c_variadic: false,
|
||||
is_name_required,
|
||||
})?;
|
||||
Ok((ident, MethodSig { header, decl }, generics))
|
||||
}
|
||||
|
||||
/// Parses all the "front matter" for a `fn` declaration, up to
|
||||
/// and including the `fn` keyword:
|
||||
///
|
||||
/// - `const fn`
|
||||
/// - `unsafe fn`
|
||||
/// - `const unsafe fn`
|
||||
/// - `extern fn`
|
||||
/// - etc.
|
||||
fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
||||
let is_const_fn = self.eat_keyword(kw::Const);
|
||||
let const_span = self.prev_span;
|
||||
let asyncness = self.parse_asyncness();
|
||||
if let IsAsync::Async { .. } = asyncness {
|
||||
self.ban_async_in_2015(self.prev_span);
|
||||
}
|
||||
let asyncness = respan(self.prev_span, asyncness);
|
||||
let unsafety = self.parse_unsafety();
|
||||
let (constness, unsafety, abi) = if is_const_fn {
|
||||
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
||||
} else {
|
||||
let abi = self.parse_extern_abi()?;
|
||||
(respan(self.prev_span, Constness::NotConst), unsafety, abi)
|
||||
};
|
||||
if !self.eat_keyword(kw::Fn) {
|
||||
// It is possible for `expect_one_of` to recover given the contents of
|
||||
// `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
|
||||
// account for this.
|
||||
if !self.expect_one_of(&[], &[])? { unreachable!() }
|
||||
}
|
||||
Ok(FnHeader { constness, unsafety, asyncness, abi })
|
||||
}
|
||||
|
||||
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
|
||||
fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
||||
// Parse optional `auto` prefix.
|
||||
|
@ -957,13 +882,7 @@ impl<'a> Parser<'a> {
|
|||
// trait item macro.
|
||||
(Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
|
||||
} else {
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// argument names to be left off if there is a definition...
|
||||
//
|
||||
// We don't allow argument names to be left off in edition 2018.
|
||||
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
|
||||
let body = self.parse_trait_method_body(at_end, &mut attrs)?;
|
||||
(ident, TraitItemKind::Method(sig, body), generics)
|
||||
self.parse_trait_item_method(at_end, &mut attrs)?
|
||||
};
|
||||
|
||||
Ok(TraitItem {
|
||||
|
@ -991,43 +910,6 @@ impl<'a> Parser<'a> {
|
|||
Ok((ident, TraitItemKind::Const(ty, default), Generics::default()))
|
||||
}
|
||||
|
||||
/// Parse the "body" of a method in a trait item definition.
|
||||
/// This can either be `;` when there's no body,
|
||||
/// or e.g. a block when the method is a provided one.
|
||||
fn parse_trait_method_body(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
) -> PResult<'a, Option<P<Block>>> {
|
||||
Ok(match self.token.kind {
|
||||
token::Semi => {
|
||||
debug!("parse_trait_method_body(): parsing required method");
|
||||
self.bump();
|
||||
*at_end = true;
|
||||
None
|
||||
}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
debug!("parse_trait_method_body(): parsing provided method");
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(inner_attrs.iter().cloned());
|
||||
Some(body)
|
||||
}
|
||||
token::Interpolated(ref nt) => {
|
||||
match **nt {
|
||||
token::NtBlock(..) => {
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(inner_attrs.iter().cloned());
|
||||
Some(body)
|
||||
}
|
||||
_ => return self.expected_semi_or_open_brace(),
|
||||
}
|
||||
}
|
||||
_ => return self.expected_semi_or_open_brace(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses the following grammar:
|
||||
///
|
||||
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
||||
|
@ -1194,45 +1076,6 @@ impl<'a> Parser<'a> {
|
|||
Ok(ident)
|
||||
}
|
||||
|
||||
/// Parses an item-position function declaration.
|
||||
fn parse_item_fn(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
vis: Visibility,
|
||||
attrs: Vec<Attribute>,
|
||||
header: FnHeader,
|
||||
) -> PResult<'a, Option<P<Item>>> {
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe,
|
||||
is_name_required: |_| true,
|
||||
})?;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
let kind = ItemKind::Fn(decl, header, generics, body);
|
||||
self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
|
||||
}
|
||||
|
||||
/// Parse the "signature", including the identifier, parameters, and generics of a function.
|
||||
fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
let decl = self.parse_fn_decl(cfg, true)?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
Ok((ident, decl, generics))
|
||||
}
|
||||
|
||||
/// Parses the parameter list and result type of a function declaration.
|
||||
pub(super) fn parse_fn_decl(
|
||||
&mut self,
|
||||
cfg: ParamCfg,
|
||||
ret_allow_plus: bool,
|
||||
) -> PResult<'a, P<FnDecl>> {
|
||||
Ok(P(FnDecl {
|
||||
inputs: self.parse_fn_params(cfg)?,
|
||||
output: self.parse_ret_ty(ret_allow_plus)?,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parses `extern` for foreign ABIs modules.
|
||||
///
|
||||
/// `extern` is expected to have been
|
||||
|
@ -1344,32 +1187,6 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses a function declaration from a foreign module.
|
||||
fn parse_item_foreign_fn(
|
||||
&mut self,
|
||||
vis: ast::Visibility,
|
||||
lo: Span,
|
||||
attrs: Vec<Attribute>,
|
||||
extern_sp: Span,
|
||||
) -> PResult<'a, ForeignItem> {
|
||||
self.expect_keyword(kw::Fn)?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(super::ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: true,
|
||||
is_name_required: |_| true,
|
||||
})?;
|
||||
let span = lo.to(self.token.span);
|
||||
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
|
||||
Ok(ast::ForeignItem {
|
||||
ident,
|
||||
attrs,
|
||||
kind: ForeignItemKind::Fn(decl, generics),
|
||||
id: DUMMY_NODE_ID,
|
||||
span,
|
||||
vis,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses a static item from a foreign module.
|
||||
/// Assumes that the `static` keyword is already parsed.
|
||||
fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
|
||||
|
@ -1910,3 +1727,466 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
|
||||
pub(super) struct ParamCfg {
|
||||
/// Is `self` is allowed as the first parameter?
|
||||
pub is_self_allowed: bool,
|
||||
/// Is `...` allowed as the tail of the parameter list?
|
||||
pub allow_c_variadic: bool,
|
||||
/// `is_name_required` decides if, per-parameter,
|
||||
/// the parameter must have a pattern or just a type.
|
||||
pub is_name_required: fn(&token::Token) -> bool,
|
||||
}
|
||||
|
||||
/// Parsing of functions and methods.
|
||||
impl<'a> Parser<'a> {
|
||||
/// Parses an item-position function declaration.
|
||||
fn parse_item_fn(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
vis: Visibility,
|
||||
attrs: Vec<Attribute>,
|
||||
header: FnHeader,
|
||||
) -> PResult<'a, Option<P<Item>>> {
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe,
|
||||
is_name_required: |_| true,
|
||||
})?;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
let kind = ItemKind::Fn(decl, header, generics, body);
|
||||
self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
|
||||
}
|
||||
|
||||
/// Parses a function declaration from a foreign module.
|
||||
fn parse_item_foreign_fn(
|
||||
&mut self,
|
||||
vis: ast::Visibility,
|
||||
lo: Span,
|
||||
attrs: Vec<Attribute>,
|
||||
extern_sp: Span,
|
||||
) -> PResult<'a, ForeignItem> {
|
||||
self.expect_keyword(kw::Fn)?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: true,
|
||||
is_name_required: |_| true,
|
||||
})?;
|
||||
let span = lo.to(self.token.span);
|
||||
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
|
||||
Ok(ast::ForeignItem {
|
||||
ident,
|
||||
attrs,
|
||||
kind: ForeignItemKind::Fn(decl, generics),
|
||||
id: DUMMY_NODE_ID,
|
||||
span,
|
||||
vis,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses a method or a macro invocation in a trait impl.
|
||||
fn parse_impl_method(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ImplItemKind)> {
|
||||
let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
|
||||
}
|
||||
|
||||
fn parse_trait_item_method(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// argument names to be left off if there is a definition...
|
||||
//
|
||||
// We don't allow argument names to be left off in edition 2018.
|
||||
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
|
||||
let body = self.parse_trait_method_body(at_end, attrs)?;
|
||||
Ok((ident, TraitItemKind::Method(sig, body), generics))
|
||||
}
|
||||
|
||||
/// Parse the "body" of a method in a trait item definition.
|
||||
/// This can either be `;` when there's no body,
|
||||
/// or e.g. a block when the method is a provided one.
|
||||
fn parse_trait_method_body(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
) -> PResult<'a, Option<P<Block>>> {
|
||||
Ok(match self.token.kind {
|
||||
token::Semi => {
|
||||
debug!("parse_trait_method_body(): parsing required method");
|
||||
self.bump();
|
||||
*at_end = true;
|
||||
None
|
||||
}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
debug!("parse_trait_method_body(): parsing provided method");
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(inner_attrs.iter().cloned());
|
||||
Some(body)
|
||||
}
|
||||
token::Interpolated(ref nt) => {
|
||||
match **nt {
|
||||
token::NtBlock(..) => {
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(inner_attrs.iter().cloned());
|
||||
Some(body)
|
||||
}
|
||||
_ => return self.expected_semi_or_open_brace(),
|
||||
}
|
||||
}
|
||||
_ => return self.expected_semi_or_open_brace(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse the "signature", including the identifier, parameters, and generics
|
||||
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
|
||||
fn parse_method_sig(
|
||||
&mut self,
|
||||
is_name_required: fn(&token::Token) -> bool,
|
||||
) -> PResult<'a, (Ident, MethodSig, Generics)> {
|
||||
let header = self.parse_fn_front_matter()?;
|
||||
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||
is_self_allowed: true,
|
||||
allow_c_variadic: false,
|
||||
is_name_required,
|
||||
})?;
|
||||
Ok((ident, MethodSig { header, decl }, generics))
|
||||
}
|
||||
|
||||
/// Parses all the "front matter" for a `fn` declaration, up to
|
||||
/// and including the `fn` keyword:
|
||||
///
|
||||
/// - `const fn`
|
||||
/// - `unsafe fn`
|
||||
/// - `const unsafe fn`
|
||||
/// - `extern fn`
|
||||
/// - etc.
|
||||
fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
||||
let is_const_fn = self.eat_keyword(kw::Const);
|
||||
let const_span = self.prev_span;
|
||||
let asyncness = self.parse_asyncness();
|
||||
if let IsAsync::Async { .. } = asyncness {
|
||||
self.ban_async_in_2015(self.prev_span);
|
||||
}
|
||||
let asyncness = respan(self.prev_span, asyncness);
|
||||
let unsafety = self.parse_unsafety();
|
||||
let (constness, unsafety, abi) = if is_const_fn {
|
||||
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
||||
} else {
|
||||
let abi = self.parse_extern_abi()?;
|
||||
(respan(self.prev_span, Constness::NotConst), unsafety, abi)
|
||||
};
|
||||
if !self.eat_keyword(kw::Fn) {
|
||||
// It is possible for `expect_one_of` to recover given the contents of
|
||||
// `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
|
||||
// account for this.
|
||||
if !self.expect_one_of(&[], &[])? { unreachable!() }
|
||||
}
|
||||
Ok(FnHeader { constness, unsafety, asyncness, abi })
|
||||
}
|
||||
|
||||
/// Parse the "signature", including the identifier, parameters, and generics of a function.
|
||||
fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
let decl = self.parse_fn_decl(cfg, true)?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
Ok((ident, decl, generics))
|
||||
}
|
||||
|
||||
/// Parses the parameter list and result type of a function declaration.
|
||||
pub(super) fn parse_fn_decl(
|
||||
&mut self,
|
||||
cfg: ParamCfg,
|
||||
ret_allow_plus: bool,
|
||||
) -> PResult<'a, P<FnDecl>> {
|
||||
Ok(P(FnDecl {
|
||||
inputs: self.parse_fn_params(cfg)?,
|
||||
output: self.parse_ret_ty(ret_allow_plus)?,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
||||
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
|
||||
let sp = self.token.span;
|
||||
let is_trait_item = cfg.is_self_allowed;
|
||||
let mut c_variadic = false;
|
||||
// Parse the arguments, starting out with `self` being possibly allowed...
|
||||
let (params, _) = self.parse_paren_comma_seq(|p| {
|
||||
let param = p.parse_param_general(&cfg, is_trait_item);
|
||||
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||
cfg.is_self_allowed = false;
|
||||
|
||||
match param {
|
||||
Ok(param) => Ok(
|
||||
if let TyKind::CVarArgs = param.ty.kind {
|
||||
c_variadic = true;
|
||||
if p.token != token::CloseDelim(token::Paren) {
|
||||
p.span_err(
|
||||
p.token.span,
|
||||
"`...` must be the last argument of a C-variadic function",
|
||||
);
|
||||
// FIXME(eddyb) this should probably still push `CVarArgs`.
|
||||
// Maybe AST validation/HIR lowering should emit the above error?
|
||||
None
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
),
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
let span = lo.to(p.prev_span);
|
||||
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
|
||||
|
||||
// Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
|
||||
self.deduplicate_recovered_params_names(&mut params);
|
||||
|
||||
if c_variadic && params.len() <= 1 {
|
||||
self.span_err(
|
||||
sp,
|
||||
"C-variadic function must be declared with at least one named argument",
|
||||
);
|
||||
}
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
|
||||
/// error.
|
||||
/// This version of parse param doesn't necessarily require identifier names.
|
||||
fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> {
|
||||
let lo = self.token.span;
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
|
||||
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
|
||||
if let Some(mut param) = self.parse_self_param()? {
|
||||
param.attrs = attrs.into();
|
||||
return if cfg.is_self_allowed {
|
||||
Ok(param)
|
||||
} else {
|
||||
self.recover_bad_self_param(param, is_trait_item)
|
||||
};
|
||||
}
|
||||
|
||||
let is_name_required = match self.token.kind {
|
||||
token::DotDotDot => false,
|
||||
_ => (cfg.is_name_required)(&self.token),
|
||||
};
|
||||
let (pat, ty) = if is_name_required || self.is_named_param() {
|
||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
||||
|
||||
let pat = self.parse_fn_param_pat()?;
|
||||
if let Err(mut err) = self.expect(&token::Colon) {
|
||||
return if let Some(ident) = self.parameter_without_type(
|
||||
&mut err,
|
||||
pat,
|
||||
is_name_required,
|
||||
cfg.is_self_allowed,
|
||||
is_trait_item,
|
||||
) {
|
||||
err.emit();
|
||||
Ok(dummy_arg(ident))
|
||||
} else {
|
||||
Err(err)
|
||||
};
|
||||
}
|
||||
|
||||
self.eat_incorrect_doc_comment_for_param_type();
|
||||
(pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?)
|
||||
} else {
|
||||
debug!("parse_param_general ident_to_pat");
|
||||
let parser_snapshot_before_ty = self.clone();
|
||||
self.eat_incorrect_doc_comment_for_param_type();
|
||||
let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic);
|
||||
if ty.is_ok() && self.token != token::Comma &&
|
||||
self.token != token::CloseDelim(token::Paren) {
|
||||
// This wasn't actually a type, but a pattern looking like a type,
|
||||
// so we are going to rollback and re-parse for recovery.
|
||||
ty = self.unexpected();
|
||||
}
|
||||
match ty {
|
||||
Ok(ty) => {
|
||||
let ident = Ident::new(kw::Invalid, self.prev_span);
|
||||
let bm = BindingMode::ByValue(Mutability::Immutable);
|
||||
let pat = self.mk_pat_ident(ty.span, bm, ident);
|
||||
(pat, ty)
|
||||
}
|
||||
// If this is a C-variadic argument and we hit an error, return the error.
|
||||
Err(err) if self.token == token::DotDotDot => return Err(err),
|
||||
// Recover from attempting to parse the argument as a type without pattern.
|
||||
Err(mut err) => {
|
||||
err.cancel();
|
||||
mem::replace(self, parser_snapshot_before_ty);
|
||||
self.recover_arg_parse()?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let span = lo.to(self.token.span);
|
||||
|
||||
Ok(Param {
|
||||
attrs: attrs.into(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
is_placeholder: false,
|
||||
pat,
|
||||
span,
|
||||
ty,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the parsed optional self parameter and whether a self shortcut was used.
|
||||
///
|
||||
/// See `parse_self_param_with_attrs` to collect attributes.
|
||||
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
|
||||
// Extract an identifier *after* having confirmed that the token is one.
|
||||
let expect_self_ident = |this: &mut Self| {
|
||||
match this.token.kind {
|
||||
// Preserve hygienic context.
|
||||
token::Ident(name, _) => {
|
||||
let span = this.token.span;
|
||||
this.bump();
|
||||
Ident::new(name, span)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
// Is `self` `n` tokens ahead?
|
||||
let is_isolated_self = |this: &Self, n| {
|
||||
this.is_keyword_ahead(n, &[kw::SelfLower])
|
||||
&& this.look_ahead(n + 1, |t| t != &token::ModSep)
|
||||
};
|
||||
// Is `mut self` `n` tokens ahead?
|
||||
let is_isolated_mut_self = |this: &Self, n| {
|
||||
this.is_keyword_ahead(n, &[kw::Mut])
|
||||
&& is_isolated_self(this, n + 1)
|
||||
};
|
||||
// Parse `self` or `self: TYPE`. We already know the current token is `self`.
|
||||
let parse_self_possibly_typed = |this: &mut Self, m| {
|
||||
let eself_ident = expect_self_ident(this);
|
||||
let eself_hi = this.prev_span;
|
||||
let eself = if this.eat(&token::Colon) {
|
||||
SelfKind::Explicit(this.parse_ty()?, m)
|
||||
} else {
|
||||
SelfKind::Value(m)
|
||||
};
|
||||
Ok((eself, eself_ident, eself_hi))
|
||||
};
|
||||
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
|
||||
let recover_self_ptr = |this: &mut Self| {
|
||||
let msg = "cannot pass `self` by raw pointer";
|
||||
let span = this.token.span;
|
||||
this.struct_span_err(span, msg)
|
||||
.span_label(span, msg)
|
||||
.emit();
|
||||
|
||||
Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span))
|
||||
};
|
||||
|
||||
// Parse optional `self` parameter of a method.
|
||||
// Only a limited set of initial token sequences is considered `self` parameters; anything
|
||||
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||
let eself_lo = self.token.span;
|
||||
let (eself, eself_ident, eself_hi) = match self.token.kind {
|
||||
token::BinOp(token::And) => {
|
||||
let eself = if is_isolated_self(self, 1) {
|
||||
// `&self`
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Immutable)
|
||||
} else if is_isolated_mut_self(self, 1) {
|
||||
// `&mut self`
|
||||
self.bump();
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Mutable)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
|
||||
// `&'lt self`
|
||||
self.bump();
|
||||
let lt = self.expect_lifetime();
|
||||
SelfKind::Region(Some(lt), Mutability::Immutable)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) {
|
||||
// `&'lt mut self`
|
||||
self.bump();
|
||||
let lt = self.expect_lifetime();
|
||||
self.bump();
|
||||
SelfKind::Region(Some(lt), Mutability::Mutable)
|
||||
} else {
|
||||
// `¬_self`
|
||||
return Ok(None);
|
||||
};
|
||||
(eself, expect_self_ident(self), self.prev_span)
|
||||
}
|
||||
// `*self`
|
||||
token::BinOp(token::Star) if is_isolated_self(self, 1) => {
|
||||
self.bump();
|
||||
recover_self_ptr(self)?
|
||||
}
|
||||
// `*mut self` and `*const self`
|
||||
token::BinOp(token::Star) if
|
||||
self.look_ahead(1, |t| t.is_mutability())
|
||||
&& is_isolated_self(self, 2) =>
|
||||
{
|
||||
self.bump();
|
||||
self.bump();
|
||||
recover_self_ptr(self)?
|
||||
}
|
||||
// `self` and `self: TYPE`
|
||||
token::Ident(..) if is_isolated_self(self, 0) => {
|
||||
parse_self_possibly_typed(self, Mutability::Immutable)?
|
||||
}
|
||||
// `mut self` and `mut self: TYPE`
|
||||
token::Ident(..) if is_isolated_mut_self(self, 0) => {
|
||||
self.bump();
|
||||
parse_self_possibly_typed(self, Mutability::Mutable)?
|
||||
}
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
||||
let eself = source_map::respan(eself_lo.to(eself_hi), eself);
|
||||
Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
|
||||
}
|
||||
|
||||
fn is_named_param(&self) -> bool {
|
||||
let offset = match self.token.kind {
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
|
||||
_ => 0,
|
||||
}
|
||||
token::BinOp(token::And) | token::AndAnd => 1,
|
||||
_ if self.token.is_keyword(kw::Mut) => 1,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
self.look_ahead(offset, |t| t.is_ident()) &&
|
||||
self.look_ahead(offset + 1, |t| t == &token::Colon)
|
||||
}
|
||||
|
||||
fn recover_first_param(&mut self) -> &'static str {
|
||||
match self.parse_outer_attributes()
|
||||
.and_then(|_| self.parse_self_param())
|
||||
.map_err(|mut e| e.cancel())
|
||||
{
|
||||
Ok(Some(_)) => "method",
|
||||
_ => "function",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{Parser, PResult, PathStyle, PrevTokenKind, TokenType};
|
||||
use super::item::ParamCfg;
|
||||
|
||||
use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
|
||||
use crate::ptr::P;
|
||||
|
@ -281,7 +282,7 @@ impl<'a> Parser<'a> {
|
|||
let unsafety = self.parse_unsafety();
|
||||
let abi = self.parse_extern_abi()?;
|
||||
self.expect_keyword(kw::Fn)?;
|
||||
let cfg = super::ParamCfg {
|
||||
let cfg = ParamCfg {
|
||||
is_self_allowed: false,
|
||||
allow_c_variadic: true,
|
||||
is_name_required: |_| false,
|
||||
|
|
|
@ -4,16 +4,13 @@ pub use DelimToken::*;
|
|||
pub use LitKind::*;
|
||||
pub use TokenKind::*;
|
||||
|
||||
use crate::ast::{self};
|
||||
use crate::parse::{parse_stream_from_source_str, ParseSess};
|
||||
use crate::print::pprust;
|
||||
use crate::ast;
|
||||
use crate::ptr::P;
|
||||
use crate::symbol::kw;
|
||||
use crate::tokenstream::{self, DelimSpan, TokenStream, TokenTree};
|
||||
use crate::tokenstream::TokenTree;
|
||||
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use syntax_pos::{self, Span, FileName, DUMMY_SP};
|
||||
use log::info;
|
||||
use syntax_pos::{self, Span, DUMMY_SP};
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
@ -737,131 +734,3 @@ impl fmt::Debug for Nonterminal {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Nonterminal {
|
||||
pub fn to_tokenstream(&self, sess: &ParseSess, span: Span) -> TokenStream {
|
||||
// A `Nonterminal` is often a parsed AST item. At this point we now
|
||||
// need to convert the parsed AST to an actual token stream, e.g.
|
||||
// un-parse it basically.
|
||||
//
|
||||
// Unfortunately there's not really a great way to do that in a
|
||||
// guaranteed lossless fashion right now. The fallback here is to just
|
||||
// stringify the AST node and reparse it, but this loses all span
|
||||
// information.
|
||||
//
|
||||
// As a result, some AST nodes are annotated with the token stream they
|
||||
// came from. Here we attempt to extract these lossless token streams
|
||||
// before we fall back to the stringification.
|
||||
let tokens = match *self {
|
||||
Nonterminal::NtItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtTraitItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtImplItem(ref item) => {
|
||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||
}
|
||||
Nonterminal::NtIdent(ident, is_raw) => {
|
||||
Some(TokenTree::token(Ident(ident.name, is_raw), ident.span).into())
|
||||
}
|
||||
Nonterminal::NtLifetime(ident) => {
|
||||
Some(TokenTree::token(Lifetime(ident.name), ident.span).into())
|
||||
}
|
||||
Nonterminal::NtTT(ref tt) => {
|
||||
Some(tt.clone().into())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// FIXME(#43081): Avoid this pretty-print + reparse hack
|
||||
let source = pprust::nonterminal_to_string(self);
|
||||
let filename = FileName::macro_expansion_source_code(&source);
|
||||
let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span));
|
||||
|
||||
// During early phases of the compiler the AST could get modified
|
||||
// directly (e.g., attributes added or removed) and the internal cache
|
||||
// of tokens my not be invalidated or updated. Consequently if the
|
||||
// "lossless" token stream disagrees with our actual stringification
|
||||
// (which has historically been much more battle-tested) then we go
|
||||
// with the lossy stream anyway (losing span information).
|
||||
//
|
||||
// Note that the comparison isn't `==` here to avoid comparing spans,
|
||||
// but it *also* is a "probable" equality which is a pretty weird
|
||||
// definition. We mostly want to catch actual changes to the AST
|
||||
// like a `#[cfg]` being processed or some weird `macro_rules!`
|
||||
// expansion.
|
||||
//
|
||||
// What we *don't* want to catch is the fact that a user-defined
|
||||
// literal like `0xf` is stringified as `15`, causing the cached token
|
||||
// stream to not be literal `==` token-wise (ignoring spans) to the
|
||||
// token stream we got from stringification.
|
||||
//
|
||||
// Instead the "probably equal" check here is "does each token
|
||||
// recursively have the same discriminant?" We basically don't look at
|
||||
// the token values here and assume that such fine grained token stream
|
||||
// modifications, including adding/removing typically non-semantic
|
||||
// tokens such as extra braces and commas, don't happen.
|
||||
if let Some(tokens) = tokens {
|
||||
if tokens.probably_equal_for_proc_macro(&tokens_for_real) {
|
||||
return tokens
|
||||
}
|
||||
info!("cached tokens found, but they're not \"probably equal\", \
|
||||
going with stringified version");
|
||||
}
|
||||
return tokens_for_real
|
||||
}
|
||||
}
|
||||
|
||||
fn prepend_attrs(sess: &ParseSess,
|
||||
attrs: &[ast::Attribute],
|
||||
tokens: Option<&tokenstream::TokenStream>,
|
||||
span: syntax_pos::Span)
|
||||
-> Option<tokenstream::TokenStream>
|
||||
{
|
||||
let tokens = tokens?;
|
||||
if attrs.len() == 0 {
|
||||
return Some(tokens.clone())
|
||||
}
|
||||
let mut builder = tokenstream::TokenStreamBuilder::new();
|
||||
for attr in attrs {
|
||||
assert_eq!(attr.style, ast::AttrStyle::Outer,
|
||||
"inner attributes should prevent cached tokens from existing");
|
||||
|
||||
let source = pprust::attribute_to_string(attr);
|
||||
let macro_filename = FileName::macro_expansion_source_code(&source);
|
||||
if attr.is_sugared_doc {
|
||||
let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span));
|
||||
builder.push(stream);
|
||||
continue
|
||||
}
|
||||
|
||||
// synthesize # [ $path $tokens ] manually here
|
||||
let mut brackets = tokenstream::TokenStreamBuilder::new();
|
||||
|
||||
// For simple paths, push the identifier directly
|
||||
if attr.path.segments.len() == 1 && attr.path.segments[0].args.is_none() {
|
||||
let ident = attr.path.segments[0].ident;
|
||||
let token = Ident(ident.name, ident.as_str().starts_with("r#"));
|
||||
brackets.push(tokenstream::TokenTree::token(token, ident.span));
|
||||
|
||||
// ... and for more complicated paths, fall back to a reparse hack that
|
||||
// should eventually be removed.
|
||||
} else {
|
||||
let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span));
|
||||
brackets.push(stream);
|
||||
}
|
||||
|
||||
brackets.push(attr.tokens.clone());
|
||||
|
||||
// The span we list here for `#` and for `[ ... ]` are both wrong in
|
||||
// that it encompasses more than each token, but it hopefully is "good
|
||||
// enough" for now at least.
|
||||
builder.push(tokenstream::TokenTree::token(Pound, attr.span));
|
||||
let delim_span = DelimSpan::from_single(attr.span);
|
||||
builder.push(tokenstream::TokenTree::Delimited(
|
||||
delim_span, DelimToken::Bracket, brackets.build().into()));
|
||||
}
|
||||
builder.push(tokens.clone());
|
||||
Some(builder.build())
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
//! ownership of the original.
|
||||
|
||||
use crate::parse::token::{self, DelimToken, Token, TokenKind};
|
||||
use crate::print::pprust;
|
||||
|
||||
use syntax_pos::{BytePos, Span, DUMMY_SP};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
@ -23,7 +22,7 @@ use rustc_data_structures::sync::Lrc;
|
|||
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
use std::{fmt, iter, mem};
|
||||
use std::{iter, mem};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -507,12 +506,6 @@ impl Cursor {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TokenStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&pprust::tts_to_string(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for TokenStream {
|
||||
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
|
||||
self.trees().collect::<Vec<_>>().encode(encoder)
|
||||
|
|
|
@ -7,6 +7,7 @@ use syntax::ext::base::ExtCtxt;
|
|||
use syntax::ext::expand::{AstFragment, ExpansionConfig};
|
||||
use syntax::ext::proc_macro::is_proc_macro_attr;
|
||||
use syntax::parse::ParseSess;
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::{kw, sym};
|
||||
use syntax::visit::{self, Visitor};
|
||||
|
@ -248,13 +249,20 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||
for attr in &item.attrs {
|
||||
if is_proc_macro_attr(&attr) {
|
||||
if let Some(prev_attr) = found_attr {
|
||||
let path_str = pprust::path_to_string(&attr.path);
|
||||
let msg = if attr.path.segments[0].ident.name ==
|
||||
prev_attr.path.segments[0].ident.name {
|
||||
format!("only one `#[{}]` attribute is allowed on any given function",
|
||||
attr.path)
|
||||
format!(
|
||||
"only one `#[{}]` attribute is allowed on any given function",
|
||||
path_str,
|
||||
)
|
||||
} else {
|
||||
format!("`#[{}]` and `#[{}]` attributes cannot both be applied \
|
||||
to the same function", attr.path, prev_attr.path)
|
||||
format!(
|
||||
"`#[{}]` and `#[{}]` attributes cannot both be applied
|
||||
to the same function",
|
||||
path_str,
|
||||
pprust::path_to_string(&prev_attr.path),
|
||||
)
|
||||
};
|
||||
|
||||
self.handler.struct_span_err(attr.span, &msg)
|
||||
|
@ -280,8 +288,10 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||
};
|
||||
|
||||
if !is_fn {
|
||||
let msg = format!("the `#[{}]` attribute may only be used on bare functions",
|
||||
attr.path);
|
||||
let msg = format!(
|
||||
"the `#[{}]` attribute may only be used on bare functions",
|
||||
pprust::path_to_string(&attr.path),
|
||||
);
|
||||
|
||||
self.handler.span_err(attr.span, &msg);
|
||||
return;
|
||||
|
@ -292,8 +302,10 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||
}
|
||||
|
||||
if !self.is_proc_macro_crate {
|
||||
let msg = format!("the `#[{}]` attribute is only usable with crates of the \
|
||||
`proc-macro` crate type", attr.path);
|
||||
let msg = format!(
|
||||
"the `#[{}]` attribute is only usable with crates of the `proc-macro` crate type",
|
||||
pprust::path_to_string(&attr.path),
|
||||
);
|
||||
|
||||
self.handler.span_err(attr.span, &msg);
|
||||
return;
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | const NAME: &'a str = "unit";
|
|||
|
|
||||
= note: expected type `&'static str`
|
||||
found type `&'a str`
|
||||
note: the lifetime 'a as defined on the impl at 6:6...
|
||||
note: the lifetime `'a` as defined on the impl at 6:6...
|
||||
--> $DIR/associated-const-impl-wrong-lifetime.rs:6:6
|
||||
|
|
||||
LL | impl<'a> Foo for &'a () {
|
||||
|
|
8
src/test/ui/associated-item/issue-48027.rs
Normal file
8
src/test/ui/associated-item/issue-48027.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
trait Bar {
|
||||
const X: usize;
|
||||
fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed
|
||||
}
|
||||
|
||||
impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object
|
||||
|
||||
fn main() {}
|
21
src/test/ui/associated-item/issue-48027.stderr
Normal file
21
src/test/ui/associated-item/issue-48027.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/issue-48027.rs:6:6
|
||||
|
|
||||
LL | const X: usize;
|
||||
| - the trait cannot contain associated consts like `X`
|
||||
...
|
||||
LL | impl dyn Bar {}
|
||||
| ^^^^^^^ the trait `Bar` cannot be made into an object
|
||||
|
||||
error[E0283]: type annotations needed: cannot resolve `_: Bar`
|
||||
--> $DIR/issue-48027.rs:3:32
|
||||
|
|
||||
LL | const X: usize;
|
||||
| --------------- required by `Bar::X`
|
||||
LL | fn return_n(&self) -> [u8; Bar::X];
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0283.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | bar(foo, x)
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 37:8...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8...
|
||||
--> $DIR/project-fn-ret-contravariant.rs:37:8
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | bar(foo, x)
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 44:8...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8...
|
||||
--> $DIR/project-fn-ret-invariant.rs:44:8
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
|
||||
|
|
19
src/test/ui/associated-types/issue-44153.rs
Normal file
19
src/test/ui/associated-types/issue-44153.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
pub trait Array {
|
||||
type Element;
|
||||
}
|
||||
|
||||
pub trait Visit {
|
||||
fn visit() {}
|
||||
}
|
||||
|
||||
impl Array for () {
|
||||
type Element = ();
|
||||
}
|
||||
|
||||
impl<'a> Visit for () where
|
||||
(): Array<Element=&'a ()>,
|
||||
{}
|
||||
|
||||
fn main() {
|
||||
<() as Visit>::visit(); //~ ERROR: type mismatch resolving
|
||||
}
|
16
src/test/ui/associated-types/issue-44153.stderr
Normal file
16
src/test/ui/associated-types/issue-44153.stderr
Normal file
|
@ -0,0 +1,16 @@
|
|||
error[E0271]: type mismatch resolving `<() as Array>::Element == &()`
|
||||
--> $DIR/issue-44153.rs:18:5
|
||||
|
|
||||
LL | fn visit() {}
|
||||
| ---------- required by `Visit::visit`
|
||||
...
|
||||
LL | <() as Visit>::visit();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ expected (), found &()
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `&()`
|
||||
= note: required because of the requirements on the impl of `Visit` for `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
23
src/test/ui/associated-types/issue-48010.rs
Normal file
23
src/test/ui/associated-types/issue-48010.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// check-pass
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub struct Path<T: Bar> {
|
||||
_inner: T::Slice,
|
||||
}
|
||||
|
||||
pub trait Bar: Sized {
|
||||
type Slice: ?Sized;
|
||||
|
||||
fn open(_: &Path<Self>);
|
||||
}
|
||||
|
||||
impl Bar for Foo {
|
||||
type Slice = [u8];
|
||||
|
||||
fn open(_: &Path<Self>) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
|
@ -15,12 +15,12 @@ LL | foo: &dyn Foo, bar: &'a dyn Foo
|
|||
LL | foo
|
||||
| --- this return type evaluates to the `'static` lifetime...
|
||||
|
|
||||
note: ...can't outlive the lifetime '_ as defined on the method body at 11:14
|
||||
note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14
|
||||
--> $DIR/issue-63388-2.rs:11:14
|
||||
|
|
||||
LL | foo: &dyn Foo, bar: &'a dyn Foo
|
||||
| ^
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 11:14
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 11:14
|
||||
|
|
||||
LL | foo + '_
|
||||
|
|
||||
|
|
|
@ -24,12 +24,12 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d
|
|||
|
|
||||
= note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
|
||||
found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`
|
||||
note: the lifetime 'c as defined on the method body at 27:24...
|
||||
note: the lifetime `'c` as defined on the method body at 27:24...
|
||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
|
||||
|
|
||||
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 27:24
|
||||
note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24
|
||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
|
||||
|
|
||||
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
||||
|
|
|
@ -14,7 +14,7 @@ LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<
|
|||
LL | | ap
|
||||
LL | | }
|
||||
| |_^
|
||||
note: ...does not necessarily outlive the lifetime 'f as defined on the function body at 7:37
|
||||
note: ...does not necessarily outlive the lifetime `'f` as defined on the function body at 7:37
|
||||
--> $DIR/variadic-ffi-4.rs:7:37
|
||||
|
|
||||
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
|
||||
|
|
|
@ -11,7 +11,7 @@ note: the anonymous lifetime #2 defined on the body at 14:48...
|
|||
|
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 11:36
|
||||
note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36
|
||||
--> $DIR/expect-fn-supply-fn.rs:11:36
|
||||
|
|
||||
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
|
@ -25,7 +25,7 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
|||
|
|
||||
= note: expected type `fn(&u32)`
|
||||
found type `fn(&'x u32)`
|
||||
note: the lifetime 'x as defined on the function body at 11:36...
|
||||
note: the lifetime `'x` as defined on the function body at 11:36...
|
||||
--> $DIR/expect-fn-supply-fn.rs:11:36
|
||||
|
|
||||
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
|
|
|
@ -38,7 +38,7 @@ LL | |
|
|||
LL | |
|
||||
LL | | });
|
||||
| |_____^
|
||||
note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 32:30
|
||||
note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 32:30
|
||||
--> $DIR/expect-region-supply-region.rs:32:30
|
||||
|
|
||||
LL | fn expect_bound_supply_named<'x>() {
|
||||
|
@ -52,7 +52,7 @@ LL | closure_expecting_bound(|x: &'x u32| {
|
|||
|
|
||||
= note: expected type `&u32`
|
||||
found type `&'x u32`
|
||||
note: the lifetime 'x as defined on the function body at 32:30...
|
||||
note: the lifetime `'x` as defined on the function body at 32:30...
|
||||
--> $DIR/expect-region-supply-region.rs:32:30
|
||||
|
|
||||
LL | fn expect_bound_supply_named<'x>() {
|
||||
|
|
|
@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied
|
|||
LL | child: Box<dyn Wedding<'kiss> + 'SnowWhite>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 3:22
|
||||
note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined on the struct at 3:22
|
||||
--> $DIR/E0478.rs:3:22
|
||||
|
|
||||
LL | struct Prince<'kiss, 'SnowWhite> {
|
||||
| ^^^^^^^^^^
|
||||
note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 3:15
|
||||
note: but lifetime parameter must outlive the lifetime `'kiss` as defined on the struct at 3:15
|
||||
--> $DIR/E0478.rs:3:15
|
||||
|
|
||||
LL | struct Prince<'kiss, 'SnowWhite> {
|
||||
|
|
|
@ -6,12 +6,12 @@ LL | Foo<'b,'a>
|
|||
|
|
||||
= note: expected type `Foo<'a, 'b>`
|
||||
found type `Foo<'b, 'a>`
|
||||
note: the lifetime 'b as defined on the impl at 6:9...
|
||||
note: the lifetime `'b` as defined on the impl at 6:9...
|
||||
--> $DIR/explicit-self-lifetime-mismatch.rs:6:9
|
||||
|
|
||||
LL | impl<'a,'b> Foo<'a,'b> {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 6:6
|
||||
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 6:6
|
||||
--> $DIR/explicit-self-lifetime-mismatch.rs:6:6
|
||||
|
|
||||
LL | impl<'a,'b> Foo<'a,'b> {
|
||||
|
@ -25,12 +25,12 @@ LL | Foo<'b,'a>
|
|||
|
|
||||
= note: expected type `Foo<'a, 'b>`
|
||||
found type `Foo<'b, 'a>`
|
||||
note: the lifetime 'a as defined on the impl at 6:6...
|
||||
note: the lifetime `'a` as defined on the impl at 6:6...
|
||||
--> $DIR/explicit-self-lifetime-mismatch.rs:6:6
|
||||
|
|
||||
LL | impl<'a,'b> Foo<'a,'b> {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 6:9
|
||||
note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 6:9
|
||||
--> $DIR/explicit-self-lifetime-mismatch.rs:6:9
|
||||
|
|
||||
LL | impl<'a,'b> Foo<'a,'b> {
|
||||
|
|
|
@ -10,7 +10,7 @@ LL | | fn(Inv<'y>)) }
|
|||
|
|
||||
= note: expected type `std::option::Option<fn(Inv<'y>)>`
|
||||
found type `std::option::Option<fn(Inv<'x>)>`
|
||||
note: the lifetime 'x as defined on the function body at 32:20...
|
||||
note: the lifetime `'x` as defined on the function body at 32:20...
|
||||
--> $DIR/hr-subtype.rs:32:20
|
||||
|
|
||||
LL | fn subtype<'x,'y:'x,'z:'y>() {
|
||||
|
@ -19,7 +19,7 @@ LL | fn subtype<'x,'y:'x,'z:'y>() {
|
|||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 32:23
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23
|
||||
--> $DIR/hr-subtype.rs:32:23
|
||||
|
|
||||
LL | fn subtype<'x,'y:'x,'z:'y>() {
|
||||
|
@ -41,7 +41,7 @@ LL | | fn(Inv<'y>)) }
|
|||
|
|
||||
= note: expected type `std::option::Option<fn(Inv<'x>)>`
|
||||
found type `std::option::Option<fn(Inv<'y>)>`
|
||||
note: the lifetime 'x as defined on the function body at 38:22...
|
||||
note: the lifetime `'x` as defined on the function body at 38:22...
|
||||
--> $DIR/hr-subtype.rs:38:22
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
|
@ -50,7 +50,7 @@ LL | fn supertype<'x,'y:'x,'z:'y>() {
|
|||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25
|
||||
--> $DIR/hr-subtype.rs:38:25
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
|
|
|
@ -10,7 +10,7 @@ LL | | fn(&'y u32)) }
|
|||
|
|
||||
= note: expected type `std::option::Option<fn(&'x u32)>`
|
||||
found type `std::option::Option<fn(&'y u32)>`
|
||||
note: the lifetime 'x as defined on the function body at 38:22...
|
||||
note: the lifetime `'x` as defined on the function body at 38:22...
|
||||
--> $DIR/hr-subtype.rs:38:22
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
|
@ -19,7 +19,7 @@ LL | fn supertype<'x,'y:'x,'z:'y>() {
|
|||
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
|
||||
LL | | fn(&'y u32)) }
|
||||
| |__________________________________________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25
|
||||
--> $DIR/hr-subtype.rs:38:25
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | static_val(x);
|
||||
| ^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 19:26...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26...
|
||||
--> $DIR/dyn-trait.rs:19:26
|
||||
|
|
||||
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
|
|||
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17
|
||||
note: hidden type `&'a mut &'b T` captures the lifetime `'b` as defined on the function body at 28:17
|
||||
--> $DIR/hidden-lifetimes.rs:28:17
|
||||
|
|
||||
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
|
||||
|
@ -16,7 +16,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
|
|||
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type `std::rc::Rc<std::cell::RefCell<&'b T>>` captures the lifetime 'b as defined on the function body at 45:24
|
||||
note: hidden type `std::rc::Rc<std::cell::RefCell<&'b T>>` captures the lifetime `'b` as defined on the function body at 45:24
|
||||
--> $DIR/hidden-lifetimes.rs:45:24
|
||||
|
|
||||
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
|
||||
|
|
|
@ -24,12 +24,12 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
|
|||
| |
|
||||
| this return type evaluates to the `'static` lifetime...
|
||||
|
|
||||
note: ...can't outlive the lifetime 'a as defined on the function body at 6:13
|
||||
note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:6:13
|
||||
|
|
||||
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
|
||||
| ^^
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 6:13
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13
|
||||
|
|
||||
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -42,12 +42,12 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
|||
| |
|
||||
| this return type evaluates to the `'static` lifetime...
|
||||
|
|
||||
note: ...can't outlive the lifetime 'a as defined on the function body at 12:15
|
||||
note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:12:15
|
||||
|
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||
| ^^
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 12:15
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15
|
||||
|
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
|
|||
LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 17:7
|
||||
note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime `'x` as defined on the function body at 17:7
|
||||
--> $DIR/region-escape-via-bound.rs:17:7
|
||||
|
|
||||
LL | where 'x: 'y
|
||||
|
|
|
@ -30,12 +30,12 @@ LL | self.x.iter().map(|a| a.0)
|
|||
| |
|
||||
| ...but this borrow...
|
||||
|
|
||||
note: ...can't outlive the lifetime 'a as defined on the method body at 10:20
|
||||
note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20
|
||||
--> $DIR/static-return-lifetime-infered.rs:10:20
|
||||
|
|
||||
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
|
||||
| ^^
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 10:20
|
||||
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20
|
||||
|
|
||||
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -11,7 +11,7 @@ LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
|
|||
LL | | x
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32...
|
||||
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
|
||||
--> $DIR/mismatched_trait_impl.rs:9:32
|
||||
|
|
||||
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
|
||||
|
|
|
@ -11,7 +11,7 @@ LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
|
|||
LL | | x
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32...
|
||||
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32...
|
||||
--> $DIR/mismatched_trait_impl.rs:9:32
|
||||
|
|
||||
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
|
||||
|
|
|
@ -12,7 +12,7 @@ LL | drop::<Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
|
|||
LL | | x
|
||||
LL | | }));
|
||||
| |_____^
|
||||
note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 1:9
|
||||
note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 1:9
|
||||
--> $DIR/issue-10291.rs:1:9
|
||||
|
|
||||
LL | fn test<'x>(x: &'x isize) {
|
||||
|
|
|
@ -16,7 +16,7 @@ note: ...so that reference does not outlive borrowed content
|
|||
|
|
||||
LL | self.a();
|
||||
| ^^^^
|
||||
note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 1:9...
|
||||
note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 1:9...
|
||||
--> $DIR/issue-16683.rs:1:9
|
||||
|
|
||||
LL | trait T<'a> {
|
||||
|
|
|
@ -17,7 +17,7 @@ LL | |
|
|||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 5:7
|
||||
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 5:7
|
||||
--> $DIR/issue-17740.rs:5:7
|
||||
|
|
||||
LL | impl <'a> Foo<'a>{
|
||||
|
@ -31,7 +31,7 @@ LL | fn bar(self: &mut Foo) {
|
|||
|
|
||||
= note: expected type `Foo<'a>`
|
||||
found type `Foo<'_>`
|
||||
note: the lifetime 'a as defined on the impl at 5:7...
|
||||
note: the lifetime `'a` as defined on the impl at 5:7...
|
||||
--> $DIR/issue-17740.rs:5:7
|
||||
|
|
||||
LL | impl <'a> Foo<'a>{
|
||||
|
|
|
@ -17,7 +17,7 @@ note: ...so that reference does not outlive borrowed content
|
|||
|
|
||||
LL | self.foo();
|
||||
| ^^^^
|
||||
note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 4:11...
|
||||
note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 4:11...
|
||||
--> $DIR/issue-17758.rs:4:11
|
||||
|
|
||||
LL | trait Foo<'a> {
|
||||
|
|
|
@ -15,7 +15,7 @@ LL | |
|
|||
LL | | println!("{:?}", self);
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...does not necessarily outlive the lifetime '_ as defined on the impl at 5:5
|
||||
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 5:5
|
||||
--> $DIR/issue-17905-2.rs:5:5
|
||||
|
|
||||
LL | &str,
|
||||
|
@ -29,7 +29,7 @@ LL | fn say(self: &Pair<&str, isize>) {
|
|||
|
|
||||
= note: expected type `Pair<&str, _>`
|
||||
found type `Pair<&str, _>`
|
||||
note: the lifetime '_ as defined on the impl at 5:5...
|
||||
note: the lifetime `'_` as defined on the impl at 5:5...
|
||||
--> $DIR/issue-17905-2.rs:5:5
|
||||
|
|
||||
LL | &str,
|
||||
|
|
|
@ -23,7 +23,7 @@ LL | |
|
|||
LL | | self.sub = t;
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 26:6
|
||||
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6
|
||||
--> $DIR/issue-20831-debruijn.rs:26:6
|
||||
|
|
||||
LL | impl<'a> Publisher<'a> for MyStruct<'a> {
|
||||
|
@ -43,7 +43,7 @@ LL | | }
|
|||
|
|
||||
= note: expected type `'a`
|
||||
found type `'_`
|
||||
note: the lifetime 'a as defined on the impl at 26:6...
|
||||
note: the lifetime `'a` as defined on the impl at 26:6...
|
||||
--> $DIR/issue-20831-debruijn.rs:26:6
|
||||
|
|
||||
LL | impl<'a> Publisher<'a> for MyStruct<'a> {
|
||||
|
@ -83,7 +83,7 @@ LL | |
|
|||
LL | | self.sub = t;
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...but the lifetime must also be valid for the lifetime 'a as defined on the impl at 26:6...
|
||||
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
|
||||
--> $DIR/issue-20831-debruijn.rs:26:6
|
||||
|
|
||||
LL | impl<'a> Publisher<'a> for MyStruct<'a> {
|
||||
|
|
|
@ -11,7 +11,7 @@ note: the anonymous lifetime #1 defined on the method body at 5:5...
|
|||
|
|
||||
LL | fn select(&self) -> BufferViewHandle<R>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 3:18
|
||||
note: ...does not necessarily outlive the lifetime `'a` as defined on the trait at 3:18
|
||||
--> $DIR/issue-27942.rs:3:18
|
||||
|
|
||||
LL | pub trait Buffer<'a, R: Resources<'a>> {
|
||||
|
@ -25,7 +25,7 @@ LL | fn select(&self) -> BufferViewHandle<R>;
|
|||
|
|
||||
= note: expected type `Resources<'_>`
|
||||
found type `Resources<'a>`
|
||||
note: the lifetime 'a as defined on the trait at 3:18...
|
||||
note: the lifetime `'a` as defined on the trait at 3:18...
|
||||
--> $DIR/issue-27942.rs:3:18
|
||||
|
|
||||
LL | pub trait Buffer<'a, R: Resources<'a>> {
|
||||
|
|
|
@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied
|
|||
LL | Foo::<'a, 'b>::xmute(u)
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 9:16
|
||||
note: lifetime parameter instantiated with the lifetime `'b` as defined on the function body at 9:16
|
||||
--> $DIR/issue-28848.rs:9:16
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
||||
| ^^
|
||||
note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 9:12
|
||||
note: but lifetime parameter must outlive the lifetime `'a` as defined on the function body at 9:12
|
||||
--> $DIR/issue-28848.rs:9:12
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
|
||||
|
|
|
@ -21,7 +21,7 @@ LL | | {
|
|||
LL | | Some(&mut self.0)
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 3:6
|
||||
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 3:6
|
||||
--> $DIR/issue-37884.rs:3:6
|
||||
|
|
||||
LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
|
||||
|
|
4
src/test/ui/issues/issue-47486.rs
Normal file
4
src/test/ui/issues/issue-47486.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
() < std::mem::size_of::<_>(); //~ ERROR: mismatched types
|
||||
[0u8; std::mem::size_of::<_>()]; //~ ERROR: type annotations needed
|
||||
}
|
19
src/test/ui/issues/issue-47486.stderr
Normal file
19
src/test/ui/issues/issue-47486.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-47486.rs:2:10
|
||||
|
|
||||
LL | () < std::mem::size_of::<_>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found usize
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `usize`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-47486.rs:3:11
|
||||
|
|
||||
LL | [0u8; std::mem::size_of::<_>()];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0308.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | match (&t,) {
|
||||
| ^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 1:23...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 1:23...
|
||||
--> $DIR/issue-52213.rs:1:23
|
||||
|
|
||||
LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
|
||||
|
@ -12,7 +12,7 @@ LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
|
|||
= note: ...so that the types are compatible:
|
||||
expected (&&(T,),)
|
||||
found (&&'a (T,),)
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 1:27...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27...
|
||||
--> $DIR/issue-52213.rs:1:27
|
||||
|
|
||||
LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | Box::new(self.out_edges(u).map(|e| e.target()))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 5:17...
|
||||
--> $DIR/issue-55796.rs:5:17
|
||||
|
|
||||
LL | pub trait Graph<'a> {
|
||||
|
@ -25,7 +25,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | Box::new(self.in_edges(u).map(|e| e.target()))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 5:17...
|
||||
--> $DIR/issue-55796.rs:5:17
|
||||
|
|
||||
LL | pub trait Graph<'a> {
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | ref_obj(x)
|
|||
|
|
||||
= note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>`
|
||||
found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>`
|
||||
note: the lifetime 'a as defined on the function body at 32:10...
|
||||
note: the lifetime `'a` as defined on the function body at 32:10...
|
||||
--> $DIR/lifetime-bound-will-change-warning.rs:32:10
|
||||
|
|
||||
LL | fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) {
|
||||
|
@ -21,7 +21,7 @@ LL | lib::ref_obj(x)
|
|||
|
|
||||
= note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>`
|
||||
found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>`
|
||||
note: the lifetime 'a as defined on the function body at 37:12...
|
||||
note: the lifetime `'a` as defined on the function body at 37:12...
|
||||
--> $DIR/lifetime-bound-will-change-warning.rs:37:12
|
||||
|
|
||||
LL | fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | s
|
|||
| ^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 23:17
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 23:17
|
||||
--> $DIR/lub-if.rs:23:17
|
||||
|
|
||||
LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
|
||||
|
@ -18,7 +18,7 @@ LL | s
|
|||
| ^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 32:17
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 32:17
|
||||
--> $DIR/lub-if.rs:32:17
|
||||
|
|
||||
LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | s
|
|||
| ^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 25:17
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 25:17
|
||||
--> $DIR/lub-match.rs:25:17
|
||||
|
|
||||
LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
|
||||
|
@ -18,7 +18,7 @@ LL | s
|
|||
| ^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 35:17
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 35:17
|
||||
--> $DIR/lub-match.rs:35:17
|
||||
|
|
||||
LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
|
||||
|
|
|
@ -6,12 +6,12 @@ LL | match self.0 { ref mut x => x }
|
|||
|
|
||||
= note: expected type `&'a mut &'a i32`
|
||||
found type `&'a mut &'b i32`
|
||||
note: the lifetime 'a as defined on the method body at 9:12...
|
||||
note: the lifetime `'a` as defined on the method body at 9:12...
|
||||
--> $DIR/match-ref-mut-invariance.rs:9:12
|
||||
|
|
||||
LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6
|
||||
note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6
|
||||
--> $DIR/match-ref-mut-invariance.rs:8:6
|
||||
|
|
||||
LL | impl<'b> S<'b> {
|
||||
|
|
|
@ -6,12 +6,12 @@ LL | x
|
|||
|
|
||||
= note: expected type `&'a mut &'a i32`
|
||||
found type `&'a mut &'b i32`
|
||||
note: the lifetime 'a as defined on the method body at 9:12...
|
||||
note: the lifetime `'a` as defined on the method body at 9:12...
|
||||
--> $DIR/match-ref-mut-let-invariance.rs:9:12
|
||||
|
|
||||
LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6
|
||||
note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6
|
||||
--> $DIR/match-ref-mut-let-invariance.rs:8:6
|
||||
|
|
||||
LL | impl<'b> S<'b> {
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | let _x = *s;
|
|||
|
|
||||
= note: expected type `std::marker::Sized`
|
||||
found type `std::marker::Sized`
|
||||
note: the lifetime 'a as defined on the function body at 9:8...
|
||||
note: the lifetime `'a` as defined on the function body at 9:8...
|
||||
--> $DIR/issue-50716.rs:9:8
|
||||
|
|
||||
LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content...
|
|||
LL | self.y = b.z
|
||||
| ^^^
|
||||
|
|
||||
note: ...the reference is valid for the lifetime '_ as defined on the impl at 12:10...
|
||||
note: ...the reference is valid for the lifetime `'_` as defined on the impl at 12:10...
|
||||
--> $DIR/issue-52742.rs:12:10
|
||||
|
|
||||
LL | impl Foo<'_, '_> {
|
||||
|
|
|
@ -16,7 +16,7 @@ note: ...so that reference does not outlive borrowed content
|
|||
|
|
||||
LL | Foo { bar }
|
||||
| ^^^
|
||||
note: but, the lifetime must be valid for the lifetime '_ as defined on the impl at 7:10...
|
||||
note: but, the lifetime must be valid for the lifetime `'_` as defined on the impl at 7:10...
|
||||
--> $DIR/issue-55394.rs:7:10
|
||||
|
|
||||
LL | impl Foo<'_> {
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | *y
|
|||
| ^^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 1:47
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 1:47
|
||||
--> $DIR/issue-55401.rs:1:47
|
||||
|
|
||||
LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 {
|
||||
|
|
|
@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` d
|
|||
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'd as defined on the function body at 12:14...
|
||||
note: first, the lifetime cannot outlive the lifetime `'d` as defined on the function body at 12:14...
|
||||
--> $DIR/normalization-bounds-error.rs:12:14
|
||||
|
|
||||
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
|
||||
| ^^
|
||||
note: ...but the lifetime must also be valid for the lifetime 'a as defined on the function body at 12:18...
|
||||
note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the function body at 12:18...
|
||||
--> $DIR/normalization-bounds-error.rs:12:18
|
||||
|
|
||||
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
|
||||
|
|
|
@ -6,12 +6,12 @@ LL | const AC: Option<&'c str> = None;
|
|||
|
|
||||
= note: expected type `std::option::Option<&'b str>`
|
||||
found type `std::option::Option<&'c str>`
|
||||
note: the lifetime 'c as defined on the impl at 20:18...
|
||||
note: the lifetime `'c` as defined on the impl at 20:18...
|
||||
--> $DIR/trait-associated-constant.rs:20:18
|
||||
|
|
||||
LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14
|
||||
note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 20:14
|
||||
--> $DIR/trait-associated-constant.rs:20:14
|
||||
|
|
||||
LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
|
||||
|
|
|
@ -14,7 +14,7 @@ LL | | }
|
|||
= note: ...so that the expression is assignable:
|
||||
expected std::boxed::Box<std::boxed::Box<&isize>>
|
||||
found std::boxed::Box<std::boxed::Box<&isize>>
|
||||
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 15:6...
|
||||
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
|
||||
--> $DIR/type-alias-free-regions.rs:15:6
|
||||
|
|
||||
LL | impl<'a> FromBox<'a> for C<'a> {
|
||||
|
@ -39,7 +39,7 @@ LL | | }
|
|||
= note: ...so that the expression is assignable:
|
||||
expected std::boxed::Box<&isize>
|
||||
found std::boxed::Box<&isize>
|
||||
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 25:6...
|
||||
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6...
|
||||
--> $DIR/type-alias-free-regions.rs:25:6
|
||||
|
|
||||
LL | impl<'a> FromTuple<'a> for C<'a> {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
|
|||
LL | <Foo<'a>>::C
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 7:8...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8...
|
||||
--> $DIR/constant-in-expr-inherent-1.rs:7:8
|
||||
|
|
||||
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C
|
|||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 17:8
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 17:8
|
||||
--> $DIR/constant-in-expr-normalize.rs:17:8
|
||||
|
|
||||
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C
|
|||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 9:8
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8
|
||||
--> $DIR/constant-in-expr-trait-item-1.rs:9:8
|
||||
|
|
||||
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | <T as Foo<'a>>::C
|
|||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...the reference is valid for the static lifetime...
|
||||
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 9:8
|
||||
note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8
|
||||
--> $DIR/constant-in-expr-trait-item-2.rs:9:8
|
||||
|
|
||||
LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
|
|||
LL | T::C
|
||||
| ^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:8...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:8...
|
||||
--> $DIR/constant-in-expr-trait-item-3.rs:9:8
|
||||
|
|
||||
LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to
|
|||
LL | ss
|
||||
| ^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10...
|
||||
--> $DIR/object-lifetime-default-elision.rs:54:10
|
||||
|
|
||||
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
|
||||
|
@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content
|
|||
|
|
||||
LL | ss
|
||||
| ^^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13...
|
||||
--> $DIR/object-lifetime-default-elision.rs:54:13
|
||||
|
|
||||
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
|
||||
|
@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | ss
|
||||
| ^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10...
|
||||
--> $DIR/object-lifetime-default-elision.rs:54:10
|
||||
|
|
||||
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
|
||||
|
@ -39,7 +39,7 @@ note: ...so that the declared lifetime parameter bounds are satisfied
|
|||
|
|
||||
LL | ss
|
||||
| ^^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13...
|
||||
--> $DIR/object-lifetime-default-elision.rs:54:13
|
||||
|
|
||||
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | ss.t = t;
|
|||
|
|
||||
= note: expected type `&'a std::boxed::Box<(dyn Test + 'static)>`
|
||||
found type `&'a std::boxed::Box<(dyn Test + 'a)>`
|
||||
note: the lifetime 'a as defined on the function body at 14:6...
|
||||
note: the lifetime `'a` as defined on the function body at 14:6...
|
||||
--> $DIR/object-lifetime-default-from-rptr-box-error.rs:14:6
|
||||
|
|
||||
LL | fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | ss.t = t;
|
|||
|
|
||||
= note: expected type `&'a MyBox<(dyn Test + 'static)>`
|
||||
found type `&'a MyBox<(dyn Test + 'a)>`
|
||||
note: the lifetime 'a as defined on the function body at 20:6...
|
||||
note: the lifetime `'a` as defined on the function body at 20:6...
|
||||
--> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6
|
||||
|
|
||||
LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
|
||||
|
|
|
@ -18,7 +18,7 @@ LL | load0(ss)
|
|||
|
|
||||
= note: expected type `&MyBox<(dyn SomeTrait + 'static)>`
|
||||
found type `&MyBox<(dyn SomeTrait + 'a)>`
|
||||
note: the lifetime 'a as defined on the function body at 30:10...
|
||||
note: the lifetime `'a` as defined on the function body at 30:10...
|
||||
--> $DIR/object-lifetime-default-mybox.rs:30:10
|
||||
|
|
||||
LL | fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> {
|
||||
|
|
|
@ -10,12 +10,12 @@ error[E0478]: lifetime bound not satisfied
|
|||
LL | z: Box<dyn Is<'a>+'b+'c>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 11:15
|
||||
note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 11:15
|
||||
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15
|
||||
|
|
||||
LL | struct Foo<'a,'b,'c> {
|
||||
| ^^
|
||||
note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 11:12
|
||||
note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 11:12
|
||||
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12
|
||||
|
|
||||
LL | struct Foo<'a,'b,'c> {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// over time, but this test used to exhibit some pretty bogus messages
|
||||
// that were not remotely helpful.
|
||||
|
||||
// error-pattern:the lifetime 'a
|
||||
// error-pattern:the lifetime `'a`
|
||||
// error-pattern:the static lifetime
|
||||
|
||||
struct Invariant<'a>(Option<&'a mut &'a mut ()>);
|
||||
|
|
|
@ -13,7 +13,7 @@ LL | | };
|
|||
|
|
||||
= note: expected type `Invariant<'a>`
|
||||
found type `Invariant<'static>`
|
||||
note: the lifetime 'a as defined on the function body at 13:10...
|
||||
note: the lifetime `'a` as defined on the function body at 13:10...
|
||||
--> $DIR/region-invariant-static-error-reporting.rs:13:10
|
||||
|
|
||||
LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin
|
|||
LL | x.borrowed()
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:42...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:42...
|
||||
--> $DIR/region-object-lifetime-2.rs:9:42
|
||||
|
|
||||
LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
|
||||
|
@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content
|
|||
|
|
||||
LL | x.borrowed()
|
||||
| ^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 9:45...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 9:45...
|
||||
--> $DIR/region-object-lifetime-2.rs:9:45
|
||||
|
|
||||
LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin
|
|||
LL | x.borrowed()
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 11:41...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 11:41...
|
||||
--> $DIR/region-object-lifetime-4.rs:11:41
|
||||
|
|
||||
LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
|
||||
|
@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content
|
|||
|
|
||||
LL | x.borrowed()
|
||||
| ^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 11:44...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 11:44...
|
||||
--> $DIR/region-object-lifetime-4.rs:11:44
|
||||
|
|
||||
LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
|
||||
|
|
|
@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
|
|||
LL | Box::new(v)
|
||||
| ^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 25:6...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 25:6...
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:25:6
|
||||
|
|
||||
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
|
||||
|
@ -37,7 +37,7 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
|
|||
= note: ...so that the expression is assignable:
|
||||
expected &[u8]
|
||||
found &'a [u8]
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 25:9...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9...
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:25:9
|
||||
|
|
||||
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to
|
|||
LL | let p: &'static mut usize = &mut self.food;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 9:18...
|
||||
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 9:18...
|
||||
--> $DIR/regions-addr-of-upvar-self.rs:9:18
|
||||
|
|
||||
LL | let _f = || {
|
||||
|
|
|
@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifet
|
|||
LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the pointer is valid for the lifetime 'a as defined on the function body at 33:15
|
||||
note: the pointer is valid for the lifetime `'a` as defined on the function body at 33:15
|
||||
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15
|
||||
|
|
||||
LL | fn with_assoc<'a,'b>() {
|
||||
| ^^
|
||||
note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 33:18
|
||||
note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 33:18
|
||||
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18
|
||||
|
|
||||
LL | fn with_assoc<'a,'b>() {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
|
|||
LL | impl<'a> Foo<'static> for &'a i32 {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 14:6...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6...
|
||||
--> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6
|
||||
|
|
||||
LL | impl<'a> Foo<'static> for &'a i32 {
|
||||
|
@ -25,7 +25,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
|
|||
LL | impl<'a,'b> Foo<'b> for &'a i64 {
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 19:6...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6...
|
||||
--> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6
|
||||
|
|
||||
LL | impl<'a,'b> Foo<'b> for &'a i64 {
|
||||
|
@ -33,7 +33,7 @@ LL | impl<'a,'b> Foo<'b> for &'a i64 {
|
|||
= note: ...so that the types are compatible:
|
||||
expected Foo<'b>
|
||||
found Foo<'_>
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 19:9...
|
||||
note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9...
|
||||
--> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
|
||||
|
|
||||
LL | impl<'a,'b> Foo<'b> for &'a i64 {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
|
|||
LL | impl<'a> Foo for &'a i32 {
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 9:6...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6...
|
||||
--> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6
|
||||
|
|
||||
LL | impl<'a> Foo for &'a i32 {
|
||||
|
|
|
@ -6,12 +6,12 @@ LL | return e;
|
|||
|
|
||||
= note: expected type `TupleStruct<'b>`
|
||||
found type `TupleStruct<'a>`
|
||||
note: the lifetime 'a as defined on the function body at 8:10...
|
||||
note: the lifetime `'a` as defined on the function body at 8:10...
|
||||
--> $DIR/regions-bounds.rs:8:10
|
||||
|
|
||||
LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 8:13
|
||||
note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 8:13
|
||||
--> $DIR/regions-bounds.rs:8:13
|
||||
|
|
||||
LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
|
||||
|
@ -25,12 +25,12 @@ LL | return e;
|
|||
|
|
||||
= note: expected type `Struct<'b>`
|
||||
found type `Struct<'a>`
|
||||
note: the lifetime 'a as defined on the function body at 12:10...
|
||||
note: the lifetime `'a` as defined on the function body at 12:10...
|
||||
--> $DIR/regions-bounds.rs:12:10
|
||||
|
|
||||
LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 12:13
|
||||
note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 12:13
|
||||
--> $DIR/regions-bounds.rs:12:13
|
||||
|
|
||||
LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to
|
|||
LL | box B(&*v) as Box<dyn X>
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
|
||||
--> $DIR/regions-close-object-into-object-2.rs:9:6
|
||||
|
|
||||
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to
|
|||
LL | box B(&*v) as Box<dyn X>
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6...
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
|
||||
--> $DIR/regions-close-object-into-object-4.rs:9:6
|
||||
|
|
||||
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue