mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
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:
commit
99fc56b9de
@ -8,6 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{is_range_literal, Node};
|
use rustc_hir::{is_range_literal, Node};
|
||||||
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||||
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
@ -412,14 +413,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
checked_ty: Ty<'tcx>,
|
checked_ty: Ty<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
) -> Option<(Span, &'static str, String, Applicability)> {
|
) -> Option<(Span, &'static str, String, Applicability)> {
|
||||||
let sm = self.sess().source_map();
|
let sess = self.sess();
|
||||||
let sp = expr.span;
|
let sp = expr.span;
|
||||||
if sm.is_imported(sp) {
|
|
||||||
// Ignore if span is from within a macro #41858, #58298. We previously used the macro
|
// If the span is from an external macro, there's no suggestion we can make.
|
||||||
// call span, but that breaks down when the type error comes from multiple calls down.
|
if in_external_macro(sess, sp) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sm = sess.source_map();
|
||||||
|
|
||||||
let replace_prefix = |s: &str, old: &str, new: &str| {
|
let replace_prefix = |s: &str, old: &str, new: &str| {
|
||||||
s.strip_prefix(old).map(|stripped| new.to_string() + stripped)
|
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 =
|
let is_struct_pat_shorthand_field =
|
||||||
self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, sp);
|
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.
|
// `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
|
||||||
let expr = expr.peel_drop_temps();
|
let expr = expr.peel_drop_temps();
|
||||||
|
|
||||||
@ -570,10 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
|
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
|
||||||
_,
|
_,
|
||||||
&ty::Ref(_, checked, _),
|
&ty::Ref(_, checked, _),
|
||||||
) if {
|
) if self.infcx.can_sub(self.param_env, checked, &expected).is_ok() => {
|
||||||
self.infcx.can_sub(self.param_env, checked, &expected).is_ok() && !is_macro
|
|
||||||
} =>
|
|
||||||
{
|
|
||||||
// We have `&T`, check if what was expected was `T`. If so,
|
// We have `&T`, check if what was expected was `T`. If so,
|
||||||
// we may want to suggest removing a `&`.
|
// we may want to suggest removing a `&`.
|
||||||
if sm.is_imported(expr.span) {
|
if sm.is_imported(expr.span) {
|
||||||
@ -589,13 +585,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if let Ok(code) = sm.span_to_snippet(expr.span) {
|
if sp.contains(expr.span) {
|
||||||
return Some((
|
if let Ok(code) = sm.span_to_snippet(expr.span) {
|
||||||
sp,
|
return Some((
|
||||||
"consider removing the borrow",
|
sp,
|
||||||
code,
|
"consider removing the borrow",
|
||||||
Applicability::MachineApplicable,
|
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) {
|
if let Some(steps) = self.deref_steps(checked_ty, expected) {
|
||||||
let expr = expr.peel_blocks();
|
let expr = expr.peel_blocks();
|
||||||
|
|
||||||
|
18
src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs
Normal file
18
src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs
Normal 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);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
29
src/test/ui/suggestions/suggest-ref-macro.rs
Normal file
29
src/test/ui/suggestions/suggest-ref-macro.rs
Normal 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
|
||||||
|
}
|
34
src/test/ui/suggestions/suggest-ref-macro.stderr
Normal file
34
src/test/ui/suggestions/suggest-ref-macro.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user