Rollup merge of #85937 - m-ou-se:macro-ref-suggestions, r=estebank

Fix bad suggestions for code from proc_macro

Fixes #85932

This disables these suggestions for spans from external macros, while keeping them for macros defined locally:

Before:
```
3 | #[hello]
  | ^^^^^^^^
  | |
  | expected `&mut i32`, found integer
  | help: consider mutably borrowing here: `&mut #[hello]`
```

After:
```
3 | #[hello]
  | ^^^^^^^^ expected `&mut i32`, found integer
```

Unchanged:
```
26 | macro_rules! bla { () => { x(123); } }
   |                              ^^^
   |                              |
   |                              expected `&mut i32`, found integer
   |                              help: consider mutably borrowing here: `&mut 123`
...
29 |     bla!();
   |     ------- in this macro invocation
```
This commit is contained in:
Yuki Okushi 2021-06-04 13:42:58 +09:00 committed by GitHub
commit 99fc56b9de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 20 deletions

View File

@ -8,6 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{is_range_literal, Node};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
use rustc_span::symbol::sym;
@ -412,14 +413,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>,
) -> Option<(Span, &'static str, String, Applicability)> {
let sm = self.sess().source_map();
let sess = self.sess();
let sp = expr.span;
if sm.is_imported(sp) {
// Ignore if span is from within a macro #41858, #58298. We previously used the macro
// call span, but that breaks down when the type error comes from multiple calls down.
// If the span is from an external macro, there's no suggestion we can make.
if in_external_macro(sess, sp) {
return None;
}
let sm = sess.source_map();
let replace_prefix = |s: &str, old: &str, new: &str| {
s.strip_prefix(old).map(|stripped| new.to_string() + stripped)
};
@ -427,10 +430,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let is_struct_pat_shorthand_field =
self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, sp);
// If the span is from a macro, then it's hard to extract the text
// and make a good suggestion, so don't bother.
let is_macro = sp.from_expansion() && sp.desugaring_kind().is_none();
// `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
let expr = expr.peel_drop_temps();
@ -570,10 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
_,
&ty::Ref(_, checked, _),
) if {
self.infcx.can_sub(self.param_env, checked, &expected).is_ok() && !is_macro
} =>
{
) if self.infcx.can_sub(self.param_env, checked, &expected).is_ok() => {
// We have `&T`, check if what was expected was `T`. If so,
// we may want to suggest removing a `&`.
if sm.is_imported(expr.span) {
@ -589,13 +585,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
return None;
}
if let Ok(code) = sm.span_to_snippet(expr.span) {
return Some((
sp,
"consider removing the borrow",
code,
Applicability::MachineApplicable,
));
if sp.contains(expr.span) {
if let Ok(code) = sm.span_to_snippet(expr.span) {
return Some((
sp,
"consider removing the borrow",
code,
Applicability::MachineApplicable,
));
}
}
}
(
@ -643,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
_ if sp == expr.span && !is_macro => {
_ if sp == expr.span => {
if let Some(steps) = self.deref_steps(checked_ty, expected) {
let expr = expr.peel_blocks();

View File

@ -0,0 +1,18 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro_quote)]
extern crate proc_macro;
use proc_macro::{quote, TokenStream};
#[proc_macro_attribute]
pub fn hello(_: TokenStream, _: TokenStream) -> TokenStream {
quote!(
fn f(_: &mut i32) {}
fn g() {
f(123);
}
)
}

View File

@ -0,0 +1,29 @@
// run-check
// aux-build:proc-macro-type-error.rs
extern crate proc_macro_type_error;
use proc_macro_type_error::hello;
#[hello] //~ERROR mismatched types
fn abc() {}
fn x(_: &mut i32) {}
macro_rules! bla {
() => {
x(123);
//~^ ERROR mismatched types
//~| SUGGESTION &mut 123
};
($v:expr) => {
x($v)
}
}
fn main() {
bla!();
bla!(456);
//~^ ERROR mismatched types
//~| SUGGESTION &mut 456
}

View File

@ -0,0 +1,34 @@
error[E0308]: mismatched types
--> $DIR/suggest-ref-macro.rs:8:1
|
LL | #[hello]
| ^^^^^^^^ expected `&mut i32`, found integer
|
= note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/suggest-ref-macro.rs:15:11
|
LL | x(123);
| ^^^
| |
| expected `&mut i32`, found integer
| help: consider mutably borrowing here: `&mut 123`
...
LL | bla!();
| ------- in this macro invocation
|
= note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/suggest-ref-macro.rs:26:10
|
LL | bla!(456);
| ^^^
| |
| expected `&mut i32`, found integer
| help: consider mutably borrowing here: `&mut 456`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.