Skip to content

Commit

Permalink
Rollup merge of rust-lang#85937 - m-ou-se:macro-ref-suggestions, r=es…
Browse files Browse the repository at this point in the history
…tebank

Fix bad suggestions for code from proc_macro

Fixes rust-lang#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
```
  • Loading branch information
JohnTitor authored Jun 3, 2021
2 parents b8cc847 + e735f60 commit 2bd3237
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 20 deletions.
38 changes: 18 additions & 20 deletions compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -412,25 +413,23 @@ 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)
};

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();

Expand Down Expand Up @@ -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) {
Expand All @@ -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,
));
}
}
}
(
Expand Down Expand Up @@ -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();

Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs
Original file line number Diff line number Diff line change
@@ -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);
}
)
}
29 changes: 29 additions & 0 deletions src/test/ui/suggestions/suggest-ref-macro.rs
Original file line number Diff line number Diff line change
@@ -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
}
34 changes: 34 additions & 0 deletions src/test/ui/suggestions/suggest-ref-macro.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 2bd3237

Please sign in to comment.