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
118 changed files with 534 additions and 232 deletions
+1 -1
View File
@@ -553,7 +553,7 @@ fn run(self, builder: &Builder<'_>) {
builder.add_rustc_lib_path(compiler, &mut cargo);
try_run(builder, &mut cargo.into());
builder.run(&mut cargo.into());
}
}
@@ -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.
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.
+3 -1
View File
@@ -1174,7 +1174,9 @@ pub enum ExprKind {
/// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `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)`).
Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`).
+2 -1
View File
@@ -1111,11 +1111,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f);
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_id(id);
visit_opt(args, |args| vis.visit_generic_args(args));
visit_exprs(exprs, vis);
vis.visit_span(span);
}
ExprKind::Binary(_binop, lhs, rhs) => {
vis.visit_expr(lhs);
+1 -1
View File
@@ -394,7 +394,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x)
}
ast::ExprKind::MethodCall(.., ref exprs) => {
ast::ExprKind::MethodCall(.., ref exprs, _) => {
// X { y: 1 }.bar(...)
contains_exterior_struct_lit(&exprs[0])
}
+1 -1
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);
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);
walk_list!(visitor, visit_expr, arguments);
}
+2 -2
View File
@@ -39,7 +39,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
let f = self.lower_expr(f);
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(
e.span,
seg,
@@ -50,7 +50,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
None,
));
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) => {
let binop = self.lower_binop(binop);
+1 -1
View File
@@ -1818,7 +1818,7 @@ fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
ast::ExprKind::Call(ref func, ref 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[..]);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
+29 -18
View File
@@ -391,7 +391,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
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 template = vec![];
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 {
parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
if idx >= args.operands.len()
|| named_pos.contains(&idx)
|| named_pos.contains_key(&idx)
|| args.reg_args.contains(&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);
if named_pos.contains(&idx) {
if named_pos.contains_key(&idx) {
err.span_label(args.operands[idx].1, "named argument");
err.span_note(
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 unused_operands: Vec<_> = used
.into_iter()
.enumerate()
.filter(|&(_, used)| !used)
.map(|(idx, _)| {
if named_pos.contains(&idx) {
// named argument
(operands[idx].1, "named argument never used")
let mut unused_operands = vec![];
let mut help_str = String::new();
for (idx, used) in used.into_iter().enumerate() {
if !used {
let msg = if let Some(sym) = named_pos.get(&idx) {
help_str.push_str(&format!(" {{{}}}", sym));
"named argument never used"
} else {
// positional argument
(operands[idx].1, "argument never used")
}
})
.collect();
help_str.push_str(&format!(" {{{}}}", idx));
"argument never used"
};
unused_operands.push((args.operands[idx].1, msg));
}
}
match unused_operands.len() {
0 => {}
1 => {
let (sp, msg) = unused_operands.into_iter().next().unwrap();
let mut err = ecx.struct_span_err(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();
}
_ => {
@@ -511,6 +516,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
for (sp, msg) in unused_operands {
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();
}
}
@@ -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()
};
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 {
id: ast::DUMMY_NODE_ID,
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
+18 -4
View File
@@ -16,7 +16,7 @@
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
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_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
@@ -242,6 +242,7 @@ fn drop(&mut self) {
fn report_inline_asm(
cgcx: &CodegenContext<LlvmCodegenBackend>,
msg: String,
level: llvm::DiagnosticLevel,
mut cookie: c_uint,
source: Option<(String, Vec<InnerSpan>)>,
) {
@@ -251,7 +252,12 @@ fn report_inline_asm(
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
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) {
@@ -264,6 +270,7 @@ fn report_inline_asm(
// diagnostics.
let mut have_source = false;
let mut buffer = String::new();
let mut level = llvm::DiagnosticLevel::Error;
let mut loc = 0;
let mut ranges = [0; 8];
let mut num_ranges = ranges.len() / 2;
@@ -273,6 +280,7 @@ fn report_inline_asm(
diag,
msg,
buffer,
&mut level,
&mut loc,
ranges.as_mut_ptr(),
&mut num_ranges,
@@ -290,7 +298,7 @@ fn report_inline_asm(
(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) {
@@ -301,7 +309,13 @@ fn report_inline_asm(
match llvm::diagnostic::Diagnostic::unpack(info) {
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) => {
+10 -2
View File
@@ -88,6 +88,7 @@ unsafe fn unpack(kind: OptimizationDiagnosticKind, di: &'ll DiagnosticInfo) -> S
#[derive(Copy, Clone)]
pub struct InlineAsmDiagnostic<'ll> {
pub level: super::DiagnosticLevel,
pub cookie: c_uint,
pub message: &'ll Twine,
pub instruction: Option<&'ll Value>,
@@ -98,10 +99,17 @@ unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
let mut cookie = 0;
let mut message = 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 }
}
}
+13
View File
@@ -489,6 +489,17 @@ pub enum DiagnosticKind {
Linker,
}
/// LLVMRustDiagnosticLevel
#[derive(Copy, Clone)]
#[repr(C)]
#[allow(dead_code)] // Variants constructed by C++.
pub enum DiagnosticLevel {
Error,
Warning,
Note,
Remark,
}
/// LLVMRustArchiveKind
#[derive(Copy, Clone)]
#[repr(C)]
@@ -2054,6 +2065,7 @@ pub fn LLVMRustUnpackOptimizationDiagnostic(
pub fn LLVMRustUnpackInlineAsmDiagnostic(
DI: &'a DiagnosticInfo,
level_out: &mut DiagnosticLevel,
cookie_out: &mut c_uint,
message_out: &mut Option<&'a Twine>,
instruction_out: &mut Option<&'a Value>,
@@ -2074,6 +2086,7 @@ pub fn LLVMRustUnpackSMDiagnostic(
d: &SMDiagnostic,
message_out: &RustString,
buffer_out: &RustString,
level_out: &mut DiagnosticLevel,
loc_out: &mut c_uint,
ranges_out: *mut c_uint,
num_ranges: &mut usize,
+13 -7
View File
@@ -1551,7 +1551,7 @@ fn drop(&mut self) {
enum SharedEmitterMessage {
Diagnostic(Diagnostic),
InlineAsmError(u32, String, Option<(String, Vec<InnerSpan>)>),
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
AbortIfErrors,
Fatal(String),
}
@@ -1576,9 +1576,10 @@ pub fn inline_asm_error(
&self,
cookie: u32,
msg: String,
level: Level,
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) {
@@ -1631,16 +1632,21 @@ pub fn check(&self, sess: &Session, blocking: bool) {
}
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 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.
let mut err = if cookie == 0 {
sess.struct_err(&msg)
} else {
if cookie != 0 {
let pos = BytePos::from_u32(cookie);
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.
+10 -2
View File
@@ -530,6 +530,7 @@ fn codegen_call_terminator(
args: &Vec<mir::Operand<'tcx>>,
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>,
fn_span: Span,
) {
let span = terminator.source_info.span;
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
@@ -634,7 +635,7 @@ fn codegen_call_terminator(
if intrinsic == Some("caller_location") {
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 {
location.val.store(&mut bx, tmp);
@@ -798,7 +799,12 @@ fn codegen_call_terminator(
args.len() + 1,
"#[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();
self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
}
@@ -1016,6 +1022,7 @@ fn codegen_terminator(
ref destination,
cleanup,
from_hir_call: _,
fn_span,
} => {
self.codegen_call_terminator(
helper,
@@ -1025,6 +1032,7 @@ fn codegen_terminator(
args,
destination,
cleanup,
fn_span,
);
}
mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {
+10 -1
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
#[export_name="\0foo"] // error: `export_name` may not contain null characters
pub fn bar() {}
```
To fix this error, remove the null characters:
```
#[export_name="foo"] // ok!
pub fn bar() {}
```
+5
View File
@@ -581,6 +581,11 @@ pub fn struct_help(&self, msg: &str) -> DiagnosticBuilder<'_> {
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 {
self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
FatalError
+1 -1
View File
@@ -272,7 +272,7 @@ pub fn expr_method_call(
) -> P<ast::Expr> {
args.insert(0, expr);
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> {
self.expr(b.span, ast::ExprKind::Block(b, None))
+4 -2
View File
@@ -1371,7 +1371,7 @@ pub struct Expr<'hir> {
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[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<'_> {
pub fn precedence(&self) -> ExprPrecedence {
@@ -1568,12 +1568,14 @@ pub enum ExprKind<'hir> {
/// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `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
/// the `hir_id` of the `MethodCall` node itself.
///
/// [`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)`).
Tup(&'hir [Expr<'hir>]),
/// A binary operation (e.g., `a + b`, `a * b`).
+1 -1
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);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::MethodCall(ref segment, _, arguments) => {
ExprKind::MethodCall(ref segment, _, arguments, _) => {
visitor.visit_path_segment(expression.span, segment);
walk_list!(visitor, visit_expr, arguments);
}
+2 -2
View File
@@ -1308,7 +1308,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
hir::ExprKind::Call(ref func, ref 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);
}
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)
}
hir::ExprKind::MethodCall(.., ref exprs) => {
hir::ExprKind::MethodCall(.., ref exprs, _) => {
// `X { y: 1 }.bar(...)`
contains_exterior_struct_lit(&exprs[0])
}
@@ -107,7 +107,7 @@ fn visit_body(&mut self, body: &'tcx Body<'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
&& Some(self.target)
== self.infcx.in_progress_tables.and_then(|tables| {
@@ -294,7 +294,7 @@ pub fn need_type_info_err(
// 3 | let _ = x.sum() as f64;
// | ^^^ cannot infer type for `S`
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)
{
// Point at the call instead of the whole expression:
+1 -1
View File
@@ -18,7 +18,7 @@
fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
tls::with_opt(|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 {
rustc_span::default_span_debug(span, f)
}
+1 -1
View File
@@ -24,7 +24,7 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) {
// 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 {
return;
}
+1 -1
View File
@@ -1899,7 +1899,7 @@ fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>) -> Option<I
}
}
}
} 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`.
let def_id = cx.tables.type_dependent_def_id(expr.hir_id)?;
if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
+1 -1
View File
@@ -526,7 +526,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
// 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
_ => {
return;
+5 -1
View File
@@ -1131,6 +1131,9 @@ pub enum TerminatorKind<'tcx> {
/// `true` if this is from a call in HIR rather than from an overloaded
/// operator. True for overloaded function call.
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,
@@ -2449,7 +2452,8 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
)
} 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);
+2 -1
View File
@@ -42,7 +42,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
resume_arg: resume_arg.fold_with(folder),
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 =
destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
@@ -52,6 +52,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
destination: dest,
cleanup,
from_hir_call,
fn_span,
}
}
Assert { ref cond, expected, ref msg, target, cleanup } => {
+1
View File
@@ -492,6 +492,7 @@ fn super_terminator_kind(&mut self,
destination,
cleanup: _,
from_hir_call: _,
fn_span: _
} => {
self.visit_operand(func, source_location);
for arg in args {
+5 -3
View File
@@ -605,7 +605,8 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
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() {
let upvar_tys = substs.as_generator().upvar_tys();
@@ -653,7 +654,8 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
if self.tcx().sess.opts.debugging_opts.span_free_formats {
p!(write("@"), print_def_path(did.to_def_id(), substs));
} 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() {
@@ -1362,7 +1364,7 @@ fn print_def_path(
if !self.empty_path {
write!(self, "::")?;
}
write!(self, "<impl at {:?}>", span)?;
write!(self, "<impl at {}>", self.tcx.sess.source_map().span_to_string(span))?;
self.empty_path = false;
return Ok(self);
@@ -142,6 +142,7 @@ fn visit_terminator_kind(&mut self, kind: &TerminatorKind<'tcx>, location: Locat
destination,
cleanup: _,
from_hir_call: _,
fn_span: _,
} => {
self.consume_operand(location, func);
for arg in args {
+1
View File
@@ -699,6 +699,7 @@ fn visit_terminator_before_primary_effect(
ref destination,
cleanup: _,
from_hir_call: _,
fn_span: _,
} => {
self.consume_operand(loc, (func, span), flow_state);
for arg in args {
+2 -2
View File
@@ -314,7 +314,7 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
infcx: &InferCtxt<'a, 'tcx>,
source: MirSource<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'_>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
) {
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 {
// Before the CFG, dump out the values for each region variable.
PassWhere::BeforeCFG => {
regioncx.dump_mir(out)?;
regioncx.dump_mir(infcx.tcx, out)?;
writeln!(out, "|")?;
if let Some(closure_region_requirements) = closure_region_requirements {
@@ -4,7 +4,9 @@
//! context internal state.
use super::{OutlivesConstraint, RegionInferenceContext};
use crate::borrow_check::type_check::Locations;
use rustc_infer::infer::NLLRegionVariableOrigin;
use rustc_middle::ty::TyCtxt;
use std::io::{self, Write};
// Room for "'_#NNNNr" before things get misaligned.
@@ -14,7 +16,7 @@
impl<'tcx> RegionInferenceContext<'tcx> {
/// 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")?;
for region in self.regions() {
@@ -48,7 +50,7 @@ pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> {
writeln!(out, "|")?;
writeln!(out, "| Inference Constraints")?;
self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?;
self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?;
Ok(())
}
@@ -59,6 +61,7 @@ pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> {
/// inference resulted in the values that it did when debugging.
fn for_each_constraint(
&self,
tcx: TyCtxt<'tcx>,
with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
) -> io::Result<()> {
for region in self.definitions.indices() {
@@ -72,7 +75,11 @@ fn for_each_constraint(
constraints.sort();
for constraint in &constraints {
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(())
@@ -467,7 +467,7 @@ fn join_state_into_successors_of<A>(
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 dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
propagate(unwind, exit_state);
@@ -41,6 +41,7 @@ fn mock_body() -> mir::Body<'static> {
destination: Some((dummy_place.clone(), mir::START_BLOCK)),
cleanup: None,
from_hir_call: false,
fn_span: DUMMY_SP,
},
);
block(3, mir::TerminatorKind::Return);
@@ -53,6 +54,7 @@ fn mock_body() -> mir::Body<'static> {
destination: Some((dummy_place.clone(), mir::START_BLOCK)),
cleanup: None,
from_hir_call: false,
fn_span: DUMMY_SP,
},
);
@@ -401,6 +401,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
ref destination,
cleanup: _,
from_hir_call: _,
fn_span: _,
} => {
self.gather_operand(func);
for arg in args {
@@ -1,6 +1,7 @@
use std::convert::TryFrom;
use rustc_hir::lang_items::PanicLocationLangItem;
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::subst::Subst;
use rustc_span::{Span, Symbol};
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
/// frame which is not `#[track_caller]`.
crate fn find_closest_untracked_caller_location(&self) -> Span {
self.stack()
let frame = self
.stack()
.iter()
.rev()
// 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.
.unwrap()
.current_source_info()
// Assert that the frame we look at is actually executing code currently
// (`current_source_info` is None when we are unwinding and the frame does
// not require cleanup).
.unwrap()
.span
.unwrap();
let loc = frame.loc.unwrap();
let block = &frame.body.basic_blocks()[loc.block];
assert_eq!(block.statements.len(), loc.statement_index);
debug!(
"find_closest_untracked_caller_location:: got terminator {:?} ({:?})",
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.
+1
View File
@@ -56,6 +56,7 @@ pub(super) fn eval_terminator(
destination,
ref cleanup,
from_hir_call: _from_hir_call,
fn_span: _,
} => {
let old_stack = self.frame_idx();
let old_loc = self.frame().loc;
+2
View File
@@ -460,6 +460,7 @@ fn make_clone_call(
destination: Some((dest, next)),
cleanup: Some(cleanup),
from_hir_call: true,
fn_span: self.span,
},
false,
);
@@ -788,6 +789,7 @@ fn build_call_shim<'tcx>(
None
},
from_hir_call: true,
fn_span: span,
},
false,
);
+2 -1
View File
@@ -909,7 +909,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
};
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);
for arg in &mut args {
self.visit_operand(arg, loc);
@@ -925,6 +925,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
cleanup: None,
destination: Some((Place::from(new_temp), new_target)),
from_hir_call,
fn_span,
},
..terminator
};
@@ -368,7 +368,14 @@ fn check_terminator(
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);
if let ty::FnDef(def_id, _) = fn_ty.kind {
if !crate::const_eval::is_min_const_fn(tcx, def_id) {
+2
View File
@@ -644,6 +644,7 @@ fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> Bas
destination: Some((unit_temp, succ)),
cleanup: unwind.into_option(),
from_hir_call: true,
fn_span: self.source_info.span,
},
source_info: self.source_info,
}),
@@ -988,6 +989,7 @@ fn unelaborated_free_block(
destination: Some((unit_temp, target)),
cleanup: None,
from_hir_call: false,
fn_span: self.source_info.span,
}; // FIXME(#43234)
let free_block = self.new_block(unwind, call);
+16 -6
View File
@@ -135,7 +135,7 @@ fn dump_matched_mir_node<'tcx, F>(
}
writeln!(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)?;
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
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);
for comment in extra_comments.comments {
writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
@@ -360,7 +360,7 @@ fn write_extra<'tcx, F>(tcx: TyCtxt<'tcx>, write: &mut dyn Write, mut visit_op:
}
struct ExtraComments<'tcx> {
_tcx: TyCtxt<'tcx>, // don't need it now, but bet we will soon
tcx: TyCtxt<'tcx>,
comments: Vec<String>,
}
@@ -377,7 +377,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
self.super_constant(constant, location);
let Constant { span, user_ty, literal } = 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 {
self.push(&format!("+ user_ty: {:?}", user_ty));
}
@@ -862,12 +862,22 @@ fn write_mir_sig(
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() {
writeln!(w, "| User Type Annotations")?;
}
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() {
writeln!(w, "|")?;
+4 -1
View File
@@ -162,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
});
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 {
ty::FnDef(def_id, _) => {
let f = ty.fn_sig(this.hir.tcx());
@@ -206,6 +206,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.record_operands_moved(&args);
debug!("into_expr: fn_span={:?}", fn_span);
this.cfg.terminate(
block,
source_info,
@@ -222,6 +224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Some((destination, success))
},
from_hir_call,
fn_span
},
);
success.unit()
@@ -443,6 +443,7 @@ fn non_scalar_compare(
destination: Some((eq_result, eq_block)),
cleanup: Some(cleanup),
from_hir_call: false,
fn_span: source_info.span
},
);
+12 -4
View File
@@ -139,11 +139,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
let kind = match expr.kind {
// 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)
let expr = method_callee(cx, expr, method_span, None);
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) => {
@@ -170,6 +170,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
fun: method.to_ref(),
args: vec![fun.to_ref(), tupled_args.to_ref()],
from_hir_call: true,
fn_span: expr.span,
}
} else {
let adt_data =
@@ -215,6 +216,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
fun: fun.to_ref(),
args: args.to_ref(),
from_hir_call: true,
fn_span: expr.span,
}
}
}
@@ -1024,7 +1026,7 @@ fn overloaded_operator<'a, 'tcx>(
args: Vec<ExprRef<'tcx>>,
) -> ExprKind<'tcx> {
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>(
@@ -1060,7 +1062,13 @@ fn overloaded_place<'a, 'tcx>(
temp_lifetime,
ty: ref_ty,
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()`
+3
View File
@@ -146,6 +146,9 @@
// Whether this is from a call in HIR, rather than from an overloaded
// operator. True for overloaded function call.
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 {
arg: ExprRef<'tcx>,
+4 -2
View File
@@ -639,7 +639,7 @@ fn parse_and_disallow_postfix_after_cast(
ExprKind::Index(_, _) => "indexing",
ExprKind::Try(_) => "?",
ExprKind::Field(_, _) => "a field access",
ExprKind::MethodCall(_, _) => "a method call",
ExprKind::MethodCall(_, _, _) => "a method call",
ExprKind::Call(_, _) => "a function call",
ExprKind::Await(_) => "`.await`",
ExprKind::Err => return Ok(with_postfix),
@@ -865,6 +865,7 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
return self.mk_await_expr(self_arg, lo);
}
let fn_span_lo = self.token.span;
let segment = self.parse_path_segment(PathStyle::Expr)?;
self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
@@ -873,8 +874,9 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
let mut args = self.parse_paren_expr_seq()?;
args.insert(0, self_arg);
let fn_span = fn_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 {
// Field access `expr.f`
if let Some(args) = segment.args {
+1 -1
View File
@@ -1198,7 +1198,7 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
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 succ = if self.ir.tcx.is_ty_uninhabited_from(
m,
+1 -1
View File
@@ -1302,7 +1302,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
return;
}
}
hir::ExprKind::MethodCall(_, span, _) => {
hir::ExprKind::MethodCall(_, span, _, _) => {
// Method calls have to be checked specially.
self.span = span;
if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) {
+1 -1
View File
@@ -2117,7 +2117,7 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
ExprKind::MethodCall(ref segment, ref arguments) => {
ExprKind::MethodCall(ref segment, ref arguments, _) => {
let mut arguments = arguments.iter();
self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments {
+3 -1
View File
@@ -1404,7 +1404,9 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
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)
}
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, _) => {
self.visit_expr(&sub_ex);
+3
View File
@@ -441,6 +441,9 @@ pub fn note_without_error(&self, msg: &str) {
pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
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 {
&self.parse_sess.span_diagnostic
+9 -1
View File
@@ -726,10 +726,18 @@ fn drop(&mut self) {
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 {
GLOBALS.with(|globals| {
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 {
f.debug_struct("Span")
.field("lo", &span.lo())
+2 -2
View File
@@ -307,7 +307,7 @@ fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, St
let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
(
Some(Node::Expr(hir::Expr {
kind: hir::ExprKind::MethodCall(path, span, expr),
kind: hir::ExprKind::MethodCall(path, span, expr, _),
..
})),
1,
@@ -457,7 +457,7 @@ pub fn check_ref(
};
if self.can_coerce(ref_ty, expected) {
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));
if let ([arg], Some(true), sym::clone) = (
&args[..],
+2 -2
View File
@@ -182,7 +182,7 @@ fn check_expr_with_expectation_and_needs(
ExprKind::Call(ref callee, _) => {
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, expr.span, "expression"),
@@ -262,7 +262,7 @@ fn check_expr_kind(
}
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::MethodCall(ref segment, span, ref args) => {
ExprKind::MethodCall(ref segment, span, ref args, _) => {
self.check_method_call(expr, segment, span, args, expected, needs)
}
ExprKind::Cast(ref e, ref t) => self.check_expr_cast(e, t, expr),
+1 -1
View File
@@ -3912,7 +3912,7 @@ fn check_argument_types(
sugg_unit: bool| {
let (span, start_span, args) = match &expr.kind {
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,
// `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
path_segment
+1 -1
View File
@@ -185,7 +185,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
self.consume_exprs(args);
}
hir::ExprKind::MethodCall(.., ref args) => {
hir::ExprKind::MethodCall(.., ref args, _) => {
// callee.m(args)
self.consume_exprs(args);
}
+5 -1
View File
@@ -676,7 +676,11 @@ pub fn new(
}
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) {
+46 -1
View File
@@ -1094,8 +1094,17 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
MessageOS << Opt->getMsg();
}
enum class LLVMRustDiagnosticLevel {
Error,
Warning,
Note,
Remark,
};
extern "C" void
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
LLVMRustDiagnosticLevel *LevelOut,
unsigned *CookieOut,
LLVMTwineRef *MessageOut,
LLVMValueRef *InstructionOut) {
// Undefined to call this not on an inline assembly diagnostic!
@@ -1105,6 +1114,23 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
*CookieOut = IA->getLocCookie();
*MessageOut = wrap(&IA->getMsgStr());
*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,
@@ -1166,6 +1192,7 @@ extern "C" LLVMRustDiagnosticKind
LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
return toRust((DiagnosticKind)unwrap(DI)->getKind());
}
// This is kept distinct from LLVMGetTypeKind, because when
// a new type kind is added, the Rust-side enum must be
// updated or UB will result.
@@ -1219,6 +1246,7 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
RustStringRef MessageOut,
RustStringRef BufferOut,
LLVMRustDiagnosticLevel* LevelOut,
unsigned* LocOut,
unsigned* RangesOut,
size_t* NumRanges) {
@@ -1226,6 +1254,23 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
RawRustStringOstream MessageOS(MessageOut);
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())
return false;
+15
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() {}
}
@@ -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
@@ -84,9 +84,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
2 => {
let seg = PathSegment::from_ident(Ident::from_str("x"));
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(
seg.clone(), vec![make_x(), e])));
seg.clone(), vec![make_x(), e], DUMMY_SP)));
},
3..=8 => {
let op = Spanned {
+2
View File
@@ -22,5 +22,7 @@ fn main() {
//~^ ERROR invalid reference to argument at index 0
asm!("{:foo}", in(reg) foo);
//~^ ERROR asm template modifier must be a single character
asm!("", in(reg) 0, in(reg) 1);
//~^ ERROR multiple unused asm arguments
}
}
+17 -1
View File
@@ -19,6 +19,8 @@ error: argument never used
|
LL | asm!("{1}", in(reg) foo);
| ^^^^^^^^^^^ 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`
--> $DIR/bad-template.rs:13:15
@@ -46,6 +48,8 @@ error: named argument never used
|
LL | asm!("{}", a = in(reg) foo);
| ^^^^^^^^^^^^^^^ 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
--> $DIR/bad-template.rs:18:15
@@ -60,6 +64,8 @@ error: named argument never used
|
LL | asm!("{1}", a = in(reg) foo);
| ^^^^^^^^^^^^^^^ 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
--> $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);
| ^^^
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
+2
View File
@@ -127,6 +127,8 @@ error: argument never used
|
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^^^^^^^^^^^ 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
--> $DIR/parse-error.rs:47:18
+3
View File
@@ -37,5 +37,8 @@ fn main() {
asm!(concat!("invalid", "_", "instruction"));
//~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
//~^ WARN: scale factor without index register is ignored
}
}
+13 -1
View File
@@ -70,5 +70,17 @@ note: instantiated into assembly here
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
@@ -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 [
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: "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 {
ch: ',',
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 {
ch: '=',
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 {
ch: '=',
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 {
ch: '>',
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 {
delimiter: Parenthesis,
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 {
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: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 {
kind: Integer,
symbol: "0",
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 {
kind: Float,
symbol: "1.0",
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 {
kind: Str,
symbol: "S",
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 {
kind: ByteStr,
symbol: "B",
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 {
kind: StrRaw(0),
symbol: "R",
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 {
kind: StrRaw(2),
symbol: "R",
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 {
kind: ByteStrRaw(0),
symbol: "BR",
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 {
kind: ByteStrRaw(2),
symbol: "BR",
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 {
kind: Char,
symbol: "C",
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 {
kind: Byte,
symbol: "B",
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 {
kind: Integer,
symbol: "0",
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 {
kind: Float,
symbol: "1.0",
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 {
kind: Str,
symbol: "S",
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 {
kind: ByteStr,
symbol: "B",
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 {
kind: StrRaw(0),
symbol: "R",
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 {
kind: StrRaw(2),
symbol: "R",
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 {
kind: ByteStrRaw(0),
symbol: "BR",
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 {
kind: ByteStrRaw(2),
symbol: "BR",
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 {
kind: Char,
symbol: "C",
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 {
kind: Byte,
symbol: "B",
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),
},
]
@@ -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);
}
@@ -70,7 +70,7 @@ fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&s
fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
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();
if type_is_atomic(cx, &args[0]);
if method == "load" || method == "store";
@@ -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]);
if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type))
&& !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type))
@@ -38,10 +38,10 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
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_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_args.len() == 2;
if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind;
@@ -66,7 +66,7 @@ fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).kind {
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 {
let p = path.ident.name;
if (p == sym!(iter) || p == sym!(iter_mut)) && args.len() == 1 {
@@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
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;
then {
@@ -70,7 +70,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
}
}
},
ExprKind::MethodCall(_, ref params) => {
ExprKind::MethodCall(_, ref params, _) => {
if params.len() == 2 {
let param = &params[1];
if let ExprKind::Paren(_) = param.kind {
@@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
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 let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right);
then {
+2 -2
View File
@@ -103,7 +103,7 @@ fn check_cond<'a, 'tcx, 'b>(
check: &'b Expr<'b>,
) -> Option<(&'static str, &'b Expr<'b>, &'b Expr<'b>)> {
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 path.ident.name == sym!(contains_key);
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<'_>) {
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 path.ident.name == sym!(insert);
if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);
@@ -71,7 +71,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
}
match expr.kind {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => {
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
for arg in args {
check_closure(cx, arg)
}
@@ -120,7 +120,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
);
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;
if args.len() == decl.inputs.len();
@@ -32,11 +32,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
// 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);
// match call to write_fmt
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;
if write_fun.ident.name == sym!(write_fmt);
// match calls to std::io::stdout() / std::io::stderr ()
@@ -301,7 +301,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if cx.tables.expr_ty(lhs).is_floating_point();
if let Some((value, _)) = constant(cx, cx.tables, rhs);
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 path.ident.name.as_str() == "exp";
then {
@@ -481,7 +481,7 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
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]);
if recv_ty.is_floating_point() {
+1 -1
View File
@@ -104,7 +104,7 @@ fn on_argumentv1_new<'a, 'tcx>(
}
} else {
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) {
return Some(format!("{}", snip));
}
@@ -556,7 +556,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
}
}
},
hir::ExprKind::MethodCall(_, _, args) => {
hir::ExprKind::MethodCall(_, _, args, _) => {
let def_id = self.tables.type_dependent_def_id(expr.hir_id).unwrap();
let base_type = self.cx.tcx.type_of(def_id);
@@ -610,7 +610,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
return;
}
match expr.kind {
Call(_, args) | MethodCall(_, _, args) => {
Call(_, args) | MethodCall(_, _, args, _) => {
let mut tys = FxHashSet::default();
for arg in args {
let def_id = arg.hir_id.owner.to_def_id();
@@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
// 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"
if path.ident.name == sym!(get);
@@ -69,7 +69,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
) = &get_index_arg.kind;
// 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 let Some(arg_lhs_struct) = lhs_args.get(0);
@@ -147,7 +147,7 @@ fn same_mutex(&self, cx: &LateContext<'_, '_>, op_mutex: &Expr<'_>) -> bool {
fn is_mutex_lock_call<'a>(cx: &LateContext<'a, '_>, expr: &'a Expr<'_>) -> Option<&'a Expr<'a>> {
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";
let ty = cx.tables.expr_ty(&args[0]);
if is_type_diagnostic_item(cx, ty, sym!(mutex_type));
@@ -42,7 +42,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! { //begin checking variables
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 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 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));
@@ -142,7 +142,7 @@ enum Heuristic {
fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind {
ExprKind::MethodCall(ref method, _, ref args) => {
ExprKind::MethodCall(ref method, _, ref args, _) => {
for &(name, len, heuristic, cap) in &HEURISTICS {
if method.ident.name.as_str() == name && args.len() == len {
return (match heuristic {
@@ -218,7 +218,7 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
match expr.kind {
ExprKind::MethodCall(ref method, _, ref args) => {
ExprKind::MethodCall(ref method, _, ref args, _) => {
for &(name, len) in &COMPLETING_METHODS {
if method.ident.name.as_str() == name && args.len() == len {
return is_infinite(cx, &args[0]);
@@ -211,7 +211,7 @@ fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef<'_>, name: &str) -
}
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
if let Some(name) = get_item_name(cx, method) {
if name.as_str() == "is_empty" {
+11 -11
View File
@@ -526,7 +526,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
let pat = &arms[0].pat.kind;
if let (
&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)
{
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::Repeat(ref e, _)
| 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)
},
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> {
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 args.len() == 1;
if let Some(arg) = args.get(0);
@@ -915,7 +915,7 @@ fn print_offset(start_str: &str, inline_offset: &Offset) -> String {
let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| {
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 len_args.len() == 1;
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 {
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 method.ident.name == sym!(len);
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<'_>) {
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
if args.len() == 1 {
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<'_>) {
if_chain! {
// 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))
|| (meth.ident.name == sym!(index_mut) && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if !self.check(&args[1], &args[0], expr);
@@ -1776,7 +1776,7 @@ fn visit_expr(&mut self, expr: &'tcx 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();
for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
self.prefer_mutable = false;
@@ -2369,8 +2369,8 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) {
if_chain! {
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 method, _, ref args, _) = expr.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 let Some(ref generic_args) = chain_method.args;
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 {
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 {
return expr.span.with_lo(span.lo());
}
@@ -49,7 +49,7 @@ fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) {
}
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 method.ident.as_str() == "map";
let ty = cx.tables.expr_ty(&args[0]);
@@ -75,7 +75,7 @@ fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) {
}
}
},
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"
&& match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
@@ -125,7 +125,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>)
}
match expr.kind {
hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _) => {
hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _, _) => {
// Calls can't be reduced any more
Some(expr.span)
},
@@ -1429,7 +1429,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>)
}
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_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
@@ -1677,7 +1677,7 @@ fn check_general_case<'a, 'tcx>(
or_has_args: bool,
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" {
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
@@ -1751,7 +1751,7 @@ fn check_general_case<'a, 'tcx>(
);
}
},
hir::ExprKind::MethodCall(_, span, ref or_args) => check_general_case(
hir::ExprKind::MethodCall(_, span, ref or_args, _) => check_general_case(
cx,
name,
method_span,
@@ -1782,7 +1782,7 @@ fn get_arg_root<'a>(cx: &LateContext<'_, '_>, arg: &'a hir::Expr<'a>) -> &'a hir
loop {
arg_root = match &arg_root.kind {
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
&& (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
hir::ExprKind::AddrOf(..) => return,
// (*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 may_slice<'a>(cx: &LateContext<'_, 'a>, ty: Ty<'a>) -> bool {
}
}
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])) {
Some(&args[0])
} 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
if_chain! {
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;
then {
return;
@@ -3310,7 +3310,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
let closure_expr = remove_blocks(&closure_body.value);
match &closure_expr.kind {
hir::ExprKind::MethodCall(_, _, args) => {
hir::ExprKind::MethodCall(_, _, args, _) => {
if_chain! {
if args.len() == 1;
if let hir::ExprKind::Path(qpath) = &args[0].kind;
+2 -2
View File
@@ -545,7 +545,7 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
}
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;
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
// 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<'_>) {
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) {
(cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
} else {
@@ -42,7 +42,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
);
}
},
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 substs = cx.tables.node_substs(e.hir_id);
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
@@ -29,7 +29,7 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions {
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]));
if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
let mut options = Vec::new();
@@ -57,7 +57,7 @@ enum OpenOption {
}
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]));
// Only proceed if this is a call on some object of type std::fs::OpenOptions
@@ -35,7 +35,7 @@
impl EarlyLintPass for OptionEnvUnwrap {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
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();
if method_name == "expect" || method_name == "unwrap";
if let ExprKind::Call(caller, _) = &args[0].kind;
@@ -43,7 +43,7 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
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 args.len() == 2;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF);
@@ -103,7 +103,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
}
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();
if let Some(slf) = args.first() {
if let ExprKind::Lit(ref lit) = slf.kind {
@@ -90,7 +90,7 @@ fn expr_as_ptr_offset_call<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
expr: &'tcx Expr<'_>,
) -> 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 path_segment.ident.name == sym!(offset) {
return Some((&args[0], &args[1], Method::Offset));
@@ -50,7 +50,7 @@ impl QuestionMark {
fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
if_chain! {
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 Self::expression_returns_none(cx, body);
if let Some(subject) = args.get(0);
+3 -3
View File
@@ -129,20 +129,20 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
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();
if name == "zip" && args.len() == 2 {
let iter = &args[0].kind;
let zip_arg = &args[1];
if_chain! {
// `.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);
// 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 is_integer_const(cx, start, 0);
// `.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;
// `.iter()` and `.len()` called on same `Path`
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