Auto merge of #73246 - Dylan-DPC:rollup-xnm531f, r=Dylan-DPC

Rollup of 7 pull requests

Successful merges:

 - #72180 (remove extra space from crate-level doctest names)
 - #73012 (Show `SyntaxContext` in formatted `Span` debug output)
 - #73097 (Try_run must only be used if toolstate is populated)
 - #73169 (Handle assembler warnings properly)
 - #73182 (Track span of function in method calls, and use this in #[track_caller])
 - #73207 (Clean up E0648 explanation)
 - #73230 (Suggest including unused asm arguments in a comment to avoid error)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-06-11 18:11:07 +00:00
commit a37c32e2d5
118 changed files with 534 additions and 232 deletions

View file

@ -553,7 +553,7 @@ impl Step for Clippy {
builder.add_rustc_lib_path(compiler, &mut cargo); builder.add_rustc_lib_path(compiler, &mut cargo);
try_run(builder, &mut cargo.into()); builder.run(&mut cargo.into());
} }
} }

View file

@ -201,7 +201,7 @@ fn mul(a: u64, b: u64) -> u128 {
); );
} }
(hi as u128) << 64 + lo as u128 ((hi as u128) << 64) + lo as u128
} }
``` ```
@ -382,7 +382,9 @@ The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC
The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported. The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.
As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated. As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.
Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.
The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler. The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.

View file

@ -1174,7 +1174,9 @@ pub enum ExprKind {
/// and the remaining elements are the rest of the arguments. /// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
MethodCall(PathSegment, Vec<P<Expr>>), /// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
MethodCall(PathSegment, Vec<P<Expr>>, Span),
/// A tuple (e.g., `(a, b, c, d)`). /// A tuple (e.g., `(a, b, c, d)`).
Tup(Vec<P<Expr>>), Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`). /// A binary operation (e.g., `a + b`, `a * b`).

View file

@ -1111,11 +1111,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f); vis.visit_expr(f);
visit_exprs(args, vis); visit_exprs(args, vis);
} }
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs) => { ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
vis.visit_ident(ident); vis.visit_ident(ident);
vis.visit_id(id); vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args)); visit_opt(args, |args| vis.visit_generic_args(args));
visit_exprs(exprs, vis); visit_exprs(exprs, vis);
vis.visit_span(span);
} }
ExprKind::Binary(_binop, lhs, rhs) => { ExprKind::Binary(_binop, lhs, rhs) => {
vis.visit_expr(lhs); vis.visit_expr(lhs);

View file

@ -394,7 +394,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x) contains_exterior_struct_lit(&x)
} }
ast::ExprKind::MethodCall(.., ref exprs) => { ast::ExprKind::MethodCall(.., ref exprs, _) => {
// X { y: 1 }.bar(...) // X { y: 1 }.bar(...)
contains_exterior_struct_lit(&exprs[0]) contains_exterior_struct_lit(&exprs[0])
} }

View file

@ -726,7 +726,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(callee_expression); visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments); walk_list!(visitor, visit_expr, arguments);
} }
ExprKind::MethodCall(ref segment, ref arguments) => { ExprKind::MethodCall(ref segment, ref arguments, _span) => {
visitor.visit_path_segment(expression.span, segment); visitor.visit_path_segment(expression.span, segment);
walk_list!(visitor, visit_expr, arguments); walk_list!(visitor, visit_expr, arguments);
} }

View file

@ -39,7 +39,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let f = self.lower_expr(f); let f = self.lower_expr(f);
hir::ExprKind::Call(f, self.lower_exprs(args)) hir::ExprKind::Call(f, self.lower_exprs(args))
} }
ExprKind::MethodCall(ref seg, ref args) => { ExprKind::MethodCall(ref seg, ref args, span) => {
let hir_seg = self.arena.alloc(self.lower_path_segment( let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span, e.span,
seg, seg,
@ -50,7 +50,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
None, None,
)); ));
let args = self.lower_exprs(args); let args = self.lower_exprs(args);
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args) hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
} }
ExprKind::Binary(binop, ref lhs, ref rhs) => { ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop); let binop = self.lower_binop(binop);

View file

@ -1818,7 +1818,7 @@ impl<'a> State<'a> {
ast::ExprKind::Call(ref func, ref args) => { ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args[..]); self.print_expr_call(func, &args[..]);
} }
ast::ExprKind::MethodCall(ref segment, ref args) => { ast::ExprKind::MethodCall(ref segment, ref args, _) => {
self.print_expr_method_call(segment, &args[..]); self.print_expr_method_call(segment, &args[..]);
} }
ast::ExprKind::Binary(op, ref lhs, ref rhs) => { ast::ExprKind::Binary(op, ref lhs, ref rhs) => {

View file

@ -391,7 +391,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
used[*pos] = true; used[*pos] = true;
} }
let named_pos: FxHashSet<usize> = args.named_args.values().cloned().collect(); let named_pos: FxHashMap<usize, Symbol> =
args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect();
let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span)); let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
let mut template = vec![]; let mut template = vec![];
for piece in unverified_pieces { for piece in unverified_pieces {
@ -405,7 +406,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
let operand_idx = match arg.position { let operand_idx = match arg.position {
parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => { parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
if idx >= args.operands.len() if idx >= args.operands.len()
|| named_pos.contains(&idx) || named_pos.contains_key(&idx)
|| args.reg_args.contains(&idx) || args.reg_args.contains(&idx)
{ {
let msg = format!("invalid reference to argument at index {}", idx); let msg = format!("invalid reference to argument at index {}", idx);
@ -426,7 +427,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
}; };
err.note(&msg); err.note(&msg);
if named_pos.contains(&idx) { if named_pos.contains_key(&idx) {
err.span_label(args.operands[idx].1, "named argument"); err.span_label(args.operands[idx].1, "named argument");
err.span_note( err.span_note(
args.operands[idx].1, args.operands[idx].1,
@ -480,27 +481,31 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
} }
} }
let operands = args.operands; let mut unused_operands = vec![];
let unused_operands: Vec<_> = used let mut help_str = String::new();
.into_iter() for (idx, used) in used.into_iter().enumerate() {
.enumerate() if !used {
.filter(|&(_, used)| !used) let msg = if let Some(sym) = named_pos.get(&idx) {
.map(|(idx, _)| { help_str.push_str(&format!(" {{{}}}", sym));
if named_pos.contains(&idx) { "named argument never used"
// named argument
(operands[idx].1, "named argument never used")
} else { } else {
// positional argument help_str.push_str(&format!(" {{{}}}", idx));
(operands[idx].1, "argument never used") "argument never used"
} };
}) unused_operands.push((args.operands[idx].1, msg));
.collect(); }
}
match unused_operands.len() { match unused_operands.len() {
0 => {} 0 => {}
1 => { 1 => {
let (sp, msg) = unused_operands.into_iter().next().unwrap(); let (sp, msg) = unused_operands.into_iter().next().unwrap();
let mut err = ecx.struct_span_err(sp, msg); let mut err = ecx.struct_span_err(sp, msg);
err.span_label(sp, msg); err.span_label(sp, msg);
err.help(&format!(
"if this argument is intentionally unused, \
consider using it in an asm comment: `\"/*{} */\"`",
help_str
));
err.emit(); err.emit();
} }
_ => { _ => {
@ -511,6 +516,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
for (sp, msg) in unused_operands { for (sp, msg) in unused_operands {
err.span_label(sp, msg); err.span_label(sp, msg);
} }
err.help(&format!(
"if these arguments are intentionally unused, \
consider using them in an asm comment: `\"/*{} */\"`",
help_str
));
err.emit(); err.emit();
} }
} }
@ -521,7 +531,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect() parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
}; };
let inline_asm = ast::InlineAsm { template, operands, options: args.options, line_spans }; let inline_asm =
ast::InlineAsm { template, operands: args.operands, options: args.options, line_spans };
P(ast::Expr { P(ast::Expr {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
kind: ast::ExprKind::InlineAsm(P(inline_asm)), kind: ast::ExprKind::InlineAsm(P(inline_asm)),

View file

@ -16,7 +16,7 @@ use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, Mo
use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
use rustc_errors::{FatalError, Handler}; use rustc_errors::{FatalError, Handler, Level};
use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug; use rustc_middle::bug;
@ -242,6 +242,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
fn report_inline_asm( fn report_inline_asm(
cgcx: &CodegenContext<LlvmCodegenBackend>, cgcx: &CodegenContext<LlvmCodegenBackend>,
msg: String, msg: String,
level: llvm::DiagnosticLevel,
mut cookie: c_uint, mut cookie: c_uint,
source: Option<(String, Vec<InnerSpan>)>, source: Option<(String, Vec<InnerSpan>)>,
) { ) {
@ -251,7 +252,12 @@ fn report_inline_asm(
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) { if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
cookie = 0; cookie = 0;
} }
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, source); let level = match level {
llvm::DiagnosticLevel::Error => Level::Error,
llvm::DiagnosticLevel::Warning => Level::Warning,
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
};
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, level, source);
} }
unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) { unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) {
@ -264,6 +270,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
// diagnostics. // diagnostics.
let mut have_source = false; let mut have_source = false;
let mut buffer = String::new(); let mut buffer = String::new();
let mut level = llvm::DiagnosticLevel::Error;
let mut loc = 0; let mut loc = 0;
let mut ranges = [0; 8]; let mut ranges = [0; 8];
let mut num_ranges = ranges.len() / 2; let mut num_ranges = ranges.len() / 2;
@ -273,6 +280,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
diag, diag,
msg, msg,
buffer, buffer,
&mut level,
&mut loc, &mut loc,
ranges.as_mut_ptr(), ranges.as_mut_ptr(),
&mut num_ranges, &mut num_ranges,
@ -290,7 +298,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
(buffer, spans) (buffer, spans)
}); });
report_inline_asm(cgcx, msg, cookie, source); report_inline_asm(cgcx, msg, level, cookie, source);
} }
unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
@ -301,7 +309,13 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
match llvm::diagnostic::Diagnostic::unpack(info) { match llvm::diagnostic::Diagnostic::unpack(info) {
llvm::diagnostic::InlineAsm(inline) => { llvm::diagnostic::InlineAsm(inline) => {
report_inline_asm(cgcx, llvm::twine_to_string(inline.message), inline.cookie, None); report_inline_asm(
cgcx,
llvm::twine_to_string(inline.message),
inline.level,
inline.cookie,
None,
);
} }
llvm::diagnostic::Optimization(opt) => { llvm::diagnostic::Optimization(opt) => {

View file

@ -88,6 +88,7 @@ impl OptimizationDiagnostic<'ll> {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct InlineAsmDiagnostic<'ll> { pub struct InlineAsmDiagnostic<'ll> {
pub level: super::DiagnosticLevel,
pub cookie: c_uint, pub cookie: c_uint,
pub message: &'ll Twine, pub message: &'ll Twine,
pub instruction: Option<&'ll Value>, pub instruction: Option<&'ll Value>,
@ -98,10 +99,17 @@ impl InlineAsmDiagnostic<'ll> {
let mut cookie = 0; let mut cookie = 0;
let mut message = None; let mut message = None;
let mut instruction = None; let mut instruction = None;
let mut level = super::DiagnosticLevel::Error;
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut cookie, &mut message, &mut instruction); super::LLVMRustUnpackInlineAsmDiagnostic(
di,
&mut level,
&mut cookie,
&mut message,
&mut instruction,
);
InlineAsmDiagnostic { cookie, message: message.unwrap(), instruction } InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
} }
} }

View file

@ -489,6 +489,17 @@ pub enum DiagnosticKind {
Linker, Linker,
} }
/// LLVMRustDiagnosticLevel
#[derive(Copy, Clone)]
#[repr(C)]
#[allow(dead_code)] // Variants constructed by C++.
pub enum DiagnosticLevel {
Error,
Warning,
Note,
Remark,
}
/// LLVMRustArchiveKind /// LLVMRustArchiveKind
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(C)] #[repr(C)]
@ -2054,6 +2065,7 @@ extern "C" {
pub fn LLVMRustUnpackInlineAsmDiagnostic( pub fn LLVMRustUnpackInlineAsmDiagnostic(
DI: &'a DiagnosticInfo, DI: &'a DiagnosticInfo,
level_out: &mut DiagnosticLevel,
cookie_out: &mut c_uint, cookie_out: &mut c_uint,
message_out: &mut Option<&'a Twine>, message_out: &mut Option<&'a Twine>,
instruction_out: &mut Option<&'a Value>, instruction_out: &mut Option<&'a Value>,
@ -2074,6 +2086,7 @@ extern "C" {
d: &SMDiagnostic, d: &SMDiagnostic,
message_out: &RustString, message_out: &RustString,
buffer_out: &RustString, buffer_out: &RustString,
level_out: &mut DiagnosticLevel,
loc_out: &mut c_uint, loc_out: &mut c_uint,
ranges_out: *mut c_uint, ranges_out: *mut c_uint,
num_ranges: &mut usize, num_ranges: &mut usize,

View file

@ -1551,7 +1551,7 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>
enum SharedEmitterMessage { enum SharedEmitterMessage {
Diagnostic(Diagnostic), Diagnostic(Diagnostic),
InlineAsmError(u32, String, Option<(String, Vec<InnerSpan>)>), InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
AbortIfErrors, AbortIfErrors,
Fatal(String), Fatal(String),
} }
@ -1576,9 +1576,10 @@ impl SharedEmitter {
&self, &self,
cookie: u32, cookie: u32,
msg: String, msg: String,
level: Level,
source: Option<(String, Vec<InnerSpan>)>, source: Option<(String, Vec<InnerSpan>)>,
) { ) {
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, source))); drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
} }
pub fn fatal(&self, msg: &str) { pub fn fatal(&self, msg: &str) {
@ -1631,16 +1632,21 @@ impl SharedEmitterMain {
} }
handler.emit_diagnostic(&d); handler.emit_diagnostic(&d);
} }
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, source)) => { Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
let msg = msg.strip_prefix("error: ").unwrap_or(&msg); let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
let mut err = match level {
Level::Error => sess.struct_err(&msg),
Level::Warning => sess.struct_warn(&msg),
Level::Note => sess.struct_note_without_error(&msg),
_ => bug!("Invalid inline asm diagnostic level"),
};
// If the cookie is 0 then we don't have span information. // If the cookie is 0 then we don't have span information.
let mut err = if cookie == 0 { if cookie != 0 {
sess.struct_err(&msg)
} else {
let pos = BytePos::from_u32(cookie); let pos = BytePos::from_u32(cookie);
let span = Span::with_root_ctxt(pos, pos); let span = Span::with_root_ctxt(pos, pos);
sess.struct_span_err(span, &msg) err.set_span(span);
}; };
// Point to the generated assembly if it is available. // Point to the generated assembly if it is available.

View file

@ -530,6 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args: &Vec<mir::Operand<'tcx>>, args: &Vec<mir::Operand<'tcx>>,
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>, cleanup: Option<mir::BasicBlock>,
fn_span: Span,
) { ) {
let span = terminator.source_info.span; let span = terminator.source_info.span;
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
@ -634,7 +635,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if intrinsic == Some("caller_location") { if intrinsic == Some("caller_location") {
if let Some((_, target)) = destination.as_ref() { if let Some((_, target)) = destination.as_ref() {
let location = self.get_caller_location(&mut bx, span); let location = self.get_caller_location(&mut bx, fn_span);
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
location.val.store(&mut bx, tmp); location.val.store(&mut bx, tmp);
@ -798,7 +799,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args.len() + 1, args.len() + 1,
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
); );
let location = self.get_caller_location(&mut bx, span); let location = self.get_caller_location(&mut bx, fn_span);
debug!(
"codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
terminator, location, fn_span
);
let last_arg = fn_abi.args.last().unwrap(); let last_arg = fn_abi.args.last().unwrap();
self.codegen_argument(&mut bx, location, &mut llargs, last_arg); self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
} }
@ -1016,6 +1022,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ref destination, ref destination,
cleanup, cleanup,
from_hir_call: _, from_hir_call: _,
fn_span,
} => { } => {
self.codegen_call_terminator( self.codegen_call_terminator(
helper, helper,
@ -1025,6 +1032,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args, args,
destination, destination,
cleanup, cleanup,
fn_span,
); );
} }
mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => { mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {

View file

@ -1,6 +1,15 @@
`export_name` attributes may not contain null characters (`\0`). An `export_name` attribute contains null characters (`\0`).
Erroneous code example:
```compile_fail,E0648 ```compile_fail,E0648
#[export_name="\0foo"] // error: `export_name` may not contain null characters #[export_name="\0foo"] // error: `export_name` may not contain null characters
pub fn bar() {} pub fn bar() {}
``` ```
To fix this error, remove the null characters:
```
#[export_name="foo"] // ok!
pub fn bar() {}
```

View file

@ -581,6 +581,11 @@ impl Handler {
DiagnosticBuilder::new(self, Level::Help, msg) DiagnosticBuilder::new(self, Level::Help, msg)
} }
/// Construct a builder at the `Note` level with the `msg`.
pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Note, msg)
}
pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> FatalError { pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> FatalError {
self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span); self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
FatalError FatalError

View file

@ -272,7 +272,7 @@ impl<'a> ExtCtxt<'a> {
) -> P<ast::Expr> { ) -> P<ast::Expr> {
args.insert(0, expr); args.insert(0, expr);
let segment = ast::PathSegment::from_ident(ident.with_span_pos(span)); let segment = ast::PathSegment::from_ident(ident.with_span_pos(span));
self.expr(span, ast::ExprKind::MethodCall(segment, args)) self.expr(span, ast::ExprKind::MethodCall(segment, args, span))
} }
pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> { pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
self.expr(b.span, ast::ExprKind::Block(b, None)) self.expr(b.span, ast::ExprKind::Block(b, None))

View file

@ -1371,7 +1371,7 @@ pub struct Expr<'hir> {
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(Expr<'static>, 64); rustc_data_structures::static_assert_size!(Expr<'static>, 72);
impl Expr<'_> { impl Expr<'_> {
pub fn precedence(&self) -> ExprPrecedence { pub fn precedence(&self) -> ExprPrecedence {
@ -1568,12 +1568,14 @@ pub enum ExprKind<'hir> {
/// and the remaining elements are the rest of the arguments. /// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
/// The final `Span` represents the span of the function and arguments
/// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
/// ///
/// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with /// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with
/// the `hir_id` of the `MethodCall` node itself. /// the `hir_id` of the `MethodCall` node itself.
/// ///
/// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id /// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id
MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>]), MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span),
/// A tuple (e.g., `(a, b, c, d)`). /// A tuple (e.g., `(a, b, c, d)`).
Tup(&'hir [Expr<'hir>]), Tup(&'hir [Expr<'hir>]),
/// A binary operation (e.g., `a + b`, `a * b`). /// A binary operation (e.g., `a + b`, `a * b`).

View file

@ -1090,7 +1090,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
visitor.visit_expr(callee_expression); visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments); walk_list!(visitor, visit_expr, arguments);
} }
ExprKind::MethodCall(ref segment, _, arguments) => { ExprKind::MethodCall(ref segment, _, arguments, _) => {
visitor.visit_path_segment(expression.span, segment); visitor.visit_path_segment(expression.span, segment);
walk_list!(visitor, visit_expr, arguments); walk_list!(visitor, visit_expr, arguments);
} }

View file

@ -1308,7 +1308,7 @@ impl<'a> State<'a> {
hir::ExprKind::Call(ref func, ref args) => { hir::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(&func, args); self.print_expr_call(&func, args);
} }
hir::ExprKind::MethodCall(ref segment, _, ref args) => { hir::ExprKind::MethodCall(ref segment, _, ref args, _) => {
self.print_expr_method_call(segment, args); self.print_expr_method_call(segment, args);
} }
hir::ExprKind::Binary(op, ref lhs, ref rhs) => { hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
@ -2491,7 +2491,7 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
contains_exterior_struct_lit(&x) contains_exterior_struct_lit(&x)
} }
hir::ExprKind::MethodCall(.., ref exprs) => { hir::ExprKind::MethodCall(.., ref exprs, _) => {
// `X { y: 1 }.bar(...)` // `X { y: 1 }.bar(...)`
contains_exterior_struct_lit(&exprs[0]) contains_exterior_struct_lit(&exprs[0])
} }

View file

@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
} }
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if let ExprKind::MethodCall(_, call_span, exprs) = expr.kind { if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
if call_span == self.target_span if call_span == self.target_span
&& Some(self.target) && Some(self.target)
== self.infcx.in_progress_tables.and_then(|tables| { == self.infcx.in_progress_tables.and_then(|tables| {
@ -294,7 +294,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// 3 | let _ = x.sum() as f64; // 3 | let _ = x.sum() as f64;
// | ^^^ cannot infer type for `S` // | ^^^ cannot infer type for `S`
span span
} else if let Some(ExprKind::MethodCall(_, call_span, _)) = } else if let Some(ExprKind::MethodCall(_, call_span, _, _)) =
local_visitor.found_method_call.map(|e| &e.kind) local_visitor.found_method_call.map(|e| &e.kind)
{ {
// Point at the call instead of the whole expression: // Point at the call instead of the whole expression:

View file

@ -18,7 +18,7 @@ use std::fmt;
fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
tls::with_opt(|tcx| { tls::with_opt(|tcx| {
if let Some(tcx) = tcx { if let Some(tcx) = tcx {
write!(f, "{}", tcx.sess.source_map().span_to_string(span)) rustc_span::debug_with_source_map(span, f, tcx.sess.source_map())
} else { } else {
rustc_span::default_span_debug(span, f) rustc_span::default_span_debug(span, f)
} }

View file

@ -24,7 +24,7 @@ declare_lint_pass!(
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) {
// We only care about method call expressions. // We only care about method call expressions.
if let hir::ExprKind::MethodCall(call, span, args) = &expr.kind { if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind {
if call.ident.name != sym::into_iter { if call.ident.name != sym::into_iter {
return; return;
} }

View file

@ -1899,7 +1899,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
} }
} }
} }
} else if let hir::ExprKind::MethodCall(_, _, ref args) = expr.kind { } else if let hir::ExprKind::MethodCall(_, _, ref args, _) = expr.kind {
// Find problematic calls to `MaybeUninit::assume_init`. // Find problematic calls to `MaybeUninit::assume_init`.
let def_id = cx.tables.type_dependent_def_id(expr.hir_id)?; let def_id = cx.tables.type_dependent_def_id(expr.hir_id)?;
if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) { if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {

View file

@ -526,7 +526,7 @@ trait UnusedDelimLint {
let (args_to_check, ctx) = match *call_or_other { let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg), Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
// first "argument" is self (which sometimes needs delims) // first "argument" is self (which sometimes needs delims)
MethodCall(_, ref args) => (&args[1..], UnusedDelimsCtx::MethodArg), MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg),
// actual catch-all arm // actual catch-all arm
_ => { _ => {
return; return;

View file

@ -1131,6 +1131,9 @@ pub enum TerminatorKind<'tcx> {
/// `true` if this is from a call in HIR rather than from an overloaded /// `true` if this is from a call in HIR rather than from an overloaded
/// operator. True for overloaded function call. /// operator. True for overloaded function call.
from_hir_call: bool, from_hir_call: bool,
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
}, },
/// Jump to the target if the condition has the expected value, /// Jump to the target if the condition has the expected value,
@ -2449,7 +2452,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
tcx.def_path_str_with_substs(def_id.to_def_id(), substs), tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
) )
} else { } else {
format!("[closure@{:?}]", tcx.hir().span(hir_id)) let span = tcx.hir().span(hir_id);
format!("[closure@{}]", tcx.sess.source_map().span_to_string(span))
}; };
let mut struct_fmt = fmt.debug_struct(&name); let mut struct_fmt = fmt.debug_struct(&name);

View file

@ -42,7 +42,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
resume_arg: resume_arg.fold_with(folder), resume_arg: resume_arg.fold_with(folder),
drop, drop,
}, },
Call { ref func, ref args, ref destination, cleanup, from_hir_call } => { Call { ref func, ref args, ref destination, cleanup, from_hir_call, fn_span } => {
let dest = let dest =
destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
@ -52,6 +52,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
destination: dest, destination: dest,
cleanup, cleanup,
from_hir_call, from_hir_call,
fn_span,
} }
} }
Assert { ref cond, expected, ref msg, target, cleanup } => { Assert { ref cond, expected, ref msg, target, cleanup } => {

View file

@ -492,6 +492,7 @@ macro_rules! make_mir_visitor {
destination, destination,
cleanup: _, cleanup: _,
from_hir_call: _, from_hir_call: _,
fn_span: _
} => { } => {
self.visit_operand(func, source_location); self.visit_operand(func, source_location);
for arg in args { for arg in args {

View file

@ -605,7 +605,8 @@ pub trait PrettyPrinter<'tcx>:
// FIXME(eddyb) should use `def_span`. // FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() { if let Some(did) = did.as_local() {
let hir_id = self.tcx().hir().as_local_hir_id(did); let hir_id = self.tcx().hir().as_local_hir_id(did);
p!(write("@{:?}", self.tcx().hir().span(hir_id))); let span = self.tcx().hir().span(hir_id);
p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
if substs.as_generator().is_valid() { if substs.as_generator().is_valid() {
let upvar_tys = substs.as_generator().upvar_tys(); let upvar_tys = substs.as_generator().upvar_tys();
@ -653,7 +654,8 @@ pub trait PrettyPrinter<'tcx>:
if self.tcx().sess.opts.debugging_opts.span_free_formats { if self.tcx().sess.opts.debugging_opts.span_free_formats {
p!(write("@"), print_def_path(did.to_def_id(), substs)); p!(write("@"), print_def_path(did.to_def_id(), substs));
} else { } else {
p!(write("@{:?}", self.tcx().hir().span(hir_id))); let span = self.tcx().hir().span(hir_id);
p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
} }
if substs.as_closure().is_valid() { if substs.as_closure().is_valid() {
@ -1362,7 +1364,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
if !self.empty_path { if !self.empty_path {
write!(self, "::")?; write!(self, "::")?;
} }
write!(self, "<impl at {:?}>", span)?; write!(self, "<impl at {}>", self.tcx.sess.source_map().span_to_string(span))?;
self.empty_path = false; self.empty_path = false;
return Ok(self); return Ok(self);

View file

@ -142,6 +142,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
destination, destination,
cleanup: _, cleanup: _,
from_hir_call: _, from_hir_call: _,
fn_span: _,
} => { } => {
self.consume_operand(location, func); self.consume_operand(location, func);
for arg in args { for arg in args {

View file

@ -699,6 +699,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
ref destination, ref destination,
cleanup: _, cleanup: _,
from_hir_call: _, from_hir_call: _,
fn_span: _,
} => { } => {
self.consume_operand(loc, (func, span), flow_state); self.consume_operand(loc, (func, span), flow_state);
for arg in args { for arg in args {

View file

@ -314,7 +314,7 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
infcx: &InferCtxt<'a, 'tcx>, infcx: &InferCtxt<'a, 'tcx>,
source: MirSource<'tcx>, source: MirSource<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'_>, regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
) { ) {
if !mir_util::dump_enabled(infcx.tcx, "nll", source.def_id()) { if !mir_util::dump_enabled(infcx.tcx, "nll", source.def_id()) {
@ -325,7 +325,7 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
match pass_where { match pass_where {
// Before the CFG, dump out the values for each region variable. // Before the CFG, dump out the values for each region variable.
PassWhere::BeforeCFG => { PassWhere::BeforeCFG => {
regioncx.dump_mir(out)?; regioncx.dump_mir(infcx.tcx, out)?;
writeln!(out, "|")?; writeln!(out, "|")?;
if let Some(closure_region_requirements) = closure_region_requirements { if let Some(closure_region_requirements) = closure_region_requirements {

View file

@ -4,7 +4,9 @@
//! context internal state. //! context internal state.
use super::{OutlivesConstraint, RegionInferenceContext}; use super::{OutlivesConstraint, RegionInferenceContext};
use crate::borrow_check::type_check::Locations;
use rustc_infer::infer::NLLRegionVariableOrigin; use rustc_infer::infer::NLLRegionVariableOrigin;
use rustc_middle::ty::TyCtxt;
use std::io::{self, Write}; use std::io::{self, Write};
// Room for "'_#NNNNr" before things get misaligned. // Room for "'_#NNNNr" before things get misaligned.
@ -14,7 +16,7 @@ const REGION_WIDTH: usize = 8;
impl<'tcx> RegionInferenceContext<'tcx> { impl<'tcx> RegionInferenceContext<'tcx> {
/// Write out our state into the `.mir` files. /// Write out our state into the `.mir` files.
pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> { pub(crate) fn dump_mir(&self, tcx: TyCtxt<'tcx>, out: &mut dyn Write) -> io::Result<()> {
writeln!(out, "| Free Region Mapping")?; writeln!(out, "| Free Region Mapping")?;
for region in self.regions() { for region in self.regions() {
@ -48,7 +50,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
writeln!(out, "|")?; writeln!(out, "|")?;
writeln!(out, "| Inference Constraints")?; writeln!(out, "| Inference Constraints")?;
self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?; self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?;
Ok(()) Ok(())
} }
@ -59,6 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// inference resulted in the values that it did when debugging. /// inference resulted in the values that it did when debugging.
fn for_each_constraint( fn for_each_constraint(
&self, &self,
tcx: TyCtxt<'tcx>,
with_msg: &mut dyn FnMut(&str) -> io::Result<()>, with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
) -> io::Result<()> { ) -> io::Result<()> {
for region in self.definitions.indices() { for region in self.definitions.indices() {
@ -72,7 +75,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
constraints.sort(); constraints.sort();
for constraint in &constraints { for constraint in &constraints {
let OutlivesConstraint { sup, sub, locations, category } = constraint; let OutlivesConstraint { sup, sub, locations, category } = constraint;
with_msg(&format!("{:?}: {:?} due to {:?} at {:?}", sup, sub, category, locations,))?; let (name, arg) = match locations {
Locations::All(span) => ("All", tcx.sess.source_map().span_to_string(*span)),
Locations::Single(loc) => ("Single", format!("{:?}", loc)),
};
with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?;
} }
Ok(()) Ok(())

View file

@ -467,7 +467,7 @@ impl Direction for Forward {
propagate(target, exit_state); propagate(target, exit_state);
} }
Call { cleanup, destination, ref func, ref args, from_hir_call: _ } => { Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => {
if let Some(unwind) = cleanup { if let Some(unwind) = cleanup {
if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
propagate(unwind, exit_state); propagate(unwind, exit_state);

View file

@ -41,6 +41,7 @@ fn mock_body() -> mir::Body<'static> {
destination: Some((dummy_place.clone(), mir::START_BLOCK)), destination: Some((dummy_place.clone(), mir::START_BLOCK)),
cleanup: None, cleanup: None,
from_hir_call: false, from_hir_call: false,
fn_span: DUMMY_SP,
}, },
); );
block(3, mir::TerminatorKind::Return); block(3, mir::TerminatorKind::Return);
@ -53,6 +54,7 @@ fn mock_body() -> mir::Body<'static> {
destination: Some((dummy_place.clone(), mir::START_BLOCK)), destination: Some((dummy_place.clone(), mir::START_BLOCK)),
cleanup: None, cleanup: None,
from_hir_call: false, from_hir_call: false,
fn_span: DUMMY_SP,
}, },
); );

View file

@ -401,6 +401,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
ref destination, ref destination,
cleanup: _, cleanup: _,
from_hir_call: _, from_hir_call: _,
fn_span: _,
} => { } => {
self.gather_operand(func); self.gather_operand(func);
for arg in args { for arg in args {

View file

@ -1,6 +1,7 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use rustc_hir::lang_items::PanicLocationLangItem; use rustc_hir::lang_items::PanicLocationLangItem;
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::Subst;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use rustc_target::abi::LayoutOf; use rustc_target::abi::LayoutOf;
@ -14,19 +15,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`. /// frame which is not `#[track_caller]`.
crate fn find_closest_untracked_caller_location(&self) -> Span { crate fn find_closest_untracked_caller_location(&self) -> Span {
self.stack() let frame = self
.stack()
.iter() .iter()
.rev() .rev()
// Find first non-`#[track_caller]` frame. // Find first non-`#[track_caller]` frame.
.find(|frame| !frame.instance.def.requires_caller_location(*self.tcx)) .find(|frame| {
debug!(
"find_closest_untracked_caller_location: checking frame {:?}",
frame.instance
);
!frame.instance.def.requires_caller_location(*self.tcx)
})
// Assert that there is always such a frame. // Assert that there is always such a frame.
.unwrap() .unwrap();
.current_source_info() let loc = frame.loc.unwrap();
// Assert that the frame we look at is actually executing code currently let block = &frame.body.basic_blocks()[loc.block];
// (`current_source_info` is None when we are unwinding and the frame does assert_eq!(block.statements.len(), loc.statement_index);
// not require cleanup). debug!(
.unwrap() "find_closest_untracked_caller_location:: got terminator {:?} ({:?})",
.span block.terminator(),
block.terminator().kind
);
if let TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
return fn_span;
}
unreachable!();
} }
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers. /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.

View file

@ -56,6 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
destination, destination,
ref cleanup, ref cleanup,
from_hir_call: _from_hir_call, from_hir_call: _from_hir_call,
fn_span: _,
} => { } => {
let old_stack = self.frame_idx(); let old_stack = self.frame_idx();
let old_loc = self.frame().loc; let old_loc = self.frame().loc;

View file

@ -460,6 +460,7 @@ impl CloneShimBuilder<'tcx> {
destination: Some((dest, next)), destination: Some((dest, next)),
cleanup: Some(cleanup), cleanup: Some(cleanup),
from_hir_call: true, from_hir_call: true,
fn_span: self.span,
}, },
false, false,
); );
@ -788,6 +789,7 @@ fn build_call_shim<'tcx>(
None None
}, },
from_hir_call: true, from_hir_call: true,
fn_span: span,
}, },
false, false,
); );

View file

@ -909,7 +909,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
}; };
match terminator.kind { match terminator.kind {
TerminatorKind::Call { mut func, mut args, from_hir_call, .. } => { TerminatorKind::Call { mut func, mut args, from_hir_call, fn_span, .. } => {
self.visit_operand(&mut func, loc); self.visit_operand(&mut func, loc);
for arg in &mut args { for arg in &mut args {
self.visit_operand(arg, loc); self.visit_operand(arg, loc);
@ -925,6 +925,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
cleanup: None, cleanup: None,
destination: Some((Place::from(new_temp), new_target)), destination: Some((Place::from(new_temp), new_target)),
from_hir_call, from_hir_call,
fn_span,
}, },
..terminator ..terminator
}; };

View file

@ -368,7 +368,14 @@ fn check_terminator(
Err((span, "const fn generators are unstable".into())) Err((span, "const fn generators are unstable".into()))
} }
TerminatorKind::Call { func, args, from_hir_call: _, destination: _, cleanup: _ } => { TerminatorKind::Call {
func,
args,
from_hir_call: _,
destination: _,
cleanup: _,
fn_span: _,
} => {
let fn_ty = func.ty(body, tcx); let fn_ty = func.ty(body, tcx);
if let ty::FnDef(def_id, _) = fn_ty.kind { if let ty::FnDef(def_id, _) = fn_ty.kind {
if !crate::const_eval::is_min_const_fn(tcx, def_id) { if !crate::const_eval::is_min_const_fn(tcx, def_id) {

View file

@ -644,6 +644,7 @@ where
destination: Some((unit_temp, succ)), destination: Some((unit_temp, succ)),
cleanup: unwind.into_option(), cleanup: unwind.into_option(),
from_hir_call: true, from_hir_call: true,
fn_span: self.source_info.span,
}, },
source_info: self.source_info, source_info: self.source_info,
}), }),
@ -988,6 +989,7 @@ where
destination: Some((unit_temp, target)), destination: Some((unit_temp, target)),
cleanup: None, cleanup: None,
from_hir_call: false, from_hir_call: false,
fn_span: self.source_info.span,
}; // FIXME(#43234) }; // FIXME(#43234)
let free_block = self.new_block(unwind, call); let free_block = self.new_block(unwind, call);

View file

@ -135,7 +135,7 @@ fn dump_matched_mir_node<'tcx, F>(
} }
writeln!(file)?; writeln!(file)?;
extra_data(PassWhere::BeforeCFG, &mut file)?; extra_data(PassWhere::BeforeCFG, &mut file)?;
write_user_type_annotations(body, &mut file)?; write_user_type_annotations(tcx, body, &mut file)?;
write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?; write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?;
extra_data(PassWhere::AfterCFG, &mut file)?; extra_data(PassWhere::AfterCFG, &mut file)?;
}; };
@ -351,7 +351,7 @@ fn write_extra<'tcx, F>(tcx: TyCtxt<'tcx>, write: &mut dyn Write, mut visit_op:
where where
F: FnMut(&mut ExtraComments<'tcx>), F: FnMut(&mut ExtraComments<'tcx>),
{ {
let mut extra_comments = ExtraComments { _tcx: tcx, comments: vec![] }; let mut extra_comments = ExtraComments { tcx, comments: vec![] };
visit_op(&mut extra_comments); visit_op(&mut extra_comments);
for comment in extra_comments.comments { for comment in extra_comments.comments {
writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?; writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
@ -360,7 +360,7 @@ where
} }
struct ExtraComments<'tcx> { struct ExtraComments<'tcx> {
_tcx: TyCtxt<'tcx>, // don't need it now, but bet we will soon tcx: TyCtxt<'tcx>,
comments: Vec<String>, comments: Vec<String>,
} }
@ -377,7 +377,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
self.super_constant(constant, location); self.super_constant(constant, location);
let Constant { span, user_ty, literal } = constant; let Constant { span, user_ty, literal } = constant;
self.push("mir::Constant"); self.push("mir::Constant");
self.push(&format!("+ span: {:?}", span)); self.push(&format!("+ span: {}", self.tcx.sess.source_map().span_to_string(*span)));
if let Some(user_ty) = user_ty { if let Some(user_ty) = user_ty {
self.push(&format!("+ user_ty: {:?}", user_ty)); self.push(&format!("+ user_ty: {:?}", user_ty));
} }
@ -862,12 +862,22 @@ fn write_mir_sig(
Ok(()) Ok(())
} }
fn write_user_type_annotations(body: &Body<'_>, w: &mut dyn Write) -> io::Result<()> { fn write_user_type_annotations(
tcx: TyCtxt<'_>,
body: &Body<'_>,
w: &mut dyn Write,
) -> io::Result<()> {
if !body.user_type_annotations.is_empty() { if !body.user_type_annotations.is_empty() {
writeln!(w, "| User Type Annotations")?; writeln!(w, "| User Type Annotations")?;
} }
for (index, annotation) in body.user_type_annotations.iter_enumerated() { for (index, annotation) in body.user_type_annotations.iter_enumerated() {
writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation.user_ty, annotation.span)?; writeln!(
w,
"| {:?}: {:?} at {}",
index.index(),
annotation.user_ty,
tcx.sess.source_map().span_to_string(annotation.span)
)?;
} }
if !body.user_type_annotations.is_empty() { if !body.user_type_annotations.is_empty() {
writeln!(w, "|")?; writeln!(w, "|")?;

View file

@ -162,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}); });
exit_block.unit() exit_block.unit()
} }
ExprKind::Call { ty, fun, args, from_hir_call } => { ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
let intrinsic = match ty.kind { let intrinsic = match ty.kind {
ty::FnDef(def_id, _) => { ty::FnDef(def_id, _) => {
let f = ty.fn_sig(this.hir.tcx()); let f = ty.fn_sig(this.hir.tcx());
@ -206,6 +206,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.record_operands_moved(&args); this.record_operands_moved(&args);
debug!("into_expr: fn_span={:?}", fn_span);
this.cfg.terminate( this.cfg.terminate(
block, block,
source_info, source_info,
@ -222,6 +224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Some((destination, success)) Some((destination, success))
}, },
from_hir_call, from_hir_call,
fn_span
}, },
); );
success.unit() success.unit()

View file

@ -443,6 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Some((eq_result, eq_block)), destination: Some((eq_result, eq_block)),
cleanup: Some(cleanup), cleanup: Some(cleanup),
from_hir_call: false, from_hir_call: false,
fn_span: source_info.span
}, },
); );

View file

@ -139,11 +139,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
let kind = match expr.kind { let kind = match expr.kind {
// Here comes the interesting stuff: // Here comes the interesting stuff:
hir::ExprKind::MethodCall(_, method_span, ref args) => { hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => {
// Rewrite a.b(c) into UFCS form like Trait::b(a, c) // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
let expr = method_callee(cx, expr, method_span, None); let expr = method_callee(cx, expr, method_span, None);
let args = args.iter().map(|e| e.to_ref()).collect(); let args = args.iter().map(|e| e.to_ref()).collect();
ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true } ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true, fn_span }
} }
hir::ExprKind::Call(ref fun, ref args) => { hir::ExprKind::Call(ref fun, ref args) => {
@ -170,6 +170,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
fun: method.to_ref(), fun: method.to_ref(),
args: vec![fun.to_ref(), tupled_args.to_ref()], args: vec![fun.to_ref(), tupled_args.to_ref()],
from_hir_call: true, from_hir_call: true,
fn_span: expr.span,
} }
} else { } else {
let adt_data = let adt_data =
@ -215,6 +216,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
fun: fun.to_ref(), fun: fun.to_ref(),
args: args.to_ref(), args: args.to_ref(),
from_hir_call: true, from_hir_call: true,
fn_span: expr.span,
} }
} }
} }
@ -1024,7 +1026,7 @@ fn overloaded_operator<'a, 'tcx>(
args: Vec<ExprRef<'tcx>>, args: Vec<ExprRef<'tcx>>,
) -> ExprKind<'tcx> { ) -> ExprKind<'tcx> {
let fun = method_callee(cx, expr, expr.span, None); let fun = method_callee(cx, expr, expr.span, None);
ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false } ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false, fn_span: expr.span }
} }
fn overloaded_place<'a, 'tcx>( fn overloaded_place<'a, 'tcx>(
@ -1060,7 +1062,13 @@ fn overloaded_place<'a, 'tcx>(
temp_lifetime, temp_lifetime,
ty: ref_ty, ty: ref_ty,
span: expr.span, span: expr.span,
kind: ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false }, kind: ExprKind::Call {
ty: fun.ty,
fun: fun.to_ref(),
args,
from_hir_call: false,
fn_span: expr.span,
},
}; };
// construct and return a deref wrapper `*foo()` // construct and return a deref wrapper `*foo()`

View file

@ -146,6 +146,9 @@ crate enum ExprKind<'tcx> {
// Whether this is from a call in HIR, rather than from an overloaded // Whether this is from a call in HIR, rather than from an overloaded
// operator. True for overloaded function call. // operator. True for overloaded function call.
from_hir_call: bool, from_hir_call: bool,
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
}, },
Deref { Deref {
arg: ExprRef<'tcx>, arg: ExprRef<'tcx>,

View file

@ -639,7 +639,7 @@ impl<'a> Parser<'a> {
ExprKind::Index(_, _) => "indexing", ExprKind::Index(_, _) => "indexing",
ExprKind::Try(_) => "?", ExprKind::Try(_) => "?",
ExprKind::Field(_, _) => "a field access", ExprKind::Field(_, _) => "a field access",
ExprKind::MethodCall(_, _) => "a method call", ExprKind::MethodCall(_, _, _) => "a method call",
ExprKind::Call(_, _) => "a function call", ExprKind::Call(_, _) => "a function call",
ExprKind::Await(_) => "`.await`", ExprKind::Await(_) => "`.await`",
ExprKind::Err => return Ok(with_postfix), ExprKind::Err => return Ok(with_postfix),
@ -865,6 +865,7 @@ impl<'a> Parser<'a> {
return self.mk_await_expr(self_arg, lo); return self.mk_await_expr(self_arg, lo);
} }
let fn_span_lo = self.token.span;
let segment = self.parse_path_segment(PathStyle::Expr)?; let segment = self.parse_path_segment(PathStyle::Expr)?;
self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
@ -873,8 +874,9 @@ impl<'a> Parser<'a> {
let mut args = self.parse_paren_expr_seq()?; let mut args = self.parse_paren_expr_seq()?;
args.insert(0, self_arg); args.insert(0, self_arg);
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new())) Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span), AttrVec::new()))
} else { } else {
// Field access `expr.f` // Field access `expr.f`
if let Some(args) = segment.args { if let Some(args) = segment.args {

View file

@ -1198,7 +1198,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(&f, succ) self.propagate_through_expr(&f, succ)
} }
hir::ExprKind::MethodCall(.., ref args) => { hir::ExprKind::MethodCall(.., ref args, _) => {
let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
let succ = if self.ir.tcx.is_ty_uninhabited_from( let succ = if self.ir.tcx.is_ty_uninhabited_from(
m, m,

View file

@ -1302,7 +1302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
return; return;
} }
} }
hir::ExprKind::MethodCall(_, span, _) => { hir::ExprKind::MethodCall(_, span, _, _) => {
// Method calls have to be checked specially. // Method calls have to be checked specially.
self.span = span; self.span = span;
if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) { if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) {

View file

@ -2117,7 +2117,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Field(ref subexpression, _) => { ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr)); self.resolve_expr(subexpression, Some(expr));
} }
ExprKind::MethodCall(ref segment, ref arguments) => { ExprKind::MethodCall(ref segment, ref arguments, _) => {
let mut arguments = arguments.iter(); let mut arguments = arguments.iter();
self.resolve_expr(arguments.next().unwrap(), Some(expr)); self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments { for argument in arguments {

View file

@ -1404,7 +1404,9 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
let res = self.save_ctxt.get_path_res(hir_expr.hir_id); let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *base) self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *base)
} }
hir::ExprKind::MethodCall(ref seg, _, args) => self.process_method_call(ex, seg, args), hir::ExprKind::MethodCall(ref seg, _, args, _) => {
self.process_method_call(ex, seg, args)
}
hir::ExprKind::Field(ref sub_ex, _) => { hir::ExprKind::Field(ref sub_ex, _) => {
self.visit_expr(&sub_ex); self.visit_expr(&sub_ex);

View file

@ -441,6 +441,9 @@ impl Session {
pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.diagnostic().span_note_without_error(sp, msg) self.diagnostic().span_note_without_error(sp, msg)
} }
pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_note_without_error(msg)
}
pub fn diagnostic(&self) -> &rustc_errors::Handler { pub fn diagnostic(&self) -> &rustc_errors::Handler {
&self.parse_sess.span_diagnostic &self.parse_sess.span_diagnostic

View file

@ -726,10 +726,18 @@ pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) ->
f() f()
} }
pub fn debug_with_source_map(
span: Span,
f: &mut fmt::Formatter<'_>,
source_map: &SourceMap,
) -> fmt::Result {
write!(f, "{} ({:?})", source_map.span_to_string(span), span.ctxt())
}
pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
GLOBALS.with(|globals| { GLOBALS.with(|globals| {
if let Some(source_map) = &*globals.source_map.borrow() { if let Some(source_map) = &*globals.source_map.borrow() {
write!(f, "{}", source_map.span_to_string(span)) debug_with_source_map(span, f, source_map)
} else { } else {
f.debug_struct("Span") f.debug_struct("Span")
.field("lo", &span.lo()) .field("lo", &span.lo())

View file

@ -307,7 +307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (method_path, method_span, method_expr) = match (hir, closure_params_len) { let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
( (
Some(Node::Expr(hir::Expr { Some(Node::Expr(hir::Expr {
kind: hir::ExprKind::MethodCall(path, span, expr), kind: hir::ExprKind::MethodCall(path, span, expr, _),
.. ..
})), })),
1, 1,
@ -457,7 +457,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
if self.can_coerce(ref_ty, expected) { if self.can_coerce(ref_ty, expected) {
let mut sugg_sp = sp; let mut sugg_sp = sp;
if let hir::ExprKind::MethodCall(ref segment, sp, ref args) = expr.kind { if let hir::ExprKind::MethodCall(ref segment, sp, ref args, _) = expr.kind {
let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp)); let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp));
if let ([arg], Some(true), sym::clone) = ( if let ([arg], Some(true), sym::clone) = (
&args[..], &args[..],

View file

@ -182,7 +182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Call(ref callee, _) => { ExprKind::Call(ref callee, _) => {
self.warn_if_unreachable(expr.hir_id, callee.span, "call") self.warn_if_unreachable(expr.hir_id, callee.span, "call")
} }
ExprKind::MethodCall(_, ref span, _) => { ExprKind::MethodCall(_, ref span, _, _) => {
self.warn_if_unreachable(expr.hir_id, *span, "call") self.warn_if_unreachable(expr.hir_id, *span, "call")
} }
_ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"), _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
@ -262,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
ExprKind::Block(ref body, _) => self.check_block_with_expected(&body, expected), ExprKind::Block(ref body, _) => self.check_block_with_expected(&body, expected),
ExprKind::Call(ref callee, ref args) => self.check_call(expr, &callee, args, expected), ExprKind::Call(ref callee, ref args) => self.check_call(expr, &callee, args, expected),
ExprKind::MethodCall(ref segment, span, ref args) => { ExprKind::MethodCall(ref segment, span, ref args, _) => {
self.check_method_call(expr, segment, span, args, expected, needs) self.check_method_call(expr, segment, span, args, expected, needs)
} }
ExprKind::Cast(ref e, ref t) => self.check_expr_cast(e, t, expr), ExprKind::Cast(ref e, ref t) => self.check_expr_cast(e, t, expr),

View file

@ -3912,7 +3912,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg_unit: bool| { sugg_unit: bool| {
let (span, start_span, args) = match &expr.kind { let (span, start_span, args) = match &expr.kind {
hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]), hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]),
hir::ExprKind::MethodCall(path_segment, span, args) => ( hir::ExprKind::MethodCall(path_segment, span, args, _) => (
*span, *span,
// `sp` doesn't point at the whole `foo.bar()`, only at `bar`. // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
path_segment path_segment

View file

@ -185,7 +185,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.consume_exprs(args); self.consume_exprs(args);
} }
hir::ExprKind::MethodCall(.., ref args) => { hir::ExprKind::MethodCall(.., ref args, _) => {
// callee.m(args) // callee.m(args)
self.consume_exprs(args); self.consume_exprs(args);
} }

View file

@ -676,7 +676,11 @@ impl Collector {
} }
fn generate_name(&self, line: usize, filename: &FileName) -> String { fn generate_name(&self, line: usize, filename: &FileName) -> String {
format!("{} - {} (line {})", filename, self.names.join("::"), line) let mut item_path = self.names.join("::");
if !item_path.is_empty() {
item_path.push(' ');
}
format!("{} - {}(line {})", filename, item_path, line)
} }
pub fn set_position(&mut self, position: Span) { pub fn set_position(&mut self, position: Span) {

View file

@ -1094,8 +1094,17 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
MessageOS << Opt->getMsg(); MessageOS << Opt->getMsg();
} }
enum class LLVMRustDiagnosticLevel {
Error,
Warning,
Note,
Remark,
};
extern "C" void extern "C" void
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut, LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
LLVMRustDiagnosticLevel *LevelOut,
unsigned *CookieOut,
LLVMTwineRef *MessageOut, LLVMTwineRef *MessageOut,
LLVMValueRef *InstructionOut) { LLVMValueRef *InstructionOut) {
// Undefined to call this not on an inline assembly diagnostic! // Undefined to call this not on an inline assembly diagnostic!
@ -1105,6 +1114,23 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
*CookieOut = IA->getLocCookie(); *CookieOut = IA->getLocCookie();
*MessageOut = wrap(&IA->getMsgStr()); *MessageOut = wrap(&IA->getMsgStr());
*InstructionOut = wrap(IA->getInstruction()); *InstructionOut = wrap(IA->getInstruction());
switch (IA->getSeverity()) {
case DS_Error:
*LevelOut = LLVMRustDiagnosticLevel::Error;
break;
case DS_Warning:
*LevelOut = LLVMRustDiagnosticLevel::Warning;
break;
case DS_Note:
*LevelOut = LLVMRustDiagnosticLevel::Note;
break;
case DS_Remark:
*LevelOut = LLVMRustDiagnosticLevel::Remark;
break;
default:
report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
}
} }
extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI, extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
@ -1166,6 +1192,7 @@ extern "C" LLVMRustDiagnosticKind
LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) { LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
return toRust((DiagnosticKind)unwrap(DI)->getKind()); return toRust((DiagnosticKind)unwrap(DI)->getKind());
} }
// This is kept distinct from LLVMGetTypeKind, because when // This is kept distinct from LLVMGetTypeKind, because when
// a new type kind is added, the Rust-side enum must be // a new type kind is added, the Rust-side enum must be
// updated or UB will result. // updated or UB will result.
@ -1219,6 +1246,7 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
RustStringRef MessageOut, RustStringRef MessageOut,
RustStringRef BufferOut, RustStringRef BufferOut,
LLVMRustDiagnosticLevel* LevelOut,
unsigned* LocOut, unsigned* LocOut,
unsigned* RangesOut, unsigned* RangesOut,
size_t* NumRanges) { size_t* NumRanges) {
@ -1226,6 +1254,23 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
RawRustStringOstream MessageOS(MessageOut); RawRustStringOstream MessageOS(MessageOut);
MessageOS << D.getMessage(); MessageOS << D.getMessage();
switch (D.getKind()) {
case SourceMgr::DK_Error:
*LevelOut = LLVMRustDiagnosticLevel::Error;
break;
case SourceMgr::DK_Warning:
*LevelOut = LLVMRustDiagnosticLevel::Warning;
break;
case SourceMgr::DK_Note:
*LevelOut = LLVMRustDiagnosticLevel::Note;
break;
case SourceMgr::DK_Remark:
*LevelOut = LLVMRustDiagnosticLevel::Remark;
break;
default:
report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
}
if (D.getLoc() == SMLoc()) if (D.getLoc() == SMLoc())
return false; return false;

View file

@ -0,0 +1,15 @@
// compile-flags:--test --test-args=--test-threads=1
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// check-pass
//! ```
//! assert_eq!(1 + 1, 2);
//! ```
pub mod foo {
/// ```
/// assert_eq!(1 + 1, 2);
/// ```
pub fn bar() {}
}

View file

@ -0,0 +1,7 @@
running 2 tests
test $DIR/doctest-output.rs - (line 5) ... ok
test $DIR/doctest-output.rs - foo::bar (line 11) ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

View file

@ -84,9 +84,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
2 => { 2 => {
let seg = PathSegment::from_ident(Ident::from_str("x")); let seg = PathSegment::from_ident(Ident::from_str("x"));
iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall( iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
seg.clone(), vec![e, make_x()]))); seg.clone(), vec![e, make_x()], DUMMY_SP)));
iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall( iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
seg.clone(), vec![make_x(), e]))); seg.clone(), vec![make_x(), e], DUMMY_SP)));
}, },
3..=8 => { 3..=8 => {
let op = Spanned { let op = Spanned {

View file

@ -22,5 +22,7 @@ fn main() {
//~^ ERROR invalid reference to argument at index 0 //~^ ERROR invalid reference to argument at index 0
asm!("{:foo}", in(reg) foo); asm!("{:foo}", in(reg) foo);
//~^ ERROR asm template modifier must be a single character //~^ ERROR asm template modifier must be a single character
asm!("", in(reg) 0, in(reg) 1);
//~^ ERROR multiple unused asm arguments
} }
} }

View file

@ -19,6 +19,8 @@ error: argument never used
| |
LL | asm!("{1}", in(reg) foo); LL | asm!("{1}", in(reg) foo);
| ^^^^^^^^^^^ argument never used | ^^^^^^^^^^^ argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
error: there is no argument named `a` error: there is no argument named `a`
--> $DIR/bad-template.rs:13:15 --> $DIR/bad-template.rs:13:15
@ -46,6 +48,8 @@ error: named argument never used
| |
LL | asm!("{}", a = in(reg) foo); LL | asm!("{}", a = in(reg) foo);
| ^^^^^^^^^^^^^^^ named argument never used | ^^^^^^^^^^^^^^^ named argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
error: invalid reference to argument at index 1 error: invalid reference to argument at index 1
--> $DIR/bad-template.rs:18:15 --> $DIR/bad-template.rs:18:15
@ -60,6 +64,8 @@ error: named argument never used
| |
LL | asm!("{1}", a = in(reg) foo); LL | asm!("{1}", a = in(reg) foo);
| ^^^^^^^^^^^^^^^ named argument never used | ^^^^^^^^^^^^^^^ named argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
error: invalid reference to argument at index 0 error: invalid reference to argument at index 0
--> $DIR/bad-template.rs:21:15 --> $DIR/bad-template.rs:21:15
@ -82,5 +88,15 @@ error: asm template modifier must be a single character
LL | asm!("{:foo}", in(reg) foo); LL | asm!("{:foo}", in(reg) foo);
| ^^^ | ^^^
error: aborting due to 10 previous errors error: multiple unused asm arguments
--> $DIR/bad-template.rs:25:18
|
LL | asm!("", in(reg) 0, in(reg) 1);
| ^^^^^^^^^ ^^^^^^^^^ argument never used
| |
| argument never used
|
= help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
error: aborting due to 11 previous errors

View file

@ -127,6 +127,8 @@ error: argument never used
| |
LL | asm!("{a}", a = const foo, a = const bar); LL | asm!("{a}", a = const foo, a = const bar);
| ^^^^^^^^^^^^^ argument never used | ^^^^^^^^^^^^^ argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
error: explicit register arguments cannot have names error: explicit register arguments cannot have names
--> $DIR/parse-error.rs:47:18 --> $DIR/parse-error.rs:47:18

View file

@ -37,5 +37,8 @@ fn main() {
asm!(concat!("invalid", "_", "instruction")); asm!(concat!("invalid", "_", "instruction"));
//~^ ERROR: invalid instruction mnemonic 'invalid_instruction' //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
//~^ WARN: scale factor without index register is ignored
} }
} }

View file

@ -70,5 +70,17 @@ note: instantiated into assembly here
LL | invalid_instruction LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors warning: scale factor without index register is ignored
--> $DIR/srcloc.rs:41:15
|
LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
| ^
|
note: instantiated into assembly here
--> <inline asm>:1:23
|
LL | movaps %xmm3, (%esi, 2)
| ^
error: aborting due to 6 previous errors; 1 warning emitted

View file

@ -1,166 +1,166 @@
TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 }] TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }]
TokenStream [ TokenStream [
Ident { Ident {
ident: "ident", ident: "ident",
span: $DIR/dump-debug-span-debug.rs:9:5: 9:10, span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0),
}, },
Ident { Ident {
ident: "r#ident", ident: "r#ident",
span: $DIR/dump-debug-span-debug.rs:10:5: 10:12, span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0),
}, },
Punct { Punct {
ch: ',', ch: ',',
spacing: Alone, spacing: Alone,
span: $DIR/dump-debug-span-debug.rs:11:5: 11:6, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0),
}, },
Punct { Punct {
ch: '=', ch: '=',
spacing: Joint, spacing: Joint,
span: $DIR/dump-debug-span-debug.rs:12:5: 12:7, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
}, },
Punct { Punct {
ch: '=', ch: '=',
spacing: Joint, spacing: Joint,
span: $DIR/dump-debug-span-debug.rs:12:5: 12:7, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
}, },
Punct { Punct {
ch: '>', ch: '>',
spacing: Alone, spacing: Alone,
span: $DIR/dump-debug-span-debug.rs:12:7: 12:8, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0),
}, },
Group { Group {
delimiter: Parenthesis, delimiter: Parenthesis,
stream: TokenStream [], stream: TokenStream [],
span: $DIR/dump-debug-span-debug.rs:13:5: 13:7, span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0),
}, },
Group { Group {
delimiter: Bracket, delimiter: Bracket,
stream: TokenStream [ stream: TokenStream [
Ident { Ident {
ident: "_", ident: "_",
span: $DIR/dump-debug-span-debug.rs:14:6: 14:7, span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0),
}, },
], ],
span: $DIR/dump-debug-span-debug.rs:14:5: 14:8, span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0),
}, },
Literal { Literal {
kind: Integer, kind: Integer,
symbol: "0", symbol: "0",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:17:5: 17:6, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0),
}, },
Literal { Literal {
kind: Float, kind: Float,
symbol: "1.0", symbol: "1.0",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:18:5: 18:8, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0),
}, },
Literal { Literal {
kind: Str, kind: Str,
symbol: "S", symbol: "S",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:19:5: 19:8, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0),
}, },
Literal { Literal {
kind: ByteStr, kind: ByteStr,
symbol: "B", symbol: "B",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:20:5: 20:9, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0),
}, },
Literal { Literal {
kind: StrRaw(0), kind: StrRaw(0),
symbol: "R", symbol: "R",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:21:5: 21:9, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0),
}, },
Literal { Literal {
kind: StrRaw(2), kind: StrRaw(2),
symbol: "R", symbol: "R",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:22:5: 22:13, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0),
}, },
Literal { Literal {
kind: ByteStrRaw(0), kind: ByteStrRaw(0),
symbol: "BR", symbol: "BR",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:23:5: 23:11, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0),
}, },
Literal { Literal {
kind: ByteStrRaw(2), kind: ByteStrRaw(2),
symbol: "BR", symbol: "BR",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:24:5: 24:15, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0),
}, },
Literal { Literal {
kind: Char, kind: Char,
symbol: "C", symbol: "C",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:25:5: 25:8, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0),
}, },
Literal { Literal {
kind: Byte, kind: Byte,
symbol: "B", symbol: "B",
suffix: None, suffix: None,
span: $DIR/dump-debug-span-debug.rs:26:5: 26:9, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0),
}, },
Literal { Literal {
kind: Integer, kind: Integer,
symbol: "0", symbol: "0",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:29:5: 29:7, span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0),
}, },
Literal { Literal {
kind: Float, kind: Float,
symbol: "1.0", symbol: "1.0",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:30:5: 30:9, span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0),
}, },
Literal { Literal {
kind: Str, kind: Str,
symbol: "S", symbol: "S",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:31:5: 31:9, span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0),
}, },
Literal { Literal {
kind: ByteStr, kind: ByteStr,
symbol: "B", symbol: "B",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:32:5: 32:10, span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0),
}, },
Literal { Literal {
kind: StrRaw(0), kind: StrRaw(0),
symbol: "R", symbol: "R",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:33:5: 33:10, span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0),
}, },
Literal { Literal {
kind: StrRaw(2), kind: StrRaw(2),
symbol: "R", symbol: "R",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:34:5: 34:14, span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0),
}, },
Literal { Literal {
kind: ByteStrRaw(0), kind: ByteStrRaw(0),
symbol: "BR", symbol: "BR",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:35:5: 35:12, span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0),
}, },
Literal { Literal {
kind: ByteStrRaw(2), kind: ByteStrRaw(2),
symbol: "BR", symbol: "BR",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:36:5: 36:16, span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0),
}, },
Literal { Literal {
kind: Char, kind: Char,
symbol: "C", symbol: "C",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:37:5: 37:9, span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0),
}, },
Literal { Literal {
kind: Byte, kind: Byte,
symbol: "B", symbol: "B",
suffix: Some("q"), suffix: Some("q"),
span: $DIR/dump-debug-span-debug.rs:38:5: 38:10, span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0),
}, },
] ]

View file

@ -0,0 +1,28 @@
// run-pass
#![feature(track_caller)]
use std::panic::Location;
struct Foo;
impl Foo {
#[track_caller]
fn check_loc(&self, line: u32, col: u32) -> &Self {
let loc = Location::caller();
assert_eq!(loc.file(), file!(), "file mismatch");
assert_eq!(loc.line(), line, "line mismatch");
assert_eq!(loc.column(), col, "column mismatch");
self
}
}
fn main() {
// Tests that when `Location::caller` is used in a method chain,
// it points to the start of the correct call (the first character after the dot)
// instead of to the very first expression in the chain
let foo = Foo;
foo.
check_loc(line!(), 9).check_loc(line!(), 31)
.check_loc(line!(), 10);
}

View file

@ -70,7 +70,7 @@ fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&s
fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref method_path, _, args) = &expr.kind; if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind;
let method = method_path.ident.name.as_str(); let method = method_path.ident.name.as_str();
if type_is_atomic(cx, &args[0]); if type_is_atomic(cx, &args[0]);
if method == "load" || method == "store"; if method == "load" || method == "store";

View file

@ -247,7 +247,7 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> {
)) ))
}) })
}, },
ExprKind::MethodCall(path, _, args) if args.len() == 1 => { ExprKind::MethodCall(path, _, args, _) if args.len() == 1 => {
let type_of_receiver = cx.tables.expr_ty(&args[0]); let type_of_receiver = cx.tables.expr_ty(&args[0]);
if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type)) if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type))
&& !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type)) && !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type))

View file

@ -38,10 +38,10 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.kind; if let ExprKind::MethodCall(ref count, _, ref count_args, _) = expr.kind;
if count.ident.name == sym!(count); if count.ident.name == sym!(count);
if count_args.len() == 1; if count_args.len() == 1;
if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].kind; if let ExprKind::MethodCall(ref filter, _, ref filter_args, _) = count_args[0].kind;
if filter.ident.name == sym!(filter); if filter.ident.name == sym!(filter);
if filter_args.len() == 2; if filter_args.len() == 2;
if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind; if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind;
@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).kind { if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).kind {
return; return;
} }
let haystack = if let ExprKind::MethodCall(ref path, _, ref args) = let haystack = if let ExprKind::MethodCall(ref path, _, ref args, _) =
filter_args[0].kind { filter_args[0].kind {
let p = path.ident.name; let p = path.ident.name;
if (p == sym!(iter) || p == sym!(iter_mut)) && args.len() == 1 { if (p == sym!(iter) || p == sym!(iter_mut)) && args.len() == 1 {

View file

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
if !expr.span.from_expansion(); if !expr.span.from_expansion();
if let ExprKind::MethodCall(ref method_name, _, ref args) = &expr.kind; if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind;
if args.len() == 1; if args.len() == 1;
then { then {

View file

@ -70,7 +70,7 @@ impl EarlyLintPass for DoubleParens {
} }
} }
}, },
ExprKind::MethodCall(_, ref params) => { ExprKind::MethodCall(_, ref params, _) => {
if params.len() == 2 { if params.len() == 2 {
let param = &params[1]; let param = &params[1];
if let ExprKind::Paren(_) = param.kind { if let ExprKind::Paren(_) = param.kind {

View file

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind; if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind;
if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.kind; if let ExprKind::MethodCall(ref method_path, _ , ref args, _) = left.kind;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION); if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION);
if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right);
then { then {

View file

@ -103,7 +103,7 @@ fn check_cond<'a, 'tcx, 'b>(
check: &'b Expr<'b>, check: &'b Expr<'b>,
) -> Option<(&'static str, &'b Expr<'b>, &'b Expr<'b>)> { ) -> Option<(&'static str, &'b Expr<'b>, &'b Expr<'b>)> {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref path, _, ref params) = check.kind; if let ExprKind::MethodCall(ref path, _, ref params, _) = check.kind;
if params.len() >= 2; if params.len() >= 2;
if path.ident.name == sym!(contains_key); if path.ident.name == sym!(contains_key);
if let ExprKind::AddrOf(BorrowKind::Ref, _, ref key) = params[1].kind; if let ExprKind::AddrOf(BorrowKind::Ref, _, ref key) = params[1].kind;
@ -140,7 +140,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref path, _, ref params) = expr.kind; if let ExprKind::MethodCall(ref path, _, ref params, _) = expr.kind;
if params.len() == 3; if params.len() == 3;
if path.ident.name == sym!(insert); if path.ident.name == sym!(insert);
if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]); if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);

View file

@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaReduction {
} }
match expr.kind { match expr.kind {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => { ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
for arg in args { for arg in args {
check_closure(cx, arg) check_closure(cx, arg)
} }
@ -120,7 +120,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
); );
if_chain!( if_chain!(
if let ExprKind::MethodCall(ref path, _, ref args) = ex.kind; if let ExprKind::MethodCall(ref path, _, ref args, _) = ex.kind;
// Not the same number of arguments, there is no way the closure is the same as the function return; // Not the same number of arguments, there is no way the closure is the same as the function return;
if args.len() == decl.inputs.len(); if args.len() == decl.inputs.len();

View file

@ -32,11 +32,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
// match call to unwrap // match call to unwrap
if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.kind; if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args, _) = expr.kind;
if unwrap_fun.ident.name == sym!(unwrap); if unwrap_fun.ident.name == sym!(unwrap);
// match call to write_fmt // match call to write_fmt
if !unwrap_args.is_empty(); if !unwrap_args.is_empty();
if let ExprKind::MethodCall(ref write_fun, _, write_args) = if let ExprKind::MethodCall(ref write_fun, _, write_args, _) =
unwrap_args[0].kind; unwrap_args[0].kind;
if write_fun.ident.name == sym!(write_fmt); if write_fun.ident.name == sym!(write_fmt);
// match calls to std::io::stdout() / std::io::stderr () // match calls to std::io::stdout() / std::io::stderr ()

View file

@ -301,7 +301,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if cx.tables.expr_ty(lhs).is_floating_point(); if cx.tables.expr_ty(lhs).is_floating_point();
if let Some((value, _)) = constant(cx, cx.tables, rhs); if let Some((value, _)) = constant(cx, cx.tables, rhs);
if F32(1.0) == value || F64(1.0) == value; if F32(1.0) == value || F64(1.0) == value;
if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind; if let ExprKind::MethodCall(ref path, _, ref method_args, _) = lhs.kind;
if cx.tables.expr_ty(&method_args[0]).is_floating_point(); if cx.tables.expr_ty(&method_args[0]).is_floating_point();
if path.ident.name.as_str() == "exp"; if path.ident.name.as_str() == "exp";
then { then {
@ -481,7 +481,7 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind {
let recv_ty = cx.tables.expr_ty(&args[0]); let recv_ty = cx.tables.expr_ty(&args[0]);
if recv_ty.is_floating_point() { if recv_ty.is_floating_point() {

View file

@ -104,7 +104,7 @@ fn on_argumentv1_new<'a, 'tcx>(
} }
} else { } else {
let snip = snippet(cx, format_args.span, "<arg>"); let snip = snippet(cx, format_args.span, "<arg>");
if let ExprKind::MethodCall(ref path, _, _) = format_args.kind { if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
if path.ident.name == sym!(to_string) { if path.ident.name == sym!(to_string) {
return Some(format!("{}", snip)); return Some(format!("{}", snip));
} }

View file

@ -556,7 +556,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
} }
} }
}, },
hir::ExprKind::MethodCall(_, _, args) => { hir::ExprKind::MethodCall(_, _, args, _) => {
let def_id = self.tables.type_dependent_def_id(expr.hir_id).unwrap(); let def_id = self.tables.type_dependent_def_id(expr.hir_id).unwrap();
let base_type = self.cx.tcx.type_of(def_id); let base_type = self.cx.tcx.type_of(def_id);
@ -610,7 +610,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
return; return;
} }
match expr.kind { match expr.kind {
Call(_, args) | MethodCall(_, _, args) => { Call(_, args) | MethodCall(_, _, args, _) => {
let mut tys = FxHashSet::default(); let mut tys = FxHashSet::default();
for arg in args { for arg in args {
let def_id = arg.hir_id.owner.to_def_id(); let def_id = arg.hir_id.owner.to_def_id();

View file

@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
// Is a method call // Is a method call
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind; if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
// Method name is "get" // Method name is "get"
if path.ident.name == sym!(get); if path.ident.name == sym!(get);
@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
) = &get_index_arg.kind; ) = &get_index_arg.kind;
// LHS of subtraction is "x.len()" // LHS of subtraction is "x.len()"
if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args) = &lhs.kind; if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args, _) = &lhs.kind;
if arg_lhs_path.ident.name == sym!(len); if arg_lhs_path.ident.name == sym!(len);
if let Some(arg_lhs_struct) = lhs_args.get(0); if let Some(arg_lhs_struct) = lhs_args.get(0);

View file

@ -147,7 +147,7 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
fn is_mutex_lock_call<'a>(cx: &LateContext<'a, '_>, expr: &'a Expr<'_>) -> Option<&'a Expr<'a>> { fn is_mutex_lock_call<'a>(cx: &LateContext<'a, '_>, expr: &'a Expr<'_>) -> Option<&'a Expr<'a>> {
if_chain! { if_chain! {
if let ExprKind::MethodCall(path, _span, args) = &expr.kind; if let ExprKind::MethodCall(path, _span, args, _) = &expr.kind;
if path.ident.to_string() == "lock"; if path.ident.to_string() == "lock";
let ty = cx.tables.expr_ty(&args[0]); let ty = cx.tables.expr_ty(&args[0]);
if is_type_diagnostic_item(cx, ty, sym!(mutex_type)); if is_type_diagnostic_item(cx, ty, sym!(mutex_type));

View file

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet {
if_chain! { //begin checking variables if_chain! { //begin checking variables
if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match
if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let
if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok() if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type)); if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type));

View file

@ -142,7 +142,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness { fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind { match expr.kind {
ExprKind::MethodCall(ref method, _, ref args) => { ExprKind::MethodCall(ref method, _, ref args, _) => {
for &(name, len, heuristic, cap) in &HEURISTICS { for &(name, len, heuristic, cap) in &HEURISTICS {
if method.ident.name.as_str() == name && args.len() == len { if method.ident.name.as_str() == name && args.len() == len {
return (match heuristic { return (match heuristic {
@ -218,7 +218,7 @@ const INFINITE_COLLECTORS: [&[&str]; 8] = [
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness { fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind { match expr.kind {
ExprKind::MethodCall(ref method, _, ref args) => { ExprKind::MethodCall(ref method, _, ref args, _) => {
for &(name, len) in &COMPLETING_METHODS { for &(name, len) in &COMPLETING_METHODS {
if method.ident.name.as_str() == name && args.len() == len { if method.ident.name.as_str() == name && args.len() == len {
return is_infinite(cx, &args[0]); return is_infinite(cx, &args[0]);

View file

@ -211,7 +211,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[Imp
} }
fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) { fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) { if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
// check if we are in an is_empty() method // check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) { if let Some(name) = get_item_name(cx, method) {
if name.as_str() == "is_empty" { if name.as_str() == "is_empty" {

View file

@ -526,7 +526,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
let pat = &arms[0].pat.kind; let pat = &arms[0].pat.kind;
if let ( if let (
&PatKind::TupleStruct(ref qpath, ref pat_args, _), &PatKind::TupleStruct(ref qpath, ref pat_args, _),
&ExprKind::MethodCall(ref method_path, _, ref method_args), &ExprKind::MethodCall(ref method_path, _, ref method_args, _),
) = (pat, &match_expr.kind) ) = (pat, &match_expr.kind)
{ {
let iter_expr = &method_args[0]; let iter_expr = &method_args[0];
@ -654,7 +654,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
| ExprKind::Struct(_, _, Some(ref e)) | ExprKind::Struct(_, _, Some(ref e))
| ExprKind::Repeat(ref e, _) | ExprKind::Repeat(ref e, _)
| ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id), | ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id),
ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => { ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es, _) | ExprKind::Tup(ref es) => {
never_loop_expr_all(&mut es.iter(), main_loop_id) never_loop_expr_all(&mut es.iter(), main_loop_id)
}, },
ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id), ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
@ -806,7 +806,7 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
if_chain! { if_chain! {
if let ExprKind::MethodCall(method, _, args) = expr.kind; if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
if method.ident.name == sym!(clone); if method.ident.name == sym!(clone);
if args.len() == 1; if args.len() == 1;
if let Some(arg) = args.get(0); if let Some(arg) = args.get(0);
@ -915,7 +915,7 @@ fn build_manual_memcpy_suggestion<'a, 'tcx>(
let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| {
if_chain! { if_chain! {
if let ExprKind::MethodCall(method, _, len_args) = end.kind; if let ExprKind::MethodCall(method, _, len_args, _) = end.kind;
if method.ident.name == sym!(len); if method.ident.name == sym!(len);
if len_args.len() == 1; if len_args.len() == 1;
if let Some(arg) = len_args.get(0); if let Some(arg) = len_args.get(0);
@ -1190,7 +1190,7 @@ fn check_for_loop_range<'a, 'tcx>(
fn is_len_call(expr: &Expr<'_>, var: Name) -> bool { fn is_len_call(expr: &Expr<'_>, var: Name) -> bool {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.kind; if let ExprKind::MethodCall(ref method, _, ref len_args, _) = expr.kind;
if len_args.len() == 1; if len_args.len() == 1;
if method.ident.name == sym!(len); if method.ident.name == sym!(len);
if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].kind; if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].kind;
@ -1244,7 +1244,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>,
fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) { fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
if let ExprKind::MethodCall(ref method, _, ref args) = arg.kind { if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind {
// just the receiver, no arguments // just the receiver, no arguments
if args.len() == 1 { if args.len() == 1 {
let method_name = &*method.ident.as_str(); let method_name = &*method.ident.as_str();
@ -1718,7 +1718,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
// a range index op // a range index op
if let ExprKind::MethodCall(ref meth, _, ref args) = expr.kind; if let ExprKind::MethodCall(ref meth, _, ref args, _) = expr.kind;
if (meth.ident.name == sym!(index) && match_trait_method(self.cx, expr, &paths::INDEX)) if (meth.ident.name == sym!(index) && match_trait_method(self.cx, expr, &paths::INDEX))
|| (meth.ident.name == sym!(index_mut) && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); || (meth.ident.name == sym!(index_mut) && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if !self.check(&args[1], &args[0], expr); if !self.check(&args[1], &args[0], expr);
@ -1776,7 +1776,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
self.visit_expr(expr); self.visit_expr(expr);
} }
}, },
ExprKind::MethodCall(_, _, args) => { ExprKind::MethodCall(_, _, args, _) => {
let def_id = self.cx.tables.type_dependent_def_id(expr.hir_id).unwrap(); let def_id = self.cx.tables.type_dependent_def_id(expr.hir_id).unwrap();
for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
self.prefer_mutable = false; self.prefer_mutable = false;
@ -2369,8 +2369,8 @@ const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) { fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind; if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].kind; if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind;
if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR); if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR);
if let Some(ref generic_args) = chain_method.args; if let Some(ref generic_args) = chain_method.args;
if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
@ -2437,7 +2437,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, '
fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span { fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span {
let mut current_expr = expr; let mut current_expr = expr;
while let ExprKind::MethodCall(ref path, ref span, ref args) = current_expr.kind { while let ExprKind::MethodCall(ref path, ref span, ref args, _) = current_expr.kind {
if path.ident.name == target_fn_name { if path.ident.name == target_fn_name {
return expr.span.with_lo(span.lo()); return expr.span.with_lo(span.lo());
} }

View file

@ -49,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
} }
if_chain! { if_chain! {
if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.kind; if let hir::ExprKind::MethodCall(ref method, _, ref args, _) = e.kind;
if args.len() == 2; if args.len() == 2;
if method.ident.as_str() == "map"; if method.ident.as_str() == "map";
let ty = cx.tables.expr_ty(&args[0]); let ty = cx.tables.expr_ty(&args[0]);
@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
} }
} }
}, },
hir::ExprKind::MethodCall(ref method, _, ref obj) => { hir::ExprKind::MethodCall(ref method, _, ref obj, _) => {
if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone" if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone"
&& match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) { && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {

View file

@ -125,7 +125,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>)
} }
match expr.kind { match expr.kind {
hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _) => { hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _, _) => {
// Calls can't be reduced any more // Calls can't be reduced any more
Some(expr.span) Some(expr.span)
}, },

View file

@ -1429,7 +1429,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
} }
match expr.kind { match expr.kind {
hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => { hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => {
lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args); lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
@ -1677,7 +1677,7 @@ fn lint_or_fun_call<'a, 'tcx>(
or_has_args: bool, or_has_args: bool,
span: Span, span: Span,
) { ) {
if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.kind { if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = &arg.kind {
if path.ident.as_str() == "len" { if path.ident.as_str() == "len" {
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
@ -1751,7 +1751,7 @@ fn lint_or_fun_call<'a, 'tcx>(
); );
} }
}, },
hir::ExprKind::MethodCall(_, span, ref or_args) => check_general_case( hir::ExprKind::MethodCall(_, span, ref or_args, _) => check_general_case(
cx, cx,
name, name,
method_span, method_span,
@ -1782,7 +1782,7 @@ fn lint_expect_fun_call(
loop { loop {
arg_root = match &arg_root.kind { arg_root = match &arg_root.kind {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr,
hir::ExprKind::MethodCall(method_name, _, call_args) => { hir::ExprKind::MethodCall(method_name, _, call_args, _) => {
if call_args.len() == 1 if call_args.len() == 1
&& (method_name.ident.name == sym!(as_str) || method_name.ident.name == sym!(as_ref)) && (method_name.ident.name == sym!(as_str) || method_name.ident.name == sym!(as_ref))
&& { && {
@ -2002,7 +2002,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir:
// &*x is a nop, &x.clone() is not // &*x is a nop, &x.clone() is not
hir::ExprKind::AddrOf(..) => return, hir::ExprKind::AddrOf(..) => return,
// (*x).func() is useless, x.clone().func() can work in case func borrows mutably // (*x).func() is useless, x.clone().func() can work in case func borrows mutably
hir::ExprKind::MethodCall(_, _, parent_args) if expr.hir_id == parent_args[0].hir_id => return, hir::ExprKind::MethodCall(_, _, parent_args, _) if expr.hir_id == parent_args[0].hir_id => return,
_ => {}, _ => {},
}, },
@ -2478,7 +2478,7 @@ fn derefs_to_slice<'a, 'tcx>(
} }
} }
if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.kind { if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
if path.ident.name == sym!(iter) && may_slice(cx, cx.tables.expr_ty(&args[0])) { if path.ident.name == sym!(iter) && may_slice(cx, cx.tables.expr_ty(&args[0])) {
Some(&args[0]) Some(&args[0])
} else { } else {
@ -3182,7 +3182,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, call_name: &str, a
// allow the `as_ref` or `as_mut` if it is followed by another method call // allow the `as_ref` or `as_mut` if it is followed by another method call
if_chain! { if_chain! {
if let Some(parent) = get_parent_expr(cx, expr); if let Some(parent) = get_parent_expr(cx, expr);
if let hir::ExprKind::MethodCall(_, ref span, _) = parent.kind; if let hir::ExprKind::MethodCall(_, ref span, _, _) = parent.kind;
if span != &expr.span; if span != &expr.span;
then { then {
return; return;
@ -3310,7 +3310,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
let closure_expr = remove_blocks(&closure_body.value); let closure_expr = remove_blocks(&closure_body.value);
match &closure_expr.kind { match &closure_expr.kind {
hir::ExprKind::MethodCall(_, _, args) => { hir::ExprKind::MethodCall(_, _, args, _) => {
if_chain! { if_chain! {
if args.len() == 1; if args.len() == 1;
if let hir::ExprKind::Path(qpath) = &args[0].kind; if let hir::ExprKind::Path(qpath) = &args[0].kind;

View file

@ -545,7 +545,7 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
} }
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.kind; if let ExprKind::MethodCall(ref method_name, _, ref expressions, _) = expr.kind;
if sym!(signum) == method_name.ident.name; if sym!(signum) == method_name.ident.name;
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
// the method call) // the method call)
@ -572,7 +572,7 @@ fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {
let (arg_ty, snip) = match expr.kind { let (arg_ty, snip) = match expr.kind {
ExprKind::MethodCall(.., ref args) if args.len() == 1 => { ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) { if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
(cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, "..")) (cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
} else { } else {

View file

@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
); );
} }
}, },
ExprKind::MethodCall(ref path, _, ref arguments) => { ExprKind::MethodCall(ref path, _, ref arguments, _) => {
let def_id = cx.tables.type_dependent_def_id(e.hir_id).unwrap(); let def_id = cx.tables.type_dependent_def_id(e.hir_id).unwrap();
let substs = cx.tables.node_substs(e.hir_id); let substs = cx.tables.node_substs(e.hir_id);
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);

View file

@ -29,7 +29,7 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, ref arguments) = e.kind { if let ExprKind::MethodCall(ref path, _, ref arguments, _) = e.kind {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
let mut options = Vec::new(); let mut options = Vec::new();
@ -57,7 +57,7 @@ enum OpenOption {
} }
fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) { fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
if let ExprKind::MethodCall(ref path, _, ref arguments) = argument.kind { if let ExprKind::MethodCall(ref path, _, ref arguments, _) = argument.kind {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0])); let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
// Only proceed if this is a call on some object of type std::fs::OpenOptions // Only proceed if this is a call on some object of type std::fs::OpenOptions

View file

@ -35,7 +35,7 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
impl EarlyLintPass for OptionEnvUnwrap { impl EarlyLintPass for OptionEnvUnwrap {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(path_segment, args) = &expr.kind; if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind;
let method_name = path_segment.ident.as_str(); let method_name = path_segment.ident.as_str();
if method_name == "expect" || method_name == "unwrap"; if method_name == "expect" || method_name == "unwrap";
if let ExprKind::Call(caller, _) = &args[0].kind; if let ExprKind::Call(caller, _) = &args[0].kind;

View file

@ -43,7 +43,7 @@ declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! { if_chain! {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind; if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
if path.ident.name == sym!(push); if path.ident.name == sym!(push);
if args.len() == 2; if args.len() == 2;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF); if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF);

View file

@ -103,7 +103,7 @@ impl EarlyLintPass for Precedence {
} }
if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind { if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind {
if let ExprKind::MethodCall(ref path_segment, ref args) = rhs.kind { if let ExprKind::MethodCall(ref path_segment, ref args, _) = rhs.kind {
let path_segment_str = path_segment.ident.name.as_str(); let path_segment_str = path_segment.ident.name.as_str();
if let Some(slf) = args.first() { if let Some(slf) = args.first() {
if let ExprKind::Lit(ref lit) = slf.kind { if let ExprKind::Lit(ref lit) = slf.kind {

View file

@ -90,7 +90,7 @@ fn expr_as_ptr_offset_call<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
expr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>,
) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> { ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
if let ExprKind::MethodCall(ref path_segment, _, ref args) = expr.kind { if let ExprKind::MethodCall(ref path_segment, _, ref args, _) = expr.kind {
if is_expr_ty_raw_ptr(cx, &args[0]) { if is_expr_ty_raw_ptr(cx, &args[0]) {
if path_segment.ident.name == sym!(offset) { if path_segment.ident.name == sym!(offset) {
return Some((&args[0], &args[1], Method::Offset)); return Some((&args[0], &args[1], Method::Offset));

View file

@ -50,7 +50,7 @@ impl QuestionMark {
fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! { if_chain! {
if let Some((if_expr, body, else_)) = higher::if_block(&expr); if let Some((if_expr, body, else_)) = higher::if_block(&expr);
if let ExprKind::MethodCall(segment, _, args) = &if_expr.kind; if let ExprKind::MethodCall(segment, _, args, _) = &if_expr.kind;
if segment.ident.name == sym!(is_none); if segment.ident.name == sym!(is_none);
if Self::expression_returns_none(cx, body); if Self::expression_returns_none(cx, body);
if let Some(subject) = args.get(0); if let Some(subject) = args.get(0);

View file

@ -129,20 +129,20 @@ declare_lint_pass!(Ranges => [
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind { if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
let name = path.ident.as_str(); let name = path.ident.as_str();
if name == "zip" && args.len() == 2 { if name == "zip" && args.len() == 2 {
let iter = &args[0].kind; let iter = &args[0].kind;
let zip_arg = &args[1]; let zip_arg = &args[1];
if_chain! { if_chain! {
// `.iter()` call // `.iter()` call
if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter; if let ExprKind::MethodCall(ref iter_path, _, ref iter_args , _) = *iter;
if iter_path.ident.name == sym!(iter); if iter_path.ident.name == sym!(iter);
// range expression in `.zip()` call: `0..x.len()` // range expression in `.zip()` call: `0..x.len()`
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg); if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
if is_integer_const(cx, start, 0); if is_integer_const(cx, start, 0);
// `.len()` call // `.len()` call
if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.kind; if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind;
if len_path.ident.name == sym!(len) && len_args.len() == 1; if len_path.ident.name == sym!(len) && len_args.len() == 1;
// `.iter()` and `.len()` called on same `Path` // `.iter()` and `.len()` called on same `Path`
if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind; if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;

Some files were not shown because too many files have changed in this diff Show more