mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #70351 - Centril:rollup-tveoq3w, r=Centril
Rollup of 8 pull requests Successful merges: - #68884 (Make the `type_of` return a generic type for generators) - #69788 (Fix sequence of Type and Trait in optin-builtin-traits in Unstable Book) - #70074 (Expand: nix all fatal errors) - #70077 (Store idents for `DefPathData` into crate metadata) - #70213 (traits/fulfill: allow `stalled_on` to track `ty::Const::Infer(_)` (unused yet).) - #70259 (Use Reveal::All in MIR optimizations) - #70284 (correctly handle const params in type_of) - #70289 (Refactor `codegen`) Failed merges: r? @ghost
This commit is contained in:
commit
9d0ae58d30
@ -16,7 +16,7 @@ has explicitly opted out via a negative impl.
|
||||
[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
|
||||
|
||||
```rust,ignore
|
||||
impl !Type for Trait
|
||||
impl !Trait for Type
|
||||
```
|
||||
|
||||
Example:
|
||||
|
@ -3,7 +3,6 @@
|
||||
use rustc_ast::ast::{self, AttrItem, AttrStyle};
|
||||
use rustc_ast::attr::mk_attr;
|
||||
use rustc_ast::token;
|
||||
use rustc_expand::panictry;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::FileName;
|
||||
|
||||
@ -16,7 +15,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
|
||||
);
|
||||
|
||||
let start_span = parser.token.span;
|
||||
let AttrItem { path, args } = panictry!(parser.parse_attr_item());
|
||||
let AttrItem { path, args } = match parser.parse_attr_item() {
|
||||
Ok(ai) => ai,
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let end_span = parser.token.span;
|
||||
if parser.token != token::Eof {
|
||||
parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute");
|
||||
|
@ -5,7 +5,6 @@ use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_expand::module::DirectoryOwnership;
|
||||
use rustc_expand::panictry;
|
||||
use rustc_parse::{self, new_parser_from_file, parser::Parser};
|
||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||
use rustc_span::symbol::Symbol;
|
||||
@ -126,7 +125,7 @@ pub fn expand_include<'cx>(
|
||||
}
|
||||
impl<'a> base::MacResult for ExpandResult<'a> {
|
||||
fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
|
||||
let r = panictry!(self.p.parse_expr());
|
||||
let r = base::parse_expr(&mut self.p)?;
|
||||
if self.p.token != token::Eof {
|
||||
self.p.sess.buffer_lint(
|
||||
&INCOMPLETE_INCLUDE,
|
||||
@ -141,18 +140,17 @@ pub fn expand_include<'cx>(
|
||||
fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
|
||||
let mut ret = SmallVec::new();
|
||||
while self.p.token != token::Eof {
|
||||
match panictry!(self.p.parse_item()) {
|
||||
Some(item) => ret.push(item),
|
||||
None => {
|
||||
match self.p.parse_item() {
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
Ok(Some(item)) => ret.push(item),
|
||||
Ok(None) => {
|
||||
let token = pprust::token_to_string(&self.p.token);
|
||||
self.p
|
||||
.sess
|
||||
.span_diagnostic
|
||||
.span_fatal(
|
||||
self.p.token.span,
|
||||
&format!("expected item, found `{}`", token),
|
||||
)
|
||||
.raise();
|
||||
let msg = format!("expected item, found `{}`", token);
|
||||
self.p.struct_span_err(self.p.token.span, &msg).emit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,16 +74,16 @@ pub fn expand_test_or_bench(
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let item = if let Annotatable::Item(i) = item {
|
||||
i
|
||||
} else {
|
||||
cx.parse_sess
|
||||
.span_diagnostic
|
||||
.span_fatal(
|
||||
item.span(),
|
||||
let item = match item {
|
||||
Annotatable::Item(i) => i,
|
||||
other => {
|
||||
cx.struct_span_err(
|
||||
other.span(),
|
||||
"`#[test]` attribute is only allowed on non associated functions",
|
||||
)
|
||||
.raise();
|
||||
.emit();
|
||||
return vec![other];
|
||||
}
|
||||
};
|
||||
|
||||
if let ast::ItemKind::MacCall(_) = item.kind {
|
||||
|
@ -345,14 +345,14 @@ fn is_test_case(i: &ast::Item) -> bool {
|
||||
|
||||
fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
|
||||
let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
|
||||
test_attr.meta_item_list().map(|meta_list| {
|
||||
if meta_list.len() != 1 {
|
||||
sd.span_fatal(test_attr.span, "`#![test_runner(..)]` accepts exactly 1 argument")
|
||||
.raise()
|
||||
}
|
||||
match meta_list[0].meta_item() {
|
||||
Some(meta_item) if meta_item.is_word() => meta_item.path.clone(),
|
||||
_ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise(),
|
||||
}
|
||||
})
|
||||
let meta_list = test_attr.meta_item_list()?;
|
||||
let span = test_attr.span;
|
||||
match &*meta_list {
|
||||
[single] => match single.meta_item() {
|
||||
Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()),
|
||||
_ => sd.struct_span_err(span, "`test_runner` argument must be a path").emit(),
|
||||
},
|
||||
_ => sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(),
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use crate::ModuleLlvm;
|
||||
use log::debug;
|
||||
use rustc::bug;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, ModuleConfig};
|
||||
use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, EmbedBitcode, ModuleConfig};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
@ -634,30 +634,24 @@ pub(crate) unsafe fn codegen(
|
||||
f(cpm)
|
||||
}
|
||||
|
||||
// If we don't have the integrated assembler, then we need to emit asm
|
||||
// from LLVM and use `gcc` to create the object file.
|
||||
let asm_to_obj = config.emit_obj && config.no_integrated_as;
|
||||
|
||||
// Change what we write and cleanup based on whether obj files are
|
||||
// just llvm bitcode. In that case write bitcode, and possibly
|
||||
// delete the bitcode if it wasn't requested. Don't generate the
|
||||
// machine code, instead copy the .o file from the .bc
|
||||
let write_bc = config.emit_bc || config.obj_is_bitcode;
|
||||
let rm_bc = !config.emit_bc && config.obj_is_bitcode;
|
||||
let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
|
||||
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
|
||||
// Two things to note:
|
||||
// - If object files are just LLVM bitcode we write bitcode, copy it to
|
||||
// the .o file, and delete the bitcode if it wasn't otherwise
|
||||
// requested.
|
||||
// - If we don't have the integrated assembler then we need to emit
|
||||
// asm from LLVM and use `gcc` to create the object file.
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
|
||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
|
||||
if write_bc || config.emit_bc_compressed || config.embed_bitcode {
|
||||
if config.bitcode_needed() {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]);
|
||||
let thin = ThinBuffer::new(llmod);
|
||||
let data = thin.data();
|
||||
|
||||
if write_bc {
|
||||
if config.emit_bc || config.obj_is_bitcode {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"LLVM_module_codegen_emit_bitcode",
|
||||
&module.name[..],
|
||||
@ -668,7 +662,7 @@ pub(crate) unsafe fn codegen(
|
||||
}
|
||||
}
|
||||
|
||||
if config.embed_bitcode {
|
||||
if config.embed_bitcode == EmbedBitcode::Full {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"LLVM_module_codegen_embed_bitcode",
|
||||
&module.name[..],
|
||||
@ -688,81 +682,75 @@ pub(crate) unsafe fn codegen(
|
||||
diag_handler.err(&msg);
|
||||
}
|
||||
}
|
||||
} else if config.embed_bitcode_marker {
|
||||
} else if config.embed_bitcode == EmbedBitcode::Marker {
|
||||
embed_bitcode(cgcx, llcx, llmod, None);
|
||||
}
|
||||
|
||||
{
|
||||
if config.emit_ir {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]);
|
||||
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
|
||||
let out_c = path_to_c_string(&out);
|
||||
if config.emit_ir {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]);
|
||||
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
|
||||
let out_c = path_to_c_string(&out);
|
||||
|
||||
extern "C" fn demangle_callback(
|
||||
input_ptr: *const c_char,
|
||||
input_len: size_t,
|
||||
output_ptr: *mut c_char,
|
||||
output_len: size_t,
|
||||
) -> size_t {
|
||||
let input = unsafe {
|
||||
slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
|
||||
};
|
||||
extern "C" fn demangle_callback(
|
||||
input_ptr: *const c_char,
|
||||
input_len: size_t,
|
||||
output_ptr: *mut c_char,
|
||||
output_len: size_t,
|
||||
) -> size_t {
|
||||
let input =
|
||||
unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
|
||||
|
||||
let input = match str::from_utf8(input) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return 0,
|
||||
};
|
||||
let input = match str::from_utf8(input) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return 0,
|
||||
};
|
||||
|
||||
let output = unsafe {
|
||||
slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
|
||||
};
|
||||
let mut cursor = io::Cursor::new(output);
|
||||
let output = unsafe {
|
||||
slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
|
||||
};
|
||||
let mut cursor = io::Cursor::new(output);
|
||||
|
||||
let demangled = match rustc_demangle::try_demangle(input) {
|
||||
Ok(d) => d,
|
||||
Err(_) => return 0,
|
||||
};
|
||||
let demangled = match rustc_demangle::try_demangle(input) {
|
||||
Ok(d) => d,
|
||||
Err(_) => return 0,
|
||||
};
|
||||
|
||||
if write!(cursor, "{:#}", demangled).is_err() {
|
||||
// Possible only if provided buffer is not big enough
|
||||
return 0;
|
||||
}
|
||||
|
||||
cursor.position() as size_t
|
||||
if write!(cursor, "{:#}", demangled).is_err() {
|
||||
// Possible only if provided buffer is not big enough
|
||||
return 0;
|
||||
}
|
||||
|
||||
let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
|
||||
result.into_result().map_err(|()| {
|
||||
let msg = format!("failed to write LLVM IR to {}", out.display());
|
||||
llvm_err(diag_handler, &msg)
|
||||
})?;
|
||||
cursor.position() as size_t
|
||||
}
|
||||
|
||||
if config.emit_asm || asm_to_obj {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
|
||||
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||
let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
|
||||
result.into_result().map_err(|()| {
|
||||
let msg = format!("failed to write LLVM IR to {}", out.display());
|
||||
llvm_err(diag_handler, &msg)
|
||||
})?;
|
||||
}
|
||||
|
||||
// We can't use the same module for asm and binary output, because that triggers
|
||||
// various errors like invalid IR or broken binaries, so we might have to clone the
|
||||
// module to produce the asm output
|
||||
let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod };
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
diag_handler,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&path,
|
||||
llvm::FileType::AssemblyFile,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
let config_emit_normal_obj = config.emit_obj && !config.obj_is_bitcode;
|
||||
|
||||
if write_obj {
|
||||
if config.emit_asm || (config_emit_normal_obj && config.no_integrated_as) {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
|
||||
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||
|
||||
// We can't use the same module for asm and binary output, because that triggers
|
||||
// various errors like invalid IR or broken binaries, so we might have to clone the
|
||||
// module to produce the asm output
|
||||
let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod };
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
|
||||
})?;
|
||||
}
|
||||
|
||||
if config_emit_normal_obj {
|
||||
if !config.no_integrated_as {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
|
||||
@ -776,7 +764,7 @@ pub(crate) unsafe fn codegen(
|
||||
llvm::FileType::ObjectFile,
|
||||
)
|
||||
})?;
|
||||
} else if asm_to_obj {
|
||||
} else {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]);
|
||||
@ -789,17 +777,19 @@ pub(crate) unsafe fn codegen(
|
||||
}
|
||||
}
|
||||
|
||||
if copy_bc_to_obj {
|
||||
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
|
||||
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
|
||||
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
|
||||
if config.obj_is_bitcode {
|
||||
if config.emit_obj {
|
||||
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
|
||||
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
|
||||
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if rm_bc {
|
||||
debug!("removing_bitcode {:?}", bc_out);
|
||||
if let Err(e) = fs::remove_file(&bc_out) {
|
||||
diag_handler.err(&format!("failed to remove bitcode: {}", e));
|
||||
if !config.emit_bc {
|
||||
debug!("removing_bitcode {:?}", bc_out);
|
||||
if let Err(e) = fs::remove_file(&bc_out) {
|
||||
diag_handler.err(&format!("failed to remove bitcode: {}", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,14 @@ use std::thread;
|
||||
|
||||
const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
|
||||
|
||||
/// The kind of bitcode to embed in object files.
|
||||
#[derive(PartialEq)]
|
||||
pub enum EmbedBitcode {
|
||||
None,
|
||||
Marker,
|
||||
Full,
|
||||
}
|
||||
|
||||
/// Module-specific configuration for `optimize_and_codegen`.
|
||||
pub struct ModuleConfig {
|
||||
/// Names of additional optimization passes to run.
|
||||
@ -74,7 +82,6 @@ pub struct ModuleConfig {
|
||||
pub emit_no_opt_bc: bool,
|
||||
pub emit_bc: bool,
|
||||
pub emit_bc_compressed: bool,
|
||||
pub emit_lto_bc: bool,
|
||||
pub emit_ir: bool,
|
||||
pub emit_asm: bool,
|
||||
pub emit_obj: bool,
|
||||
@ -94,8 +101,7 @@ pub struct ModuleConfig {
|
||||
// emscripten's ecc compiler, when used as the linker.
|
||||
pub obj_is_bitcode: bool,
|
||||
pub no_integrated_as: bool,
|
||||
pub embed_bitcode: bool,
|
||||
pub embed_bitcode_marker: bool,
|
||||
pub embed_bitcode: EmbedBitcode,
|
||||
}
|
||||
|
||||
impl ModuleConfig {
|
||||
@ -116,13 +122,11 @@ impl ModuleConfig {
|
||||
emit_pre_lto_bc: false,
|
||||
emit_bc: false,
|
||||
emit_bc_compressed: false,
|
||||
emit_lto_bc: false,
|
||||
emit_ir: false,
|
||||
emit_asm: false,
|
||||
emit_obj: false,
|
||||
obj_is_bitcode: false,
|
||||
embed_bitcode: false,
|
||||
embed_bitcode_marker: false,
|
||||
embed_bitcode: EmbedBitcode::None,
|
||||
no_integrated_as: false,
|
||||
|
||||
verify_llvm_ir: false,
|
||||
@ -145,16 +149,15 @@ impl ModuleConfig {
|
||||
self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager;
|
||||
self.obj_is_bitcode =
|
||||
sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled();
|
||||
let embed_bitcode =
|
||||
sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode;
|
||||
if embed_bitcode {
|
||||
match sess.opts.optimize {
|
||||
config::OptLevel::No | config::OptLevel::Less => {
|
||||
self.embed_bitcode_marker = embed_bitcode;
|
||||
self.embed_bitcode =
|
||||
if sess.target.target.options.embed_bitcode || sess.opts.debugging_opts.embed_bitcode {
|
||||
match sess.opts.optimize {
|
||||
config::OptLevel::No | config::OptLevel::Less => EmbedBitcode::Marker,
|
||||
_ => EmbedBitcode::Full,
|
||||
}
|
||||
_ => self.embed_bitcode = embed_bitcode,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EmbedBitcode::None
|
||||
};
|
||||
|
||||
// Copy what clang does by turning on loop vectorization at O2 and
|
||||
// slp vectorization at O3. Otherwise configure other optimization aspects
|
||||
@ -190,7 +193,10 @@ impl ModuleConfig {
|
||||
}
|
||||
|
||||
pub fn bitcode_needed(&self) -> bool {
|
||||
self.emit_bc || self.obj_is_bitcode || self.emit_bc_compressed || self.embed_bitcode
|
||||
self.emit_bc
|
||||
|| self.obj_is_bitcode
|
||||
|| self.emit_bc_compressed
|
||||
|| self.embed_bitcode == EmbedBitcode::Full
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,7 +385,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
||||
modules_config.emit_no_opt_bc = true;
|
||||
modules_config.emit_pre_lto_bc = true;
|
||||
modules_config.emit_bc = true;
|
||||
modules_config.emit_lto_bc = true;
|
||||
metadata_config.emit_bc = true;
|
||||
allocator_config.emit_bc = true;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorReported};
|
||||
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::edition::Edition;
|
||||
@ -296,16 +296,26 @@ where
|
||||
}
|
||||
|
||||
pub trait ProcMacro {
|
||||
fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt<'_>, span: Span, ts: TokenStream) -> TokenStream;
|
||||
fn expand<'cx>(
|
||||
&self,
|
||||
ecx: &'cx mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
ts: TokenStream,
|
||||
) -> Result<TokenStream, ErrorReported>;
|
||||
}
|
||||
|
||||
impl<F> ProcMacro for F
|
||||
where
|
||||
F: Fn(TokenStream) -> TokenStream,
|
||||
{
|
||||
fn expand<'cx>(&self, _ecx: &'cx mut ExtCtxt<'_>, _span: Span, ts: TokenStream) -> TokenStream {
|
||||
fn expand<'cx>(
|
||||
&self,
|
||||
_ecx: &'cx mut ExtCtxt<'_>,
|
||||
_span: Span,
|
||||
ts: TokenStream,
|
||||
) -> Result<TokenStream, ErrorReported> {
|
||||
// FIXME setup implicit context in TLS before calling self.
|
||||
(*self)(ts)
|
||||
Ok((*self)(ts))
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,7 +326,7 @@ pub trait AttrProcMacro {
|
||||
span: Span,
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
) -> TokenStream;
|
||||
) -> Result<TokenStream, ErrorReported>;
|
||||
}
|
||||
|
||||
impl<F> AttrProcMacro for F
|
||||
@ -329,9 +339,9 @@ where
|
||||
_span: Span,
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
) -> TokenStream {
|
||||
) -> Result<TokenStream, ErrorReported> {
|
||||
// FIXME setup implicit context in TLS before calling self.
|
||||
(*self)(annotation, annotated)
|
||||
Ok((*self)(annotation, annotated))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1004,31 +1014,9 @@ impl<'a> ExtCtxt<'a> {
|
||||
self.current_expansion.id.expansion_cause()
|
||||
}
|
||||
|
||||
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> {
|
||||
self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
|
||||
}
|
||||
pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> {
|
||||
self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
|
||||
}
|
||||
pub fn struct_span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> {
|
||||
self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
|
||||
}
|
||||
|
||||
/// Emit `msg` attached to `sp`, and stop compilation immediately.
|
||||
///
|
||||
/// `span_err` should be strongly preferred where-ever possible:
|
||||
/// this should *only* be used when:
|
||||
///
|
||||
/// - continuing has a high risk of flow-on errors (e.g., errors in
|
||||
/// declaring a macro would cause all uses of that macro to
|
||||
/// complain about "undefined macro"), or
|
||||
/// - there is literally nothing else that can be done (however,
|
||||
/// in most cases one can construct a dummy expression/item to
|
||||
/// substitute; we never hit resolve/type-checking so the dummy
|
||||
/// value doesn't have to match anything)
|
||||
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
|
||||
self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise();
|
||||
}
|
||||
|
||||
/// Emit `msg` attached to `sp`, without immediately stopping
|
||||
/// compilation.
|
||||
@ -1038,9 +1026,6 @@ impl<'a> ExtCtxt<'a> {
|
||||
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
||||
self.parse_sess.span_diagnostic.span_err(sp, msg);
|
||||
}
|
||||
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
|
||||
self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code);
|
||||
}
|
||||
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
||||
self.parse_sess.span_diagnostic.span_warn(sp, msg);
|
||||
}
|
||||
@ -1168,6 +1153,18 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an expression. On error, emit it, advancing to `Eof`, and return `None`.
|
||||
pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
|
||||
match p.parse_expr() {
|
||||
Ok(e) => return Some(e),
|
||||
Err(mut err) => err.emit(),
|
||||
}
|
||||
while p.token != token::Eof {
|
||||
p.bump();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Interpreting `tts` as a comma-separated sequence of expressions,
|
||||
/// expect exactly one string literal, or emit an error and return `None`.
|
||||
pub fn get_single_str_from_tts(
|
||||
@ -1181,7 +1178,7 @@ pub fn get_single_str_from_tts(
|
||||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
||||
return None;
|
||||
}
|
||||
let ret = panictry!(p.parse_expr());
|
||||
let ret = parse_expr(&mut p)?;
|
||||
let _ = p.eat(&token::Comma);
|
||||
|
||||
if p.token != token::Eof {
|
||||
@ -1190,8 +1187,8 @@ pub fn get_single_str_from_tts(
|
||||
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s.to_string())
|
||||
}
|
||||
|
||||
/// Extracts comma-separated expressions from `tts`. If there is a
|
||||
/// parsing error, emit a non-fatal error and return `None`.
|
||||
/// Extracts comma-separated expressions from `tts`.
|
||||
/// On error, emit it, and return `None`.
|
||||
pub fn get_exprs_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
@ -1200,7 +1197,7 @@ pub fn get_exprs_from_tts(
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
let mut es = Vec::new();
|
||||
while p.token != token::Eof {
|
||||
let expr = panictry!(p.parse_expr());
|
||||
let expr = parse_expr(&mut p)?;
|
||||
|
||||
// Perform eager expansion on the expression.
|
||||
// We want to be able to handle e.g., `concat!("foo", "bar")`.
|
||||
|
@ -204,7 +204,7 @@ ast_fragments! {
|
||||
}
|
||||
|
||||
impl AstFragmentKind {
|
||||
fn dummy(self, span: Span) -> AstFragment {
|
||||
crate fn dummy(self, span: Span) -> AstFragment {
|
||||
self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
|
||||
}
|
||||
|
||||
@ -682,7 +682,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
InvocationKind::Bang { mac, .. } => match ext {
|
||||
SyntaxExtensionKind::Bang(expander) => {
|
||||
self.gate_proc_macro_expansion_kind(span, fragment_kind);
|
||||
let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens());
|
||||
let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) {
|
||||
Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
|
||||
Ok(ts) => ts,
|
||||
};
|
||||
self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
|
||||
}
|
||||
SyntaxExtensionKind::LegacyBang(expander) => {
|
||||
@ -709,8 +712,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
if let MacArgs::Eq(..) = attr_item.args {
|
||||
self.cx.span_err(span, "key-value macro attributes are not supported");
|
||||
}
|
||||
let tok_result =
|
||||
expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens);
|
||||
let inner_tokens = attr_item.args.inner_tokens();
|
||||
let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) {
|
||||
Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)),
|
||||
Ok(ts) => ts,
|
||||
};
|
||||
self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
|
||||
}
|
||||
SyntaxExtensionKind::LegacyAttr(expander) => {
|
||||
@ -1139,6 +1145,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||
// macros are expanded before any lint passes so this warning has to be hardcoded
|
||||
if attr.has_name(sym::derive) {
|
||||
self.cx
|
||||
.parse_sess()
|
||||
.span_diagnostic
|
||||
.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations")
|
||||
.note("this may become a hard error in a future release")
|
||||
.emit();
|
||||
|
@ -9,25 +9,6 @@
|
||||
|
||||
extern crate proc_macro as pm;
|
||||
|
||||
// A variant of 'try!' that panics on an Err. This is used as a crutch on the
|
||||
// way towards a non-panic!-prone parser. It should be used for fatal parsing
|
||||
// errors; eventually we plan to convert all code using panictry to just use
|
||||
// normal try.
|
||||
#[macro_export]
|
||||
macro_rules! panictry {
|
||||
($e:expr) => {{
|
||||
use rustc_errors::FatalError;
|
||||
use std::result::Result::{Err, Ok};
|
||||
match $e {
|
||||
Ok(e) => e,
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
FatalError.raise()
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
mod placeholders;
|
||||
mod proc_macro_server;
|
||||
|
||||
|
@ -84,7 +84,7 @@ use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
|
||||
|
||||
use rustc_errors::{FatalError, PResult};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_span::Span;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
@ -271,6 +271,7 @@ crate enum ParseResult<T> {
|
||||
Failure(Token, &'static str),
|
||||
/// Fatal error (malformed macro?). Abort compilation.
|
||||
Error(rustc_span::Span, String),
|
||||
ErrorReported,
|
||||
}
|
||||
|
||||
/// A `ParseResult` where the `Success` variant contains a mapping of
|
||||
@ -652,6 +653,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
|
||||
Success(_) => {}
|
||||
Failure(token, msg) => return Failure(token, msg),
|
||||
Error(sp, msg) => return Error(sp, msg),
|
||||
ErrorReported => return ErrorReported,
|
||||
}
|
||||
|
||||
// inner parse loop handled all cur_items, so it's empty
|
||||
@ -735,10 +737,11 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
|
||||
let mut item = bb_items.pop().unwrap();
|
||||
if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
|
||||
let match_cur = item.match_cur;
|
||||
item.push_match(
|
||||
match_cur,
|
||||
MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))),
|
||||
);
|
||||
let nt = match parse_nt(parser.to_mut(), span, ident.name) {
|
||||
Err(()) => return ErrorReported,
|
||||
Ok(nt) => nt,
|
||||
};
|
||||
item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
|
||||
item.idx += 1;
|
||||
item.match_cur += 1;
|
||||
} else {
|
||||
@ -849,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
|
||||
/// # Returns
|
||||
///
|
||||
/// The parsed non-terminal.
|
||||
fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
|
||||
fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result<Nonterminal, ()> {
|
||||
// FIXME(Centril): Consider moving this to `parser.rs` to make
|
||||
// the visibilities of the methods used below `pub(super)` at most.
|
||||
|
||||
if name == sym::tt {
|
||||
return token::NtTT(p.parse_token_tree());
|
||||
}
|
||||
match parse_nt_inner(p, sp, name) {
|
||||
Ok(nt) => nt,
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
}
|
||||
return Ok(token::NtTT(p.parse_token_tree()));
|
||||
}
|
||||
parse_nt_inner(p, sp, name).map_err(|mut err| {
|
||||
err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name))
|
||||
.emit()
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> {
|
||||
|
@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF
|
||||
use crate::mbe;
|
||||
use crate::mbe::macro_check;
|
||||
use crate::mbe::macro_parser::parse_tt;
|
||||
use crate::mbe::macro_parser::{Error, Failure, Success};
|
||||
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success};
|
||||
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
|
||||
use crate::mbe::transcribe::transcribe;
|
||||
|
||||
@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{self as attr, TransparencyError};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_feature::Features;
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_session::parse::ParseSess;
|
||||
@ -83,41 +83,56 @@ fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Pa
|
||||
);
|
||||
}
|
||||
|
||||
fn emit_frag_parse_err(
|
||||
mut e: DiagnosticBuilder<'_>,
|
||||
parser: &Parser<'_>,
|
||||
site_span: Span,
|
||||
macro_ident: ast::Ident,
|
||||
arm_span: Span,
|
||||
kind: AstFragmentKind,
|
||||
) {
|
||||
if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") {
|
||||
if !e.span.is_dummy() {
|
||||
// early end of macro arm (#52866)
|
||||
e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
|
||||
}
|
||||
let msg = &e.message[0];
|
||||
e.message[0] = (
|
||||
format!(
|
||||
"macro expansion ends with an incomplete expression: {}",
|
||||
msg.0.replace(", found `<eof>`", ""),
|
||||
),
|
||||
msg.1,
|
||||
);
|
||||
}
|
||||
if e.span.is_dummy() {
|
||||
// Get around lack of span in error (#30128)
|
||||
e.replace_span_with(site_span);
|
||||
if !parser.sess.source_map().is_imported(arm_span) {
|
||||
e.span_label(arm_span, "in this macro arm");
|
||||
}
|
||||
} else if parser.sess.source_map().is_imported(parser.token.span) {
|
||||
e.span_label(site_span, "in this macro invocation");
|
||||
}
|
||||
match kind {
|
||||
AstFragmentKind::Pat if macro_ident.name == sym::vec => {
|
||||
suggest_slice_pat(&mut e, site_span, parser);
|
||||
}
|
||||
_ => annotate_err_with_kind(&mut e, kind, site_span),
|
||||
};
|
||||
e.emit();
|
||||
}
|
||||
|
||||
impl<'a> ParserAnyMacro<'a> {
|
||||
crate fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
|
||||
let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self;
|
||||
let fragment = panictry!(parse_ast_fragment(parser, kind).map_err(|mut e| {
|
||||
if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") {
|
||||
if !e.span.is_dummy() {
|
||||
// early end of macro arm (#52866)
|
||||
e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
|
||||
}
|
||||
let msg = &e.message[0];
|
||||
e.message[0] = (
|
||||
format!(
|
||||
"macro expansion ends with an incomplete expression: {}",
|
||||
msg.0.replace(", found `<eof>`", ""),
|
||||
),
|
||||
msg.1,
|
||||
);
|
||||
let fragment = match parse_ast_fragment(parser, kind) {
|
||||
Ok(f) => f,
|
||||
Err(err) => {
|
||||
emit_frag_parse_err(err, parser, site_span, macro_ident, arm_span, kind);
|
||||
return kind.dummy(site_span);
|
||||
}
|
||||
if e.span.is_dummy() {
|
||||
// Get around lack of span in error (#30128)
|
||||
e.replace_span_with(site_span);
|
||||
if !parser.sess.source_map().is_imported(arm_span) {
|
||||
e.span_label(arm_span, "in this macro arm");
|
||||
}
|
||||
} else if parser.sess.source_map().is_imported(parser.token.span) {
|
||||
e.span_label(site_span, "in this macro invocation");
|
||||
}
|
||||
match kind {
|
||||
AstFragmentKind::Pat if macro_ident.name == sym::vec => {
|
||||
suggest_slice_pat(&mut e, site_span, parser);
|
||||
}
|
||||
_ => annotate_err_with_kind(&mut e, kind, site_span),
|
||||
};
|
||||
e
|
||||
}));
|
||||
};
|
||||
|
||||
// We allow semicolons at the end of expressions -- e.g., the semicolon in
|
||||
// `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
|
||||
@ -165,6 +180,14 @@ impl TTMacroExpander for MacroRulesMacroExpander {
|
||||
}
|
||||
}
|
||||
|
||||
fn macro_rules_dummy_expander<'cx>(
|
||||
_: &'cx mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
_: TokenStream,
|
||||
) -> Box<dyn MacResult + 'cx> {
|
||||
DummyResult::any(span)
|
||||
}
|
||||
|
||||
fn trace_macros_note(cx_expansions: &mut FxHashMap<Span, Vec<String>>, sp: Span, message: String) {
|
||||
let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
|
||||
cx_expansions.entry(sp).or_default().push(message);
|
||||
@ -240,7 +263,13 @@ fn generic_extension<'cx>(
|
||||
|
||||
let rhs_spans = rhs.iter().map(|t| t.span()).collect::<Vec<_>>();
|
||||
// rhs has holes ( `$id` and `$(...)` that need filled)
|
||||
let mut tts = transcribe(cx, &named_matches, rhs, transparency);
|
||||
let mut tts = match transcribe(cx, &named_matches, rhs, transparency) {
|
||||
Ok(tts) => tts,
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(arm_span);
|
||||
}
|
||||
};
|
||||
|
||||
// Replace all the tokens for the corresponding positions in the macro, to maintain
|
||||
// proper positions in error reporting, while maintaining the macro_backtrace.
|
||||
@ -278,7 +307,12 @@ fn generic_extension<'cx>(
|
||||
Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {}
|
||||
_ => best_failure = Some((token, msg)),
|
||||
},
|
||||
Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]),
|
||||
Error(err_sp, ref msg) => {
|
||||
let span = err_sp.substitute_dummy(sp);
|
||||
cx.struct_span_err(span, &msg).emit();
|
||||
return DummyResult::any(span);
|
||||
}
|
||||
ErrorReported => return DummyResult::any(sp),
|
||||
}
|
||||
|
||||
// The matcher was not `Success(..)`ful.
|
||||
@ -337,6 +371,18 @@ pub fn compile_declarative_macro(
|
||||
def: &ast::Item,
|
||||
edition: Edition,
|
||||
) -> SyntaxExtension {
|
||||
let mk_syn_ext = |expander| {
|
||||
SyntaxExtension::new(
|
||||
sess,
|
||||
SyntaxExtensionKind::LegacyBang(expander),
|
||||
def.span,
|
||||
Vec::new(),
|
||||
edition,
|
||||
def.ident.name,
|
||||
&def.attrs,
|
||||
)
|
||||
};
|
||||
|
||||
let diag = &sess.span_diagnostic;
|
||||
let lhs_nm = ast::Ident::new(sym::lhs, def.span);
|
||||
let rhs_nm = ast::Ident::new(sym::rhs, def.span);
|
||||
@ -391,13 +437,15 @@ pub fn compile_declarative_macro(
|
||||
Failure(token, msg) => {
|
||||
let s = parse_failure_msg(&token);
|
||||
let sp = token.span.substitute_dummy(def.span);
|
||||
let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s);
|
||||
err.span_label(sp, msg);
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit();
|
||||
return mk_syn_ext(Box::new(macro_rules_dummy_expander));
|
||||
}
|
||||
Error(sp, s) => {
|
||||
sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise();
|
||||
Error(sp, msg) => {
|
||||
sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit();
|
||||
return mk_syn_ext(Box::new(macro_rules_dummy_expander));
|
||||
}
|
||||
ErrorReported => {
|
||||
return mk_syn_ext(Box::new(macro_rules_dummy_expander));
|
||||
}
|
||||
};
|
||||
|
||||
@ -460,24 +508,14 @@ pub fn compile_declarative_macro(
|
||||
None => {}
|
||||
}
|
||||
|
||||
let expander: Box<_> = Box::new(MacroRulesMacroExpander {
|
||||
mk_syn_ext(Box::new(MacroRulesMacroExpander {
|
||||
name: def.ident,
|
||||
span: def.span,
|
||||
transparency,
|
||||
lhses,
|
||||
rhses,
|
||||
valid,
|
||||
});
|
||||
|
||||
SyntaxExtension::new(
|
||||
sess,
|
||||
SyntaxExtensionKind::LegacyBang(expander),
|
||||
def.span,
|
||||
Vec::new(),
|
||||
edition,
|
||||
def.ident.name,
|
||||
&def.attrs,
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
fn check_lhs_nt_follows(
|
||||
|
@ -8,7 +8,7 @@ use rustc_ast::token::{self, NtTT, Token};
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::pluralize;
|
||||
use rustc_errors::{pluralize, PResult};
|
||||
use rustc_span::hygiene::{ExpnId, Transparency};
|
||||
use rustc_span::symbol::MacroRulesNormalizedIdent;
|
||||
use rustc_span::Span;
|
||||
@ -80,15 +80,15 @@ impl Iterator for Frame {
|
||||
/// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`.
|
||||
///
|
||||
/// Along the way, we do some additional error checking.
|
||||
pub(super) fn transcribe(
|
||||
cx: &ExtCtxt<'_>,
|
||||
pub(super) fn transcribe<'a>(
|
||||
cx: &ExtCtxt<'a>,
|
||||
interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
|
||||
src: Vec<mbe::TokenTree>,
|
||||
transparency: Transparency,
|
||||
) -> TokenStream {
|
||||
) -> PResult<'a, TokenStream> {
|
||||
// Nothing for us to transcribe...
|
||||
if src.is_empty() {
|
||||
return TokenStream::default();
|
||||
return Ok(TokenStream::default());
|
||||
}
|
||||
|
||||
// We descend into the RHS (`src`), expanding things as we go. This stack contains the things
|
||||
@ -152,7 +152,7 @@ pub(super) fn transcribe(
|
||||
Frame::Delimited { forest, span, .. } => {
|
||||
if result_stack.is_empty() {
|
||||
// No results left to compute! We are back at the top-level.
|
||||
return TokenStream::new(result);
|
||||
return Ok(TokenStream::new(result));
|
||||
}
|
||||
|
||||
// Step back into the parent Delimited.
|
||||
@ -173,11 +173,11 @@ pub(super) fn transcribe(
|
||||
seq @ mbe::TokenTree::Sequence(..) => {
|
||||
match lockstep_iter_size(&seq, interp, &repeats) {
|
||||
LockstepIterSize::Unconstrained => {
|
||||
cx.span_fatal(
|
||||
return Err(cx.struct_span_err(
|
||||
seq.span(), /* blame macro writer */
|
||||
"attempted to repeat an expression containing no syntax variables \
|
||||
matched as repeating at this depth",
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
LockstepIterSize::Contradiction(ref msg) => {
|
||||
@ -185,7 +185,7 @@ pub(super) fn transcribe(
|
||||
// happens when two meta-variables are used in the same repetition in a
|
||||
// sequence, but they come from different sequence matchers and repeat
|
||||
// different amounts.
|
||||
cx.span_fatal(seq.span(), &msg[..]);
|
||||
return Err(cx.struct_span_err(seq.span(), &msg[..]));
|
||||
}
|
||||
|
||||
LockstepIterSize::Constraint(len, _) => {
|
||||
@ -203,7 +203,10 @@ pub(super) fn transcribe(
|
||||
// FIXME: this really ought to be caught at macro definition
|
||||
// time... It happens when the Kleene operator in the matcher and
|
||||
// the body for the same meta-variable do not match.
|
||||
cx.span_fatal(sp.entire(), "this must repeat at least once");
|
||||
return Err(cx.struct_span_err(
|
||||
sp.entire(),
|
||||
"this must repeat at least once",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// 0 is the initial counter (we have done 0 repretitions so far). `len`
|
||||
@ -242,10 +245,10 @@ pub(super) fn transcribe(
|
||||
}
|
||||
} else {
|
||||
// We were unable to descend far enough. This is an error.
|
||||
cx.span_fatal(
|
||||
return Err(cx.struct_span_err(
|
||||
sp, /* blame the macro writer */
|
||||
&format!("variable '{}' is still repeating at this depth", ident),
|
||||
);
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// If we aren't able to match the meta-var, we push it back into the result but
|
||||
|
@ -5,7 +5,7 @@ use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::{self, TokenStream};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Applicability, FatalError};
|
||||
use rustc_errors::{Applicability, ErrorReported};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
@ -21,21 +21,16 @@ impl base::ProcMacro for BangProcMacro {
|
||||
ecx: &'cx mut ExtCtxt<'_>,
|
||||
span: Span,
|
||||
input: TokenStream,
|
||||
) -> TokenStream {
|
||||
) -> Result<TokenStream, ErrorReported> {
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
match self.client.run(&EXEC_STRATEGY, server, input) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let msg = "proc macro panicked";
|
||||
let mut err = ecx.struct_span_fatal(span, msg);
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
}
|
||||
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
self.client.run(&EXEC_STRATEGY, server, input).map_err(|e| {
|
||||
let mut err = ecx.struct_span_err(span, "proc macro panicked");
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
ErrorReported
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,21 +45,16 @@ impl base::AttrProcMacro for AttrProcMacro {
|
||||
span: Span,
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
) -> TokenStream {
|
||||
) -> Result<TokenStream, ErrorReported> {
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let msg = "custom attribute panicked";
|
||||
let mut err = ecx.struct_span_fatal(span, msg);
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
}
|
||||
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
self.client.run(&EXEC_STRATEGY, server, annotation, annotated).map_err(|e| {
|
||||
let mut err = ecx.struct_span_err(span, "custom attribute panicked");
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
ErrorReported
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,8 +86,7 @@ impl MultiItemModifier for ProcMacroDerive {
|
||||
| Annotatable::Expr(_) => {
|
||||
ecx.span_err(
|
||||
span,
|
||||
"proc-macro derives may only be \
|
||||
applied to a struct, enum, or union",
|
||||
"proc-macro derives may only be applied to a struct, enum, or union",
|
||||
);
|
||||
return ExpandResult::Ready(Vec::new());
|
||||
}
|
||||
@ -107,8 +96,7 @@ impl MultiItemModifier for ProcMacroDerive {
|
||||
_ => {
|
||||
ecx.span_err(
|
||||
span,
|
||||
"proc-macro derives may only be \
|
||||
applied to a struct, enum, or union",
|
||||
"proc-macro derives may only be applied to a struct, enum, or union",
|
||||
);
|
||||
return ExpandResult::Ready(Vec::new());
|
||||
}
|
||||
@ -121,20 +109,16 @@ impl MultiItemModifier for ProcMacroDerive {
|
||||
let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let msg = "proc-macro derive panicked";
|
||||
let mut err = ecx.struct_span_fatal(span, msg);
|
||||
let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
|
||||
if let Some(s) = e.as_str() {
|
||||
err.help(&format!("message: {}", s));
|
||||
}
|
||||
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
return ExpandResult::Ready(vec![]);
|
||||
}
|
||||
};
|
||||
|
||||
let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
|
||||
let msg = "proc-macro derive produced unparseable tokens";
|
||||
|
||||
let mut parser =
|
||||
rustc_parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
|
||||
let mut items = vec![];
|
||||
@ -144,18 +128,15 @@ impl MultiItemModifier for ProcMacroDerive {
|
||||
Ok(None) => break,
|
||||
Ok(Some(item)) => items.push(Annotatable::Item(item)),
|
||||
Err(mut err) => {
|
||||
// FIXME: handle this better
|
||||
err.cancel();
|
||||
ecx.struct_span_fatal(span, msg).emit();
|
||||
FatalError.raise();
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fail if there have been errors emitted
|
||||
if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
|
||||
ecx.struct_span_fatal(span, msg).emit();
|
||||
FatalError.raise();
|
||||
ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
|
||||
}
|
||||
|
||||
ExpandResult::Ready(items)
|
||||
|
@ -159,6 +159,7 @@ impl DefKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// The resolution of a path or export.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum Res<Id = hir::HirId> {
|
||||
|
@ -19,7 +19,7 @@ use rustc::traits::select;
|
||||
use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
||||
use rustc::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use rustc::ty::relate::RelateResult;
|
||||
use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
|
||||
use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
|
||||
pub use rustc::ty::IntVarValue;
|
||||
use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
|
||||
use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid};
|
||||
@ -501,6 +501,7 @@ impl NLLRegionVariableOrigin {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum FixupError<'tcx> {
|
||||
UnresolvedIntTy(IntVid),
|
||||
@ -1347,8 +1348,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
let mut r = ShallowResolver::new(self);
|
||||
value.fold_with(&mut r)
|
||||
value.fold_with(&mut ShallowResolver { infcx: self })
|
||||
}
|
||||
|
||||
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
@ -1551,22 +1551,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
// variables, thus we don't need to substitute back the original values.
|
||||
self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ShallowResolver<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
|
||||
#[inline(always)]
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
|
||||
ShallowResolver { infcx }
|
||||
}
|
||||
|
||||
/// If `typ` is a type variable of some kind, resolve it one level
|
||||
/// (but do not resolve types found in the result). If `typ` is
|
||||
/// not a type variable, just return it unmodified.
|
||||
pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
||||
// FIXME(eddyb) inline into `ShallowResolver::visit_ty`.
|
||||
fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match typ.kind {
|
||||
ty::Infer(ty::TyVar(v)) => {
|
||||
// Not entirely obvious: if `typ` is a type variable,
|
||||
@ -1580,78 +1570,142 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
|
||||
// depth.
|
||||
//
|
||||
// Note: if these two lines are combined into one we get
|
||||
// dynamic borrow errors on `self.infcx.inner`.
|
||||
let known = self.infcx.inner.borrow_mut().type_variables.probe(v).known();
|
||||
known.map(|t| self.fold_ty(t)).unwrap_or(typ)
|
||||
// dynamic borrow errors on `self.inner`.
|
||||
let known = self.inner.borrow_mut().type_variables.probe(v).known();
|
||||
known.map(|t| self.shallow_resolve_ty(t)).unwrap_or(typ)
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(v)) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.map(|v| v.to_type(self.tcx))
|
||||
.unwrap_or(typ),
|
||||
|
||||
ty::Infer(ty::FloatVar(v)) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.map(|v| v.to_type(self.tcx))
|
||||
.unwrap_or(typ),
|
||||
|
||||
_ => typ,
|
||||
}
|
||||
}
|
||||
|
||||
// `resolver.shallow_resolve_changed(ty)` is equivalent to
|
||||
// `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always
|
||||
// inlined, despite being large, because it has only two call sites that
|
||||
// are extremely hot.
|
||||
/// `ty_or_const_infer_var_changed` is equivalent to one of these two:
|
||||
/// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
|
||||
/// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
|
||||
///
|
||||
/// However, `ty_or_const_infer_var_changed` is more efficient. It's always
|
||||
/// inlined, despite being large, because it has only two call sites that
|
||||
/// are extremely hot (both in `traits::fulfill`'s checking of `stalled_on`
|
||||
/// inference variables), and it handles both `Ty` and `ty::Const` without
|
||||
/// having to resort to storing full `GenericArg`s in `stalled_on`.
|
||||
#[inline(always)]
|
||||
pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
|
||||
match infer {
|
||||
ty::TyVar(v) => {
|
||||
pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>) -> bool {
|
||||
match infer_var {
|
||||
TyOrConstInferVar::Ty(v) => {
|
||||
use self::type_variable::TypeVariableValue;
|
||||
|
||||
// If `inlined_probe` returns a `Known` value its `kind` never
|
||||
// matches `infer`.
|
||||
match self.infcx.inner.borrow_mut().type_variables.inlined_probe(v) {
|
||||
// If `inlined_probe` returns a `Known` value, it never equals
|
||||
// `ty::Infer(ty::TyVar(v))`.
|
||||
match self.inner.borrow_mut().type_variables.inlined_probe(v) {
|
||||
TypeVariableValue::Unknown { .. } => false,
|
||||
TypeVariableValue::Known { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
ty::IntVar(v) => {
|
||||
// If inlined_probe_value returns a value it's always a
|
||||
TyOrConstInferVar::TyInt(v) => {
|
||||
// If `inlined_probe_value` returns a value it's always a
|
||||
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
|
||||
// `ty::Infer(_)`.
|
||||
self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
|
||||
self.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
|
||||
}
|
||||
|
||||
ty::FloatVar(v) => {
|
||||
// If inlined_probe_value returns a value it's always a
|
||||
TyOrConstInferVar::TyFloat(v) => {
|
||||
// If `probe_value` returns a value it's always a
|
||||
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
|
||||
//
|
||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||
self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
|
||||
self.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
TyOrConstInferVar::Const(v) => {
|
||||
// If `probe_value` returns a `Known` value, it never equals
|
||||
// `ty::ConstKind::Infer(ty::InferConst::Var(v))`.
|
||||
//
|
||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||
match self.inner.borrow_mut().const_unification_table.probe_value(v).val {
|
||||
ConstVariableValue::Unknown { .. } => false,
|
||||
ConstVariableValue::Known { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper for `ty_or_const_infer_var_changed` (see comment on that), currently
|
||||
/// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum TyOrConstInferVar<'tcx> {
|
||||
/// Equivalent to `ty::Infer(ty::TyVar(_))`.
|
||||
Ty(TyVid),
|
||||
/// Equivalent to `ty::Infer(ty::IntVar(_))`.
|
||||
TyInt(IntVid),
|
||||
/// Equivalent to `ty::Infer(ty::FloatVar(_))`.
|
||||
TyFloat(FloatVid),
|
||||
|
||||
/// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`.
|
||||
Const(ConstVid<'tcx>),
|
||||
}
|
||||
|
||||
impl TyOrConstInferVar<'tcx> {
|
||||
/// Tries to extract an inference variable from a type or a constant, returns `None`
|
||||
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
|
||||
/// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
|
||||
pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option<Self> {
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
|
||||
GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
|
||||
GenericArgKind::Lifetime(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to extract an inference variable from a type, returns `None`
|
||||
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`).
|
||||
pub fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> {
|
||||
match ty.kind {
|
||||
ty::Infer(ty::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
|
||||
ty::Infer(ty::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
|
||||
ty::Infer(ty::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to extract an inference variable from a constant, returns `None`
|
||||
/// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
|
||||
pub fn maybe_from_const(ct: &'tcx ty::Const<'tcx>) -> Option<Self> {
|
||||
match ct.val {
|
||||
ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ShallowResolver<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
|
||||
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.shallow_resolve(ty)
|
||||
self.infcx.shallow_resolve_ty(ty)
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
|
@ -509,14 +509,6 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecializedDecoder<Ident> for DecodeContext<'_, '_> {
|
||||
fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
|
||||
// FIXME(jseyfried): intercrate hygiene
|
||||
|
||||
Ok(Ident::with_dummy_span(Symbol::decode(self)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
|
||||
Fingerprint::decode_opaque(&mut self.opaque)
|
||||
@ -663,15 +655,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
&self.raw_proc_macros.unwrap()[pos]
|
||||
}
|
||||
|
||||
fn item_name(&self, item_index: DefIndex) -> Symbol {
|
||||
fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
|
||||
if !self.is_proc_macro(item_index) {
|
||||
self.def_key(item_index)
|
||||
let name = self
|
||||
.def_key(item_index)
|
||||
.disambiguated_data
|
||||
.data
|
||||
.get_opt_name()
|
||||
.expect("no name in item_name")
|
||||
.expect("no name in item_ident");
|
||||
let span = self
|
||||
.root
|
||||
.per_def
|
||||
.ident_span
|
||||
.get(self, item_index)
|
||||
.map(|data| data.decode((self, sess)))
|
||||
.unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
|
||||
Ident::new(name, span)
|
||||
} else {
|
||||
Symbol::intern(self.raw_proc_macro(item_index).name())
|
||||
Ident::new(
|
||||
Symbol::intern(self.raw_proc_macro(item_index).name()),
|
||||
self.get_span(item_index, sess),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,6 +754,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
kind: &EntryKind,
|
||||
index: DefIndex,
|
||||
parent_did: DefId,
|
||||
sess: &Session,
|
||||
) -> ty::VariantDef {
|
||||
let data = match kind {
|
||||
EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => {
|
||||
@ -771,7 +776,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
|
||||
ty::VariantDef::new(
|
||||
tcx,
|
||||
Ident::with_dummy_span(self.item_name(index)),
|
||||
self.item_ident(index, sess),
|
||||
variant_did,
|
||||
ctor_did,
|
||||
data.discr,
|
||||
@ -783,7 +788,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
.decode(self)
|
||||
.map(|index| ty::FieldDef {
|
||||
did: self.local_def_id(index),
|
||||
ident: Ident::with_dummy_span(self.item_name(index)),
|
||||
ident: self.item_ident(index, sess),
|
||||
vis: self.get_visibility(index),
|
||||
})
|
||||
.collect(),
|
||||
@ -812,10 +817,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
.get(self, item_id)
|
||||
.unwrap_or(Lazy::empty())
|
||||
.decode(self)
|
||||
.map(|index| self.get_variant(tcx, &self.kind(index), index, did))
|
||||
.map(|index| self.get_variant(tcx, &self.kind(index), index, did, tcx.sess))
|
||||
.collect()
|
||||
} else {
|
||||
std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect()
|
||||
std::iter::once(self.get_variant(tcx, &kind, item_id, did, tcx.sess)).collect()
|
||||
};
|
||||
|
||||
tcx.alloc_adt_def(did, adt_kind, variants, repr)
|
||||
@ -1007,7 +1012,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
if let Some(kind) = self.def_kind(child_index) {
|
||||
callback(Export {
|
||||
res: Res::Def(kind, self.local_def_id(child_index)),
|
||||
ident: Ident::with_dummy_span(self.item_name(child_index)),
|
||||
ident: self.item_ident(child_index, sess),
|
||||
vis: self.get_visibility(child_index),
|
||||
span: self
|
||||
.root
|
||||
@ -1028,10 +1033,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
|
||||
let def_key = self.def_key(child_index);
|
||||
let span = self.get_span(child_index, sess);
|
||||
if let (Some(kind), Some(name)) =
|
||||
(self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name())
|
||||
{
|
||||
let ident = Ident::with_dummy_span(name);
|
||||
if let (Some(kind), true) = (
|
||||
self.def_kind(child_index),
|
||||
def_key.disambiguated_data.data.get_opt_name().is_some(),
|
||||
) {
|
||||
let ident = self.item_ident(child_index, sess);
|
||||
let vis = self.get_visibility(child_index);
|
||||
let def_id = self.local_def_id(child_index);
|
||||
let res = Res::Def(kind, def_id);
|
||||
@ -1138,10 +1144,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem {
|
||||
fn get_associated_item(&self, id: DefIndex, sess: &Session) -> ty::AssocItem {
|
||||
let def_key = self.def_key(id);
|
||||
let parent = self.local_def_id(def_key.parent.unwrap());
|
||||
let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
|
||||
let ident = self.item_ident(id, sess);
|
||||
|
||||
let (kind, container, has_self) = match self.kind(id) {
|
||||
EntryKind::AssocConst(container, _, _) => (ty::AssocKind::Const, container, false),
|
||||
@ -1155,7 +1161,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
};
|
||||
|
||||
ty::AssocItem {
|
||||
ident: Ident::with_dummy_span(name),
|
||||
ident,
|
||||
kind,
|
||||
vis: self.get_visibility(id),
|
||||
defaultness: container.defaultness(),
|
||||
@ -1219,7 +1225,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
.get(self, id)
|
||||
.unwrap_or(Lazy::empty())
|
||||
.decode(self)
|
||||
.map(|index| respan(self.get_span(index, sess), self.item_name(index)))
|
||||
.map(|index| respan(self.get_span(index, sess), self.item_ident(index, sess).name))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
|child| result.push(child.res.def_id()), tcx.sess);
|
||||
tcx.arena.alloc_slice(&result)
|
||||
}
|
||||
associated_item => { cdata.get_associated_item(def_id.index) }
|
||||
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
|
||||
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
|
||||
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
|
||||
coerce_unsized_info => {
|
||||
@ -442,8 +442,8 @@ impl CStore {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem {
|
||||
self.get_crate_data(def.krate).get_associated_item(def.index)
|
||||
pub fn associated_item_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::AssocItem {
|
||||
self.get_crate_data(def.krate).get_associated_item(def.index, sess)
|
||||
}
|
||||
|
||||
pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource {
|
||||
|
@ -12,7 +12,7 @@ use rustc::traits::specialization_graph;
|
||||
use rustc::ty::codec::{self as ty_codec, TyEncoder};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::ty::{self, SymbolName, Ty, TyCtxt};
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::ast::{self, Ident};
|
||||
use rustc_ast::attr;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -30,7 +30,7 @@ use rustc_index::vec::Idx;
|
||||
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
|
||||
use rustc_session::config::{self, CrateType};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
|
||||
use std::hash::Hash;
|
||||
use std::num::NonZeroUsize;
|
||||
@ -220,13 +220,6 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecializedEncoder<Ident> for EncodeContext<'tcx> {
|
||||
fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> {
|
||||
// FIXME(jseyfried): intercrate hygiene
|
||||
ident.name.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
|
||||
@ -633,6 +626,7 @@ impl EncodeContext<'tcx> {
|
||||
assert!(f.did.is_local());
|
||||
f.did.index
|
||||
}));
|
||||
self.encode_ident_span(def_id, variant.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
self.encode_item_type(def_id);
|
||||
@ -735,6 +729,7 @@ impl EncodeContext<'tcx> {
|
||||
record!(self.per_def.visibility[def_id] <- field.vis);
|
||||
record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
|
||||
record!(self.per_def.attributes[def_id] <- variant_data.fields()[field_index].attrs);
|
||||
self.encode_ident_span(def_id, field.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
self.encode_item_type(def_id);
|
||||
@ -869,6 +864,7 @@ impl EncodeContext<'tcx> {
|
||||
record!(self.per_def.visibility[def_id] <- trait_item.vis);
|
||||
record!(self.per_def.span[def_id] <- ast_item.span);
|
||||
record!(self.per_def.attributes[def_id] <- ast_item.attrs);
|
||||
self.encode_ident_span(def_id, ast_item.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_const_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
@ -952,6 +948,7 @@ impl EncodeContext<'tcx> {
|
||||
record!(self.per_def.visibility[def_id] <- impl_item.vis);
|
||||
record!(self.per_def.span[def_id] <- ast_item.span);
|
||||
record!(self.per_def.attributes[def_id] <- ast_item.attrs);
|
||||
self.encode_ident_span(def_id, impl_item.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_const_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
@ -1058,6 +1055,8 @@ impl EncodeContext<'tcx> {
|
||||
|
||||
debug!("EncodeContext::encode_info_for_item({:?})", def_id);
|
||||
|
||||
self.encode_ident_span(def_id, item.ident);
|
||||
|
||||
record!(self.per_def.kind[def_id] <- match item.kind {
|
||||
hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic,
|
||||
hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic,
|
||||
@ -1284,6 +1283,7 @@ impl EncodeContext<'tcx> {
|
||||
record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
|
||||
record!(self.per_def.span[def_id] <- macro_def.span);
|
||||
record!(self.per_def.attributes[def_id] <- macro_def.attrs);
|
||||
self.encode_ident_span(def_id, macro_def.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
}
|
||||
@ -1528,6 +1528,7 @@ impl EncodeContext<'tcx> {
|
||||
ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx));
|
||||
record!(self.per_def.span[def_id] <- nitem.span);
|
||||
record!(self.per_def.attributes[def_id] <- nitem.attrs);
|
||||
self.encode_ident_span(def_id, nitem.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_const_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
@ -1622,6 +1623,10 @@ impl EncodeContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_ident_span(&mut self, def_id: DefId, ident: Ident) {
|
||||
record!(self.per_def.ident_span[def_id] <- ident.span);
|
||||
}
|
||||
|
||||
/// In some cases, along with the item itself, we also
|
||||
/// encode some sub-items. Usually we want some info from the item
|
||||
/// so it's easier to do that here then to wait until we would encounter
|
||||
|
@ -256,6 +256,7 @@ define_per_def_tables! {
|
||||
kind: Table<DefIndex, Lazy<EntryKind>>,
|
||||
visibility: Table<DefIndex, Lazy<ty::Visibility>>,
|
||||
span: Table<DefIndex, Lazy<Span>>,
|
||||
ident_span: Table<DefIndex, Lazy<Span>>,
|
||||
attributes: Table<DefIndex, Lazy<[ast::Attribute]>>,
|
||||
children: Table<DefIndex, Lazy<[DefIndex]>>,
|
||||
stability: Table<DefIndex, Lazy<attr::Stability>>,
|
||||
|
@ -337,14 +337,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
) -> ConstPropagator<'mir, 'tcx> {
|
||||
let def_id = source.def_id();
|
||||
let substs = &InternalSubsts::identity_for_item(tcx, def_id);
|
||||
let mut param_env = tcx.param_env(def_id);
|
||||
|
||||
// If we're evaluating inside a monomorphic function, then use `Reveal::All` because
|
||||
// we want to see the same instances that codegen will see. This allows us to `resolve()`
|
||||
// specializations.
|
||||
if !substs.needs_subst() {
|
||||
param_env = param_env.with_reveal_all();
|
||||
}
|
||||
let param_env = tcx.param_env(def_id).with_reveal_all();
|
||||
|
||||
let span = tcx.def_span(def_id);
|
||||
let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ());
|
||||
|
@ -3,8 +3,8 @@
|
||||
use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc::mir::visit::*;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::subst::{Subst, SubstsRef};
|
||||
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_attr as attr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
@ -66,14 +66,7 @@ impl Inliner<'tcx> {
|
||||
|
||||
let mut callsites = VecDeque::new();
|
||||
|
||||
let mut param_env = self.tcx.param_env(self.source.def_id());
|
||||
|
||||
let substs = &InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
|
||||
|
||||
// For monomorphic functions, we can use `Reveal::All` to resolve specialized instances.
|
||||
if !substs.needs_subst() {
|
||||
param_env = param_env.with_reveal_all();
|
||||
}
|
||||
let param_env = self.tcx.param_env(self.source.def_id()).with_reveal_all();
|
||||
|
||||
// Only do inlining into fn bodies.
|
||||
let id = self.tcx.hir().as_local_hir_id(self.source.def_id()).unwrap();
|
||||
|
@ -139,7 +139,8 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
|
||||
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
||||
|
||||
let (yield_ty, return_ty) = if body.generator_kind.is_some() {
|
||||
let gen_sig = match ty.kind {
|
||||
let gen_ty = tcx.body_tables(body_id).node_type(id);
|
||||
let gen_sig = match gen_ty.kind {
|
||||
ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
|
||||
_ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty),
|
||||
};
|
||||
|
@ -904,7 +904,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
self.insert_field_names(def_id, field_names);
|
||||
}
|
||||
Res::Def(DefKind::AssocFn, def_id) => {
|
||||
if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
|
||||
if cstore
|
||||
.associated_item_cloned_untracked(def_id, self.r.session)
|
||||
.method_has_self_argument
|
||||
{
|
||||
self.r.has_self.insert(def_id);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::infer::{InferCtxt, ShallowResolver};
|
||||
use crate::infer::{InferCtxt, TyOrConstInferVar};
|
||||
use rustc::ty::error::ExpectedFound;
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable};
|
||||
use rustc_data_structures::obligation_forest::ProcessResult;
|
||||
@ -73,7 +73,10 @@ pub struct FulfillmentContext<'tcx> {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PendingPredicateObligation<'tcx> {
|
||||
pub obligation: PredicateObligation<'tcx>,
|
||||
pub stalled_on: Vec<ty::InferTy>,
|
||||
// FIXME(eddyb) look into whether this could be a `SmallVec`.
|
||||
// Judging by the comment in `process_obligation`, the 1-element case
|
||||
// is common so this could be a `SmallVec<[TyOrConstInferVar<'tcx>; 1]>`.
|
||||
pub stalled_on: Vec<TyOrConstInferVar<'tcx>>,
|
||||
}
|
||||
|
||||
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
@ -266,8 +269,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
// Match arms are in order of frequency, which matters because this
|
||||
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
|
||||
1 => {
|
||||
let infer = pending_obligation.stalled_on[0];
|
||||
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
|
||||
let infer_var = pending_obligation.stalled_on[0];
|
||||
self.selcx.infcx().ty_or_const_infer_var_changed(infer_var)
|
||||
}
|
||||
0 => {
|
||||
// In this case we haven't changed, but wish to make a change.
|
||||
@ -277,8 +280,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
// This `for` loop was once a call to `all()`, but this lower-level
|
||||
// form was a perf win. See #64545 for details.
|
||||
(|| {
|
||||
for &infer in &pending_obligation.stalled_on {
|
||||
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
|
||||
for &infer_var in &pending_obligation.stalled_on {
|
||||
if self.selcx.infcx().ty_or_const_infer_var_changed(infer_var) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -309,13 +312,6 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
|
||||
debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
|
||||
|
||||
fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
|
||||
match ty.kind {
|
||||
ty::Infer(infer) => infer,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
match obligation.predicate {
|
||||
ty::Predicate::Trait(ref data, _) => {
|
||||
let trait_obligation = obligation.with(data.clone());
|
||||
@ -467,7 +463,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
obligation.cause.span,
|
||||
) {
|
||||
None => {
|
||||
pending_obligation.stalled_on = vec![infer_ty(ty)];
|
||||
pending_obligation.stalled_on =
|
||||
vec![TyOrConstInferVar::maybe_from_ty(ty).unwrap()];
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
Some(os) => ProcessResult::Changed(mk_pending(os)),
|
||||
@ -483,8 +480,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
None => {
|
||||
// None means that both are unresolved.
|
||||
pending_obligation.stalled_on = vec![
|
||||
infer_ty(subtype.skip_binder().a),
|
||||
infer_ty(subtype.skip_binder().b),
|
||||
TyOrConstInferVar::maybe_from_ty(subtype.skip_binder().a).unwrap(),
|
||||
TyOrConstInferVar::maybe_from_ty(subtype.skip_binder().b).unwrap(),
|
||||
];
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
@ -534,20 +531,23 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the set of type variables contained in a trait ref
|
||||
/// Returns the set of type inference variables contained in a trait ref.
|
||||
fn trait_ref_type_vars<'a, 'tcx>(
|
||||
selcx: &mut SelectionContext<'a, 'tcx>,
|
||||
t: ty::PolyTraitRef<'tcx>,
|
||||
) -> Vec<ty::InferTy> {
|
||||
t.skip_binder() // ok b/c this check doesn't care about regions
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Vec<TyOrConstInferVar<'tcx>> {
|
||||
trait_ref
|
||||
.skip_binder() // ok b/c this check doesn't care about regions
|
||||
// FIXME(eddyb) walk over `GenericArg` to support const infer vars.
|
||||
.input_types()
|
||||
.map(|t| selcx.infcx().resolve_vars_if_possible(&t))
|
||||
.filter(|t| t.has_infer_types())
|
||||
.flat_map(|t| t.walk())
|
||||
.filter_map(|t| match t.kind {
|
||||
ty::Infer(infer) => Some(infer),
|
||||
_ => None,
|
||||
})
|
||||
.map(|ty| selcx.infcx().resolve_vars_if_possible(&ty))
|
||||
// FIXME(eddyb) try using `maybe_walk` to skip *all* subtrees that
|
||||
// don't contain inference variables, not just the outermost level.
|
||||
// FIXME(eddyb) use `has_infer_types_or_const`.
|
||||
.filter(|ty| ty.has_infer_types())
|
||||
.flat_map(|ty| ty.walk())
|
||||
// FIXME(eddyb) use `TyOrConstInferVar::maybe_from_generic_arg`.
|
||||
.filter_map(TyOrConstInferVar::maybe_from_ty)
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -188,12 +188,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
Node::Field(field) => icx.to_ty(&field.ty),
|
||||
|
||||
Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => {
|
||||
if gen.is_some() {
|
||||
return tcx.typeck_tables_of(def_id).node_type(hir_id);
|
||||
}
|
||||
|
||||
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
tcx.mk_closure(def_id, substs)
|
||||
if let Some(movability) = gen {
|
||||
tcx.mk_generator(def_id, substs, movability)
|
||||
} else {
|
||||
tcx.mk_closure(def_id, substs)
|
||||
}
|
||||
}
|
||||
|
||||
Node::AnonConst(_) => {
|
||||
@ -235,29 +235,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
};
|
||||
|
||||
if let Some(path) = path {
|
||||
let arg_index = path
|
||||
// We've encountered an `AnonConst` in some path, so we need to
|
||||
// figure out which generic parameter it corresponds to and return
|
||||
// the relevant type.
|
||||
|
||||
let (arg_index, segment) = path
|
||||
.segments
|
||||
.iter()
|
||||
.filter_map(|seg| seg.args.as_ref())
|
||||
.map(|generic_args| generic_args.args)
|
||||
.find_map(|args| {
|
||||
.filter_map(|seg| seg.args.as_ref().map(|args| (args.args, seg)))
|
||||
.find_map(|(args, seg)| {
|
||||
args.iter()
|
||||
.filter(|arg| arg.is_const())
|
||||
.enumerate()
|
||||
.filter(|(_, arg)| arg.id() == hir_id)
|
||||
.map(|(index, _)| index)
|
||||
.map(|(index, _)| (index, seg))
|
||||
.next()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
bug!("no arg matching AnonConst in path");
|
||||
});
|
||||
|
||||
// We've encountered an `AnonConst` in some path, so we need to
|
||||
// figure out which generic parameter it corresponds to and return
|
||||
// the relevant type.
|
||||
let generics = match path.res {
|
||||
Res::Def(DefKind::Ctor(..), def_id)
|
||||
| Res::Def(DefKind::AssocTy, def_id) => {
|
||||
// Try to use the segment resolution if it is valid, otherwise we
|
||||
// default to the path resolution.
|
||||
let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
|
||||
let generics = match res {
|
||||
Res::Def(DefKind::Ctor(..), def_id) => {
|
||||
tcx.generics_of(tcx.parent(def_id).unwrap())
|
||||
}
|
||||
Res::Def(_, def_id) => tcx.generics_of(def_id),
|
||||
@ -265,8 +267,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!(
|
||||
"unexpected const parent path def, parent: {:?}, def: {:?}",
|
||||
parent_node, res
|
||||
"unexpected anon const res {:?} in path: {:?}",
|
||||
res, path,
|
||||
),
|
||||
);
|
||||
return tcx.types.err;
|
||||
@ -291,8 +293,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!(
|
||||
"missing generic parameter for `AnonConst`, parent {:?}",
|
||||
parent_node
|
||||
"missing generic parameter for `AnonConst`, parent: {:?}, res: {:?}",
|
||||
parent_node, res
|
||||
),
|
||||
);
|
||||
tcx.types.err
|
||||
|
@ -62,6 +62,7 @@ This API is completely unstable and subject to change.
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(never_type)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
|
64
src/test/mir-opt/const_prop/control-flow-simplification.rs
Normal file
64
src/test/mir-opt/const_prop/control-flow-simplification.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// compile-flags: -Zmir-opt-level=1
|
||||
|
||||
trait NeedsDrop:Sized{
|
||||
const NEEDS:bool=std::mem::needs_drop::<Self>();
|
||||
}
|
||||
|
||||
impl<This> NeedsDrop for This{}
|
||||
|
||||
fn hello<T>(){
|
||||
if <bool>::NEEDS {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
hello::<()>();
|
||||
hello::<Vec<()>>();
|
||||
}
|
||||
|
||||
// END RUST SOURCE
|
||||
// START rustc.hello.ConstProp.before.mir
|
||||
// let mut _0: ();
|
||||
// let mut _1: bool;
|
||||
// let mut _2: !;
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// _1 = const <bool as NeedsDrop>::NEEDS;
|
||||
// switchInt(_1) -> [false: bb1, otherwise: bb2];
|
||||
// }
|
||||
// bb1: {
|
||||
// _0 = ();
|
||||
// StorageDead(_1);
|
||||
// return;
|
||||
// }
|
||||
// bb2: {
|
||||
// StorageLive(_2);
|
||||
// const std::rt::begin_panic::<&str>(const "explicit panic");
|
||||
// }
|
||||
// END rustc.hello.ConstProp.before.mir
|
||||
// START rustc.hello.ConstProp.after.mir
|
||||
// let mut _0: ();
|
||||
// let mut _1: bool;
|
||||
// let mut _2: !;
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// _1 = const false;
|
||||
// switchInt(const false) -> [false: bb1, otherwise: bb2];
|
||||
// }
|
||||
// bb1: {
|
||||
// _0 = ();
|
||||
// StorageDead(_1);
|
||||
// return;
|
||||
// }
|
||||
// bb2: {
|
||||
// StorageLive(_2);
|
||||
// const std::rt::begin_panic::<&str>(const "explicit panic");
|
||||
// }
|
||||
// END rustc.hello.ConstProp.after.mir
|
||||
// START rustc.hello.PreCodegen.before.mir
|
||||
// let mut _0: ();
|
||||
// bb0: {
|
||||
// return;
|
||||
// }
|
||||
// END rustc.hello.PreCodegen.before.mir
|
@ -18,22 +18,6 @@ LL | | break 0u8;
|
||||
LL | | };
|
||||
| |_________- enclosing `async` block
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:13:43
|
||||
|
|
||||
LL | fn return_targets_async_block_not_fn() -> u8 {
|
||||
| --------------------------------- ^^ expected `u8`, found `()`
|
||||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
|
||||
error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == ()`
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:18:39
|
||||
|
|
||||
LL | let _: &dyn Future<Output = ()> = █
|
||||
| ^^^^^^ expected `()`, found `u8`
|
||||
|
|
||||
= note: required for the cast to the object type `dyn std::future::Future<Output = ()>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:22:58
|
||||
|
|
||||
@ -55,6 +39,22 @@ LL | let _: &dyn Future<Output = ()> = █
|
||||
|
|
||||
= note: required for the cast to the object type `dyn std::future::Future<Output = ()>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:13:43
|
||||
|
|
||||
LL | fn return_targets_async_block_not_fn() -> u8 {
|
||||
| --------------------------------- ^^ expected `u8`, found `()`
|
||||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
|
||||
error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == ()`
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:18:39
|
||||
|
|
||||
LL | let _: &dyn Future<Output = ()> = █
|
||||
| ^^^^^^ expected `()`, found `u8`
|
||||
|
|
||||
= note: required for the cast to the object type `dyn std::future::Future<Output = ()>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:48:44
|
||||
|
|
||||
|
@ -5,6 +5,7 @@
|
||||
use std::future::Future;
|
||||
|
||||
fn get_future() -> impl Future<Output = ()> {
|
||||
//~^ ERROR the trait bound `(): std::future::Future` is not satisfied
|
||||
panic!()
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,27 @@
|
||||
error[E0277]: the trait bound `(): std::future::Future` is not satisfied
|
||||
--> $DIR/async-error-span.rs:7:20
|
||||
|
|
||||
LL | fn get_future() -> impl Future<Output = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `()`
|
||||
LL |
|
||||
LL | panic!()
|
||||
| -------- this returned value is of type `!`
|
||||
|
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0698]: type inside `async fn` body must be known in this context
|
||||
--> $DIR/async-error-span.rs:12:9
|
||||
--> $DIR/async-error-span.rs:13:9
|
||||
|
|
||||
LL | let a;
|
||||
| ^ cannot infer type
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/async-error-span.rs:13:5
|
||||
--> $DIR/async-error-span.rs:14:5
|
||||
|
|
||||
LL | get_future().await;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0698`.
|
||||
Some errors have detailed explanations: E0277, E0698.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -62,6 +62,7 @@ fn foo10() -> Result<(), ()> {
|
||||
fn foo11() -> Result<(), ()> {
|
||||
let _ = await bar()?; //~ ERROR `await` is only allowed inside `async` functions and blocks
|
||||
//~^ ERROR incorrect use of `await`
|
||||
//~| ERROR the `?` operator can only be applied to values that implement `std::ops::Try`
|
||||
Ok(())
|
||||
}
|
||||
fn foo12() -> Result<(), ()> {
|
||||
|
@ -71,49 +71,49 @@ LL | let _ = await bar()?;
|
||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:68:14
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:69:14
|
||||
|
|
||||
LL | let _ = (await bar())?;
|
||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:73:24
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:74:24
|
||||
|
|
||||
LL | let _ = bar().await();
|
||||
| ^^ help: `await` is not a method call, remove the parentheses
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:78:24
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:79:24
|
||||
|
|
||||
LL | let _ = bar().await()?;
|
||||
| ^^ help: `await` is not a method call, remove the parentheses
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:106:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:107:13
|
||||
|
|
||||
LL | let _ = await!(bar());
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:110:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:111:13
|
||||
|
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:115:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:116:17
|
||||
|
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:123:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:124:17
|
||||
|
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: expected expression, found `=>`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:131:25
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:132:25
|
||||
|
|
||||
LL | match await { await => () }
|
||||
| ----- ^^ expected expression
|
||||
@ -121,13 +121,13 @@ LL | match await { await => () }
|
||||
| while parsing this incorrect await expression
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:131:11
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:132:11
|
||||
|
|
||||
LL | match await { await => () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
|
||||
|
||||
error: expected one of `.`, `?`, `{`, or an operator, found `}`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:134:1
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:135:1
|
||||
|
|
||||
LL | match await { await => () }
|
||||
| ----- - expected one of `.`, `?`, `{`, or an operator
|
||||
@ -162,7 +162,7 @@ LL | let _ = await bar()?;
|
||||
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:68:14
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:69:14
|
||||
|
|
||||
LL | fn foo12() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -170,7 +170,7 @@ LL | let _ = (await bar())?;
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:73:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:74:13
|
||||
|
|
||||
LL | fn foo13() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -178,7 +178,7 @@ LL | let _ = bar().await();
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:78:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:79:13
|
||||
|
|
||||
LL | fn foo14() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -186,7 +186,7 @@ LL | let _ = bar().await()?;
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:83:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:84:13
|
||||
|
|
||||
LL | fn foo15() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -194,7 +194,7 @@ LL | let _ = bar().await;
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:87:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:88:13
|
||||
|
|
||||
LL | fn foo16() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -202,7 +202,7 @@ LL | let _ = bar().await?;
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:92:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:93:17
|
||||
|
|
||||
LL | fn foo() -> Result<(), ()> {
|
||||
| --- this is not `async`
|
||||
@ -210,7 +210,7 @@ LL | let _ = bar().await?;
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:99:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:100:17
|
||||
|
|
||||
LL | let foo = || {
|
||||
| -- this is not `async`
|
||||
@ -218,7 +218,7 @@ LL | let _ = bar().await?;
|
||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:115:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:116:17
|
||||
|
|
||||
LL | fn foo() -> Result<(), ()> {
|
||||
| --- this is not `async`
|
||||
@ -226,7 +226,7 @@ LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:123:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:124:17
|
||||
|
|
||||
LL | let foo = || {
|
||||
| -- this is not `async`
|
||||
@ -242,7 +242,16 @@ LL | let _ = await bar()?;
|
||||
= help: the trait `std::ops::Try` is not implemented for `impl std::future::Future`
|
||||
= note: required by `std::ops::Try::into_result`
|
||||
|
||||
error: aborting due to 35 previous errors
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:63:19
|
||||
|
|
||||
LL | let _ = await bar()?;
|
||||
| ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future`
|
||||
|
|
||||
= help: the trait `std::ops::Try` is not implemented for `impl std::future::Future`
|
||||
= note: required by `std::ops::Try::into_result`
|
||||
|
||||
error: aborting due to 36 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0728.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
20
src/test/ui/async-await/issue-67651.rs
Normal file
20
src/test/ui/async-await/issue-67651.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// edition:2018
|
||||
|
||||
trait From {
|
||||
fn from();
|
||||
}
|
||||
|
||||
impl From for () {
|
||||
fn from() {}
|
||||
}
|
||||
|
||||
impl From for () {
|
||||
//~^ ERROR conflicting implementations of trait
|
||||
fn from() {}
|
||||
}
|
||||
|
||||
fn bar() -> impl core::future::Future<Output = ()> {
|
||||
async move { From::from() }
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/async-await/issue-67651.stderr
Normal file
12
src/test/ui/async-await/issue-67651.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0119]: conflicting implementations of trait `From` for type `()`:
|
||||
--> $DIR/issue-67651.rs:11:1
|
||||
|
|
||||
LL | impl From for () {
|
||||
| ---------------- first implementation here
|
||||
...
|
||||
LL | impl From for () {
|
||||
| ^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -1,13 +0,0 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/issue-63388-2.rs:12:10
|
||||
|
|
||||
LL | foo: &dyn Foo, bar: &'a dyn Foo
|
||||
| -------- -----------
|
||||
LL | ) -> &dyn Foo
|
||||
| ^ help: consider using the named lifetime: `&'a`
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
@ -8,7 +8,7 @@ trait Foo {}
|
||||
|
||||
impl Xyz {
|
||||
async fn do_sth<'a>(
|
||||
foo: &dyn Foo, bar: &'a dyn Foo //~ ERROR cannot infer
|
||||
foo: &dyn Foo, bar: &'a dyn Foo
|
||||
) -> &dyn Foo //~ ERROR missing lifetime specifier
|
||||
{
|
||||
foo
|
||||
|
@ -8,21 +8,6 @@ LL | ) -> &dyn Foo
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
|
||||
|
||||
error: cannot infer an appropriate lifetime
|
||||
--> $DIR/issue-63388-2.rs:11:9
|
||||
|
|
||||
LL | foo: &dyn Foo, bar: &'a dyn Foo
|
||||
| ^^^ ...but this borrow...
|
||||
...
|
||||
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
|
||||
--> $DIR/issue-63388-2.rs:11:14
|
||||
|
|
||||
LL | foo: &dyn Foo, bar: &'a dyn Foo
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
|
@ -5,6 +5,7 @@
|
||||
async fn copy() -> Result<()> //~ ERROR wrong number of type arguments
|
||||
{
|
||||
Ok(())
|
||||
//~^ type annotations needed
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -4,6 +4,13 @@ error[E0107]: wrong number of type arguments: expected 2, found 1
|
||||
LL | async fn copy() -> Result<()>
|
||||
| ^^^^^^^^^^ expected 2 type arguments
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-65159.rs:7:5
|
||||
|
|
||||
LL | Ok(())
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0282.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
|
@ -9,6 +9,9 @@ impl<T> Trait<'_, '_> for T { }
|
||||
async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
//~^ ERROR ambiguous lifetime bound
|
||||
//~| ERROR ambiguous lifetime bound
|
||||
//~| ERROR ambiguous lifetime bound
|
||||
//~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
//~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
(a, b)
|
||||
}
|
||||
|
||||
|
@ -14,5 +14,42 @@ LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: ambiguous lifetime bound in `impl Trait`
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
||||
|
|
||||
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another
|
||||
|
|
||||
= help: add #![feature(member_constraints)] to the crate attributes to enable
|
||||
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
||||
|
|
||||
LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | (a, b)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#4r
|
||||
|
||||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
|
||||
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
||||
|
|
||||
LL | / async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | (a, b)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: hidden type `(&u8, &u8)` captures lifetime '_#5r
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0700`.
|
||||
|
17
src/test/ui/const-generics/issues/issue70273-assoc-fn.rs
Normal file
17
src/test/ui/const-generics/issues/issue70273-assoc-fn.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
trait T<const A: usize> {
|
||||
fn f();
|
||||
}
|
||||
struct S;
|
||||
|
||||
impl T<0usize> for S {
|
||||
fn f() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _err = <S as T<0usize>>::f();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/issue70273-assoc-fn.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
21
src/test/ui/const-generics/type_of_anon_const.rs
Normal file
21
src/test/ui/const-generics/type_of_anon_const.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
trait T<const A: usize> {
|
||||
fn l<const N: bool>() -> usize;
|
||||
fn r<const N: bool>() -> bool;
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl<const N: usize> T<N> for S {
|
||||
fn l<const M: bool>() -> usize { N }
|
||||
fn r<const M: bool>() -> bool { M }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(<S as T<123>>::l::<true>(), 123);
|
||||
assert!(<S as T<123>>::r::<true>());
|
||||
}
|
8
src/test/ui/const-generics/type_of_anon_const.stderr
Normal file
8
src/test/ui/const-generics/type_of_anon_const.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/type_of_anon_const.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo {
|
||||
i: isize,
|
||||
|
@ -1,11 +1,19 @@
|
||||
error[E0599]: no method named `clone` found for struct `Foo` in the current scope
|
||||
--> $DIR/copy-a-resource.rs:18:16
|
||||
--> $DIR/copy-a-resource.rs:23:16
|
||||
|
|
||||
LL | struct Foo {
|
||||
| ---------- method `clone` not found for this
|
||||
...
|
||||
LL | let _y = x.clone();
|
||||
| ^^^^^ method not found in `Foo`
|
||||
|
|
||||
::: $SRC_DIR/libcore/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `std::sync::Arc<Foo>` here
|
||||
| the method is available for `std::rc::Rc<Foo>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
trait Foo {
|
||||
type X;
|
||||
fn method(&self) {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0599]: no method named `clone` found for struct `Bar<NotClone>` in the current scope
|
||||
--> $DIR/derive-assoc-type-not-impl.rs:18:30
|
||||
--> $DIR/derive-assoc-type-not-impl.rs:23:30
|
||||
|
|
||||
LL | struct Bar<T: Foo> {
|
||||
| ------------------
|
||||
@ -12,6 +12,14 @@ LL | struct NotClone;
|
||||
...
|
||||
LL | Bar::<NotClone> { x: 1 }.clone();
|
||||
| ^^^^^ method not found in `Bar<NotClone>`
|
||||
|
|
||||
::: $SRC_DIR/libcore/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `std::sync::Arc<Bar<NotClone>>` here
|
||||
| the method is available for `std::rc::Rc<Bar<NotClone>>` here
|
||||
|
|
||||
= note: the method `clone` exists but the following trait bounds were not satisfied:
|
||||
`NotClone: std::clone::Clone`
|
||||
|
@ -1,9 +1,17 @@
|
||||
// edition:2018
|
||||
// aux-build:edition-kw-macro-2015.rs
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[macro_use]
|
||||
extern crate edition_kw_macro_2015;
|
||||
|
||||
mod module {
|
||||
pub fn r#async() {}
|
||||
}
|
||||
|
||||
pub fn check_async() {
|
||||
let mut async = 1; //~ ERROR expected identifier, found keyword `async`
|
||||
let mut r#async = 1; // OK
|
||||
@ -17,4 +25,6 @@ pub fn check_async() {
|
||||
if passes_ident!(r#async) == 1 {} // OK
|
||||
module::async(); //~ ERROR expected identifier, found keyword `async`
|
||||
module::r#async(); // OK
|
||||
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: expected identifier, found keyword `async`
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:8:13
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:16:13
|
||||
|
|
||||
LL | let mut async = 1;
|
||||
| ^^^^^ expected identifier, found keyword
|
||||
@ -10,7 +10,7 @@ LL | let mut r#async = 1;
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected identifier, found keyword `async`
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:18:13
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:26:13
|
||||
|
|
||||
LL | module::async();
|
||||
| ^^^^^ expected identifier, found keyword
|
||||
@ -21,13 +21,13 @@ LL | module::r#async();
|
||||
| ^^^^^^^
|
||||
|
||||
error: no rules expected the token `r#async`
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:12:31
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:20:31
|
||||
|
|
||||
LL | r#async = consumes_async!(r#async);
|
||||
| ^^^^^^^ no rules expected this token in macro call
|
||||
|
||||
error: no rules expected the token `async`
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:13:35
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:21:35
|
||||
|
|
||||
LL | r#async = consumes_async_raw!(async);
|
||||
| ^^^^^ no rules expected this token in macro call
|
||||
@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move
|
||||
LL | ($i: ident) => ($i)
|
||||
| ^ expected one of `move`, `|`, or `||`
|
||||
|
|
||||
::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8
|
||||
::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8
|
||||
|
|
||||
LL | if passes_ident!(async) == 1 {}
|
||||
| -------------------- in this macro invocation
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/edition-keywords-2018-2015-parsing.rs:29:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,9 +1,17 @@
|
||||
// edition:2018
|
||||
// aux-build:edition-kw-macro-2018.rs
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[macro_use]
|
||||
extern crate edition_kw_macro_2018;
|
||||
|
||||
mod module {
|
||||
pub fn r#async() {}
|
||||
}
|
||||
|
||||
pub fn check_async() {
|
||||
let mut async = 1; //~ ERROR expected identifier, found keyword `async`
|
||||
let mut r#async = 1; // OK
|
||||
@ -17,4 +25,6 @@ pub fn check_async() {
|
||||
if passes_ident!(r#async) == 1 {} // OK
|
||||
module::async(); //~ ERROR expected identifier, found keyword `async`
|
||||
module::r#async(); // OK
|
||||
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: expected identifier, found keyword `async`
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:8:13
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:16:13
|
||||
|
|
||||
LL | let mut async = 1;
|
||||
| ^^^^^ expected identifier, found keyword
|
||||
@ -10,7 +10,7 @@ LL | let mut r#async = 1;
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected identifier, found keyword `async`
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:18:13
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:26:13
|
||||
|
|
||||
LL | module::async();
|
||||
| ^^^^^ expected identifier, found keyword
|
||||
@ -21,13 +21,13 @@ LL | module::r#async();
|
||||
| ^^^^^^^
|
||||
|
||||
error: no rules expected the token `r#async`
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:12:31
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:20:31
|
||||
|
|
||||
LL | r#async = consumes_async!(r#async);
|
||||
| ^^^^^^^ no rules expected this token in macro call
|
||||
|
||||
error: no rules expected the token `async`
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:13:35
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:21:35
|
||||
|
|
||||
LL | r#async = consumes_async_raw!(async);
|
||||
| ^^^^^ no rules expected this token in macro call
|
||||
@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move
|
||||
LL | ($i: ident) => ($i)
|
||||
| ^ expected one of `move`, `|`, or `||`
|
||||
|
|
||||
::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8
|
||||
::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8
|
||||
|
|
||||
LL | if passes_ident!(async) == 1 {}
|
||||
| -------------------- in this macro invocation
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/edition-keywords-2018-2018-parsing.rs:29:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
fn main() {
|
||||
let x = Some(1);
|
||||
|
||||
|
@ -1,8 +1,16 @@
|
||||
error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered
|
||||
--> $DIR/E0004-2.rs:4:11
|
||||
--> $DIR/E0004-2.rs:9:11
|
||||
|
|
||||
LL | match x { }
|
||||
| ^ patterns `None` and `Some(_)` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/option.rs:LL:COL
|
||||
|
|
||||
LL | None,
|
||||
| ---- not covered
|
||||
...
|
||||
LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
|
||||
| ---- not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
fn main() {
|
||||
let x = Some(1);
|
||||
let Some(y) = x; //~ ERROR E0005
|
||||
|
@ -1,8 +1,13 @@
|
||||
error[E0005]: refutable pattern in local binding: `None` not covered
|
||||
--> $DIR/E0005.rs:3:9
|
||||
--> $DIR/E0005.rs:8:9
|
||||
|
|
||||
LL | let Some(y) = x;
|
||||
| ^^^^^^^ pattern `None` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/option.rs:LL:COL
|
||||
|
|
||||
LL | None,
|
||||
| ---- not covered
|
||||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
fn main() {
|
||||
let xs : Vec<Option<i32>> = vec![Some(1), None];
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
error[E0005]: refutable pattern in `for` loop binding: `None` not covered
|
||||
--> $DIR/E0297.rs:4:9
|
||||
--> $DIR/E0297.rs:9:9
|
||||
|
|
||||
LL | for Some(x) in xs {}
|
||||
| ^^^^^^^ pattern `None` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/option.rs:LL:COL
|
||||
|
|
||||
LL | None,
|
||||
| ---- not covered
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
#![feature(never_type)]
|
||||
|
||||
fn foo() -> Result<u32, !> {
|
||||
|
@ -1,8 +1,13 @@
|
||||
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
||||
--> $DIR/feature-gate-exhaustive-patterns.rs:8:9
|
||||
--> $DIR/feature-gate-exhaustive-patterns.rs:13:9
|
||||
|
|
||||
LL | let Ok(_x) = foo();
|
||||
| ^^^^^^ pattern `Err(_)` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/result.rs:LL:COL
|
||||
|
|
||||
LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
|
||||
| --- not covered
|
||||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
|
@ -1,10 +1,15 @@
|
||||
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:15:5
|
||||
--> $DIR/iterable.rs:20:5
|
||||
|
|
||||
LL | impl<T> Iterable for Vec<T> {
|
||||
| --------------------------- in this `impl` item
|
||||
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
||||
|
|
||||
::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
LL | type Item;
|
||||
| ---- associated type defined here
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
|
||||
@ -12,12 +17,17 @@ LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:27:5
|
||||
--> $DIR/iterable.rs:32:5
|
||||
|
|
||||
LL | impl<T> Iterable for [T] {
|
||||
| ------------------------ in this `impl` item
|
||||
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
||||
|
|
||||
::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
LL | type Item;
|
||||
| ---- associated type defined here
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found associated type `<[T] as Iterable>::Item<'_>`
|
||||
@ -25,7 +35,7 @@ LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:19:30
|
||||
--> $DIR/iterable.rs:24:30
|
||||
|
|
||||
LL | trait Iterable {
|
||||
| -------------- required by `Iterable`
|
||||
@ -39,7 +49,7 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:31:30
|
||||
--> $DIR/iterable.rs:36:30
|
||||
|
|
||||
LL | trait Iterable {
|
||||
| -------------- required by `Iterable`
|
||||
|
@ -83,6 +83,16 @@ error[E0599]: no method named `method` found for struct `std::rc::Rc<&mut std::b
|
||||
|
|
||||
LL | std::rc::Rc::new(&mut Box::new(&1i32)).method();
|
||||
| ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&i32>>`
|
||||
|
|
||||
::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12
|
||||
|
|
||||
LL | fn method(&self) {}
|
||||
| ------
|
||||
| |
|
||||
| the method is available for `std::boxed::Box<std::rc::Rc<&mut std::boxed::Box<&i32>>>` here
|
||||
| the method is available for `std::pin::Pin<std::rc::Rc<&mut std::boxed::Box<&i32>>>` here
|
||||
| the method is available for `std::sync::Arc<std::rc::Rc<&mut std::boxed::Box<&i32>>>` here
|
||||
| the method is available for `std::rc::Rc<std::rc::Rc<&mut std::boxed::Box<&i32>>>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
struct C {
|
||||
x: isize,
|
||||
}
|
||||
|
@ -1,11 +1,19 @@
|
||||
error[E0599]: no method named `clone` found for struct `C` in the current scope
|
||||
--> $DIR/issue-2823.rs:13:16
|
||||
--> $DIR/issue-2823.rs:18:16
|
||||
|
|
||||
LL | struct C {
|
||||
| -------- method `clone` not found for this
|
||||
...
|
||||
LL | let _d = c.clone();
|
||||
| ^^^^^ method not found in `C`
|
||||
|
|
||||
::: $SRC_DIR/libcore/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `std::sync::Arc<C>` here
|
||||
| the method is available for `std::rc::Rc<C>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
// aux-build:issue-69725.rs
|
||||
|
||||
extern crate issue_69725;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0599]: no method named `clone` found for struct `issue_69725::Struct<A>` in the current scope
|
||||
--> $DIR/issue-69725.rs:7:32
|
||||
--> $DIR/issue-69725.rs:12:32
|
||||
|
|
||||
LL | let _ = Struct::<A>::new().clone();
|
||||
| ^^^^^ method not found in `issue_69725::Struct<A>`
|
||||
@ -8,6 +8,14 @@ LL | let _ = Struct::<A>::new().clone();
|
||||
|
|
||||
LL | pub struct Struct<A>(A);
|
||||
| ------------------------ doesn't satisfy `issue_69725::Struct<A>: std::clone::Clone`
|
||||
|
|
||||
::: $SRC_DIR/libcore/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `std::sync::Arc<issue_69725::Struct<A>>` here
|
||||
| the method is available for `std::rc::Rc<issue_69725::Struct<A>>` here
|
||||
|
|
||||
= note: the method `clone` exists but the following trait bounds were not satisfied:
|
||||
`A: std::clone::Clone`
|
||||
|
@ -1,9 +1,10 @@
|
||||
// Regression test for issue #61033.
|
||||
|
||||
macro_rules! test1 {
|
||||
($x:ident, $($tt:tt)*) => { $($tt)+ } //~ERROR this must repeat at least once
|
||||
($x:ident, $($tt:tt)*) => { $($tt)+ } //~ ERROR this must repeat at least once
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test1!(x,);
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
}
|
||||
|
@ -4,5 +4,14 @@ error: this must repeat at least once
|
||||
LL | ($x:ident, $($tt:tt)*) => { $($tt)+ }
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-61033-1.rs:9:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -5,7 +5,9 @@ macro_rules! test2 {
|
||||
$(* $id1:ident)*
|
||||
$(+ $id2:ident)*
|
||||
) => {
|
||||
$( //~ERROR meta-variable `id1` repeats 2 times
|
||||
$(
|
||||
//~^ ERROR meta-variable `id1` repeats 2 times
|
||||
//~| ERROR meta-variable `id1` repeats 2 times
|
||||
$id1 + $id2 // $id1 and $id2 may repeat different numbers of times
|
||||
)*
|
||||
}
|
||||
@ -16,4 +18,8 @@ fn main() {
|
||||
* a * b
|
||||
+ a + b + c
|
||||
}
|
||||
test2! {
|
||||
* a * b
|
||||
+ a + b + c + d
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,22 @@ error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times
|
||||
|
|
||||
LL | $(
|
||||
| __________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times
|
||||
LL | | )*
|
||||
| |_________^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: meta-variable `id1` repeats 2 times, but `id2` repeats 4 times
|
||||
--> $DIR/issue-61033-2.rs:8:10
|
||||
|
|
||||
LL | $(
|
||||
| __________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times
|
||||
LL | | )*
|
||||
| |_________^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
fn main() {}
|
||||
|
||||
macro_rules! ambiguity {
|
||||
($($i:ident)* $j:ident) => {};
|
||||
}
|
||||
|
||||
ambiguity!(error); //~ ERROR local ambiguity
|
||||
ambiguity!(error); //~ ERROR local ambiguity
|
@ -0,0 +1,14 @@
|
||||
error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j').
|
||||
--> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12
|
||||
|
|
||||
LL | ambiguity!(error);
|
||||
| ^^^^^
|
||||
|
||||
error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j').
|
||||
--> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12
|
||||
|
|
||||
LL | ambiguity!(error);
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -4,6 +4,8 @@ macro_rules! m {
|
||||
//~| ERROR macro expansion ignores token `typeof`
|
||||
//~| ERROR macro expansion ignores token `;`
|
||||
//~| ERROR macro expansion ignores token `;`
|
||||
//~| ERROR cannot find type `i` in this scope
|
||||
//~| ERROR cannot find value `i` in this scope
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -42,5 +42,29 @@ LL | m!();
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0412]: cannot find type `i` in this scope
|
||||
--> $DIR/macro-context.rs:3:13
|
||||
|
|
||||
LL | () => ( i ; typeof );
|
||||
| ^ help: a builtin type with a similar name exists: `i8`
|
||||
...
|
||||
LL | let a: m!();
|
||||
| ---- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0425]: cannot find value `i` in this scope
|
||||
--> $DIR/macro-context.rs:3:13
|
||||
|
|
||||
LL | () => ( i ; typeof );
|
||||
| ^ help: a local variable with a similar name exists: `a`
|
||||
...
|
||||
LL | let i = m!();
|
||||
| ---- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0425.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
||||
|
@ -1,4 +1,11 @@
|
||||
macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment
|
||||
macro_rules! test {
|
||||
($a, $b) => {
|
||||
//~^ ERROR missing fragment
|
||||
//~| ERROR missing fragment
|
||||
//~| WARN this was previously accepted
|
||||
()
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test!()
|
||||
|
@ -1,8 +1,18 @@
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:1:24
|
||||
--> $DIR/macro-match-nonterminal.rs:2:8
|
||||
|
|
||||
LL | macro_rules! test { ($a, $b) => (()); }
|
||||
| ^
|
||||
LL | ($a, $b) => {
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:10
|
||||
|
|
||||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// compile-flags: -Z trace-macros
|
||||
|
||||
#![recursion_limit="4"]
|
||||
#![recursion_limit = "4"]
|
||||
|
||||
macro_rules! my_faulty_macro {
|
||||
() => {
|
||||
@ -24,9 +24,7 @@ macro_rules! my_recursive_macro {
|
||||
}
|
||||
|
||||
macro_rules! my_macro {
|
||||
() => {
|
||||
|
||||
};
|
||||
() => {};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -39,7 +37,7 @@ fn main() {
|
||||
}
|
||||
|
||||
#[my_macro]
|
||||
fn use_bang_macro_as_attr(){}
|
||||
fn use_bang_macro_as_attr() {}
|
||||
|
||||
#[derive(Debug)]
|
||||
fn use_derive_macro_as_attr(){}
|
||||
#[derive(Debug)] //~ ERROR `derive` may only be applied to structs
|
||||
fn use_derive_macro_as_attr() {}
|
||||
|
@ -13,7 +13,7 @@ LL | my_faulty_macro!();
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: trace_macro
|
||||
--> $DIR/trace_faulty_macros.rs:33:5
|
||||
--> $DIR/trace_faulty_macros.rs:31:5
|
||||
|
|
||||
LL | my_faulty_macro!();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
@ -35,7 +35,7 @@ LL | my_recursive_macro!();
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: trace_macro
|
||||
--> $DIR/trace_faulty_macros.rs:34:5
|
||||
--> $DIR/trace_faulty_macros.rs:32:5
|
||||
|
|
||||
LL | my_recursive_macro!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -60,5 +60,22 @@ LL | let a = pat_macro!();
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: `derive` may only be applied to structs, enums and unions
|
||||
--> $DIR/trace_faulty_macros.rs:42:1
|
||||
|
|
||||
LL | #[derive(Debug)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
note: trace_macro
|
||||
--> $DIR/trace_faulty_macros.rs:36:13
|
||||
|
|
||||
LL | let a = pat_macro!();
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: expanding `pat_macro! { }`
|
||||
= note: to `pat_macro ! (A { a : a, b : 0, c : _, .. }) ;`
|
||||
= note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }`
|
||||
= note: to `A { a: a, b: 0, c: _, .. }`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
// ignore-wasm32-bare no libc to test ffi with
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -1,8 +1,16 @@
|
||||
error[E0599]: no method named `clone` found for enum `libc::c_void` in the current scope
|
||||
--> $DIR/non-copyable-void.rs:11:23
|
||||
--> $DIR/non-copyable-void.rs:16:23
|
||||
|
|
||||
LL | let _z = (*y).clone();
|
||||
| ^^^^^ method not found in `libc::c_void`
|
||||
|
|
||||
::: $SRC_DIR/libcore/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `std::sync::Arc<libc::c_void>` here
|
||||
| the method is available for `std::rc::Rc<libc::c_void>` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
// Test that a class with a non-copyable field can't be
|
||||
// copied
|
||||
|
||||
|
@ -1,11 +1,19 @@
|
||||
error[E0599]: no method named `clone` found for struct `Foo` in the current scope
|
||||
--> $DIR/noncopyable-class.rs:34:16
|
||||
--> $DIR/noncopyable-class.rs:39:16
|
||||
|
|
||||
LL | struct Foo {
|
||||
| ---------- method `clone` not found for this
|
||||
...
|
||||
LL | let _y = x.clone();
|
||||
| ^^^^^ method not found in `Foo`
|
||||
|
|
||||
::: $SRC_DIR/libcore/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `std::sync::Arc<Foo>` here
|
||||
| the method is available for `std::rc::Rc<Foo>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
// Regression test for #62894, shouldn't crash.
|
||||
// error-pattern: this file contains an unclosed delimiter
|
||||
// error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/issue-62894.rs:7:14
|
||||
--> $DIR/issue-62894.rs:12:14
|
||||
|
|
||||
LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
|
||||
| - - - unclosed delimiter
|
||||
@ -11,7 +11,7 @@ LL | fn main() {}
|
||||
| ^
|
||||
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/issue-62894.rs:7:14
|
||||
--> $DIR/issue-62894.rs:12:14
|
||||
|
|
||||
LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
|
||||
| - - - unclosed delimiter
|
||||
@ -23,7 +23,7 @@ LL | fn main() {}
|
||||
| ^
|
||||
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/issue-62894.rs:7:14
|
||||
--> $DIR/issue-62894.rs:12:14
|
||||
|
|
||||
LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
|
||||
| - - - unclosed delimiter
|
||||
@ -35,13 +35,18 @@ LL | fn main() {}
|
||||
| ^
|
||||
|
||||
error: expected one of `(`, `[`, or `{`, found keyword `fn`
|
||||
--> $DIR/issue-62894.rs:7:1
|
||||
--> $DIR/issue-62894.rs:12:1
|
||||
|
|
||||
LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
|
||||
| - expected one of `(`, `[`, or `{`
|
||||
LL |
|
||||
LL | fn main() {}
|
||||
| ^^ unexpected token
|
||||
|
|
||||
::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
|
||||
|
|
||||
LL | ($left:expr, $right:expr) => ({
|
||||
| ---------- while parsing argument for this `expr` macro fragment
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -6,3 +6,5 @@ macro_rules! foo {
|
||||
}
|
||||
|
||||
foo!();
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,9 +1,12 @@
|
||||
macro_rules! mac {
|
||||
( $($v:tt)* ) => (
|
||||
$v //~ ERROR still repeating at this depth
|
||||
)
|
||||
( $($v:tt)* ) => {
|
||||
$v
|
||||
//~^ ERROR still repeating at this depth
|
||||
//~| ERROR still repeating at this depth
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mac!(0);
|
||||
mac!(1);
|
||||
}
|
||||
|
@ -4,5 +4,11 @@ error: variable 'v' is still repeating at this depth
|
||||
LL | $v
|
||||
| ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: variable 'v' is still repeating at this depth
|
||||
--> $DIR/macro-repeat.rs:3:9
|
||||
|
|
||||
LL | $v
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
10
src/test/ui/parser/nt-parsing-has-recovery.rs
Normal file
10
src/test/ui/parser/nt-parsing-has-recovery.rs
Normal file
@ -0,0 +1,10 @@
|
||||
macro_rules! foo {
|
||||
($e:expr) => {}
|
||||
}
|
||||
|
||||
foo!(1 + @); //~ ERROR expected expression, found `@`
|
||||
foo!(1 + @); //~ ERROR expected expression, found `@`
|
||||
|
||||
fn main() {
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
}
|
29
src/test/ui/parser/nt-parsing-has-recovery.stderr
Normal file
29
src/test/ui/parser/nt-parsing-has-recovery.stderr
Normal file
@ -0,0 +1,29 @@
|
||||
error: expected expression, found `@`
|
||||
--> $DIR/nt-parsing-has-recovery.rs:5:10
|
||||
|
|
||||
LL | ($e:expr) => {}
|
||||
| ------- while parsing argument for this `expr` macro fragment
|
||||
...
|
||||
LL | foo!(1 + @);
|
||||
| ^ expected expression
|
||||
|
||||
error: expected expression, found `@`
|
||||
--> $DIR/nt-parsing-has-recovery.rs:6:10
|
||||
|
|
||||
LL | ($e:expr) => {}
|
||||
| ------- while parsing argument for this `expr` macro fragment
|
||||
...
|
||||
LL | foo!(1 + @);
|
||||
| ^ expected expression
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/nt-parsing-has-recovery.rs:9:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
use self::Direction::{North, East, South, West};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0004]: non-exhaustive patterns: `(true, false)` not covered
|
||||
--> $DIR/match-arm-statics-2.rs:17:11
|
||||
--> $DIR/match-arm-statics-2.rs:22:11
|
||||
|
|
||||
LL | match (true, false) {
|
||||
| ^^^^^^^^^^^^^ pattern `(true, false)` not covered
|
||||
@ -7,15 +7,23 @@ LL | match (true, false) {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
|
||||
--> $DIR/match-arm-statics-2.rs:29:11
|
||||
--> $DIR/match-arm-statics-2.rs:34:11
|
||||
|
|
||||
LL | match Some(Some(North)) {
|
||||
| ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/option.rs:LL:COL
|
||||
|
|
||||
LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
|
||||
| ----
|
||||
| |
|
||||
| not covered
|
||||
| not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
|
||||
--> $DIR/match-arm-statics-2.rs:48:11
|
||||
--> $DIR/match-arm-statics-2.rs:53:11
|
||||
|
|
||||
LL | / struct Foo {
|
||||
LL | | bar: Option<Direction>,
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
#![feature(never_type)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
|
||||
--> $DIR/match-privately-empty.rs:13:11
|
||||
--> $DIR/match-privately-empty.rs:18:11
|
||||
|
|
||||
LL | match private::DATA {
|
||||
| ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/option.rs:LL:COL
|
||||
|
|
||||
LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
|
||||
| ---- not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
// FIXME: missing sysroot spans (#53081)
|
||||
// ignore-i586-unknown-linux-gnu
|
||||
// ignore-i586-unknown-linux-musl
|
||||
// ignore-i686-unknown-linux-musl
|
||||
|
||||
#![allow(illegal_floating_point_literal_pattern)]
|
||||
|
||||
enum T { A, B }
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0004]: non-exhaustive patterns: `A` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:7:11
|
||||
--> $DIR/non-exhaustive-match.rs:12:11
|
||||
|
|
||||
LL | enum T { A, B }
|
||||
| ---------------
|
||||
@ -13,7 +13,7 @@ LL | match x { T::B => { } }
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `false` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:8:11
|
||||
--> $DIR/non-exhaustive-match.rs:13:11
|
||||
|
|
||||
LL | match true {
|
||||
| ^^^^ pattern `false` not covered
|
||||
@ -21,15 +21,20 @@ LL | match true {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:11:11
|
||||
--> $DIR/non-exhaustive-match.rs:16:11
|
||||
|
|
||||
LL | match Some(10) {
|
||||
| ^^^^^^^^ pattern `Some(_)` not covered
|
||||
|
|
||||
::: $SRC_DIR/libcore/option.rs:LL:COL
|
||||
|
|
||||
LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
|
||||
| ---- not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:14:11
|
||||
--> $DIR/non-exhaustive-match.rs:19:11
|
||||
|
|
||||
LL | match (2, 3, 4) {
|
||||
| ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
|
||||
@ -37,7 +42,7 @@ LL | match (2, 3, 4) {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `(A, A)` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:18:11
|
||||
--> $DIR/non-exhaustive-match.rs:23:11
|
||||
|
|
||||
LL | match (T::A, T::A) {
|
||||
| ^^^^^^^^^^^^ pattern `(A, A)` not covered
|
||||
@ -45,7 +50,7 @@ LL | match (T::A, T::A) {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `B` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:22:11
|
||||
--> $DIR/non-exhaustive-match.rs:27:11
|
||||
|
|
||||
LL | enum T { A, B }
|
||||
| ---------------
|
||||
@ -59,7 +64,7 @@ LL | match T::A {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `[]` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:33:11
|
||||
--> $DIR/non-exhaustive-match.rs:38:11
|
||||
|
|
||||
LL | match *vec {
|
||||
| ^^^^ pattern `[]` not covered
|
||||
@ -67,7 +72,7 @@ LL | match *vec {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
|
||||
--> $DIR/non-exhaustive-match.rs:46:11
|
||||
--> $DIR/non-exhaustive-match.rs:51:11
|
||||
|
|
||||
LL | match *vec {
|
||||
| ^^^^ pattern `[_, _, _, _, ..]` not covered
|
||||
|
@ -3,11 +3,9 @@
|
||||
#[macro_use]
|
||||
extern crate derive_bad;
|
||||
|
||||
#[derive(
|
||||
A
|
||||
)]
|
||||
//~^^ ERROR proc-macro derive produced unparseable tokens
|
||||
#[derive(A)]
|
||||
//~^ ERROR proc-macro derive produced unparseable tokens
|
||||
//~| ERROR expected `:`, found `}`
|
||||
struct A;
|
||||
struct A; //~ ERROR the name `A` is defined multiple times
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,16 +1,28 @@
|
||||
error: expected `:`, found `}`
|
||||
--> $DIR/derive-bad.rs:7:5
|
||||
--> $DIR/derive-bad.rs:6:10
|
||||
|
|
||||
LL | A
|
||||
| ^ expected `:`
|
||||
LL | #[derive(A)]
|
||||
| ^ expected `:`
|
||||
|
|
||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: proc-macro derive produced unparseable tokens
|
||||
--> $DIR/derive-bad.rs:7:5
|
||||
--> $DIR/derive-bad.rs:6:10
|
||||
|
|
||||
LL | A
|
||||
| ^
|
||||
LL | #[derive(A)]
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0428]: the name `A` is defined multiple times
|
||||
--> $DIR/derive-bad.rs:9:1
|
||||
|
|
||||
LL | #[derive(A)]
|
||||
| - previous definition of the type `A` here
|
||||
...
|
||||
LL | struct A;
|
||||
| ^^^^^^^^^ `A` redefined here
|
||||
|
|
||||
= note: `A` must be defined only once in the type namespace of this module
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0428`.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user