Rollup merge of #88501 - m-ou-se:prelude-collusion-oh-no-macros-help, r=estebank
Use right span in prelude collision suggestions with macros. Fixes https://github.com/rust-lang/rust/issues/88347 r? `@estebank`
This commit is contained in:
commit
91c4fee9fc
@ -597,6 +597,14 @@ impl Span {
|
||||
if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
|
||||
}
|
||||
|
||||
/// Walk down the expansion ancestors to find a span that's contained within `outer`.
|
||||
pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
|
||||
while !outer.contains(self) {
|
||||
self = self.parent()?;
|
||||
}
|
||||
Some(self)
|
||||
}
|
||||
|
||||
/// Edition of the crate from which this span came.
|
||||
pub fn edition(self) -> edition::Edition {
|
||||
self.ctxt().edition()
|
||||
|
@ -156,15 +156,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
segment.ident.name
|
||||
));
|
||||
|
||||
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr);
|
||||
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
|
||||
if precise {
|
||||
let args = args
|
||||
.iter()
|
||||
.skip(1)
|
||||
.map(|arg| {
|
||||
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
|
||||
format!(
|
||||
", {}",
|
||||
self.sess().source_map().span_to_snippet(arg.span).unwrap()
|
||||
self.sess().source_map().span_to_snippet(span).unwrap()
|
||||
)
|
||||
})
|
||||
.collect::<String>();
|
||||
@ -272,11 +273,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
method_name.name
|
||||
));
|
||||
|
||||
let mut self_ty_name = self
|
||||
.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(self_ty_span)
|
||||
.unwrap_or_else(|_| self_ty.to_string());
|
||||
let mut self_ty_name = self_ty_span
|
||||
.find_ancestor_inside(span)
|
||||
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
|
||||
.unwrap_or_else(|| self_ty.to_string());
|
||||
|
||||
// Get the number of generics the self type has (if an Adt) unless we can determine that
|
||||
// the user has written the self type with generics already which we (naively) do by looking
|
||||
@ -370,7 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Creates a string version of the `expr` that includes explicit adjustments.
|
||||
/// Returns the string and also a bool indicating whther this is a *precise*
|
||||
/// suggestion.
|
||||
fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, bool) {
|
||||
fn adjust_expr(
|
||||
&self,
|
||||
pick: &Pick<'tcx>,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
outer: Span,
|
||||
) -> (String, bool) {
|
||||
let derefs = "*".repeat(pick.autoderefs);
|
||||
|
||||
let autoref = match pick.autoref_or_ptr_adjustment {
|
||||
@ -379,12 +384,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
|
||||
};
|
||||
|
||||
let (expr_text, precise) =
|
||||
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
|
||||
(expr_text, true)
|
||||
} else {
|
||||
("(..)".to_string(), false)
|
||||
};
|
||||
let (expr_text, precise) = if let Some(expr_text) = expr
|
||||
.span
|
||||
.find_ancestor_inside(outer)
|
||||
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
|
||||
{
|
||||
(expr_text, true)
|
||||
} else {
|
||||
("(..)".to_string(), false)
|
||||
};
|
||||
|
||||
let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
|
||||
pick.autoref_or_ptr_adjustment
|
||||
|
@ -680,15 +680,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
migrated_variables_concat
|
||||
);
|
||||
|
||||
let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
|
||||
|
||||
// If the body was entirely expanded from a macro
|
||||
// invocation, i.e. the body is not contained inside the
|
||||
// closure span, then we walk up the expansion until we
|
||||
// find the span before the expansion.
|
||||
while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
|
||||
closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
|
||||
}
|
||||
let closure_body_span = self.tcx.hir().span(body_id.hir_id)
|
||||
.find_ancestor_inside(closure_span)
|
||||
.unwrap_or(DUMMY_SP);
|
||||
|
||||
if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
|
||||
let mut lines = s.lines();
|
||||
|
45
src/test/ui/rust-2021/future-prelude-collision-macros.fixed
Normal file
45
src/test/ui/rust-2021/future-prelude-collision-macros.fixed
Normal file
@ -0,0 +1,45 @@
|
||||
// run-rustfix
|
||||
// edition:2018
|
||||
// check-pass
|
||||
#![warn(rust_2021_prelude_collisions)]
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
macro_rules! foo {
|
||||
() => {{
|
||||
123;
|
||||
S
|
||||
}};
|
||||
}
|
||||
|
||||
trait MyTry<T> {
|
||||
fn try_into(self, _: u8);
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl MyTry<i32> for S {
|
||||
fn try_into(self, _: u8) {}
|
||||
}
|
||||
|
||||
trait TryFromU8: Sized {
|
||||
fn try_from(_: u8);
|
||||
}
|
||||
|
||||
impl TryFromU8 for u32 {
|
||||
fn try_from(_: u8) {}
|
||||
}
|
||||
|
||||
macro_rules! bar {
|
||||
() => {
|
||||
u32
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
MyTry::try_into(foo!(), todo!());
|
||||
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
|
||||
//~| WARNING this is accepted in the current edition
|
||||
<bar!() as TryFromU8>::try_from(0);
|
||||
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
|
||||
//~| WARNING this is accepted in the current edition
|
||||
}
|
45
src/test/ui/rust-2021/future-prelude-collision-macros.rs
Normal file
45
src/test/ui/rust-2021/future-prelude-collision-macros.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// run-rustfix
|
||||
// edition:2018
|
||||
// check-pass
|
||||
#![warn(rust_2021_prelude_collisions)]
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
macro_rules! foo {
|
||||
() => {{
|
||||
123;
|
||||
S
|
||||
}};
|
||||
}
|
||||
|
||||
trait MyTry<T> {
|
||||
fn try_into(self, _: u8);
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl MyTry<i32> for S {
|
||||
fn try_into(self, _: u8) {}
|
||||
}
|
||||
|
||||
trait TryFromU8: Sized {
|
||||
fn try_from(_: u8);
|
||||
}
|
||||
|
||||
impl TryFromU8 for u32 {
|
||||
fn try_from(_: u8) {}
|
||||
}
|
||||
|
||||
macro_rules! bar {
|
||||
() => {
|
||||
u32
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo!().try_into(todo!());
|
||||
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
|
||||
//~| WARNING this is accepted in the current edition
|
||||
<bar!()>::try_from(0);
|
||||
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
|
||||
//~| WARNING this is accepted in the current edition
|
||||
}
|
25
src/test/ui/rust-2021/future-prelude-collision-macros.stderr
Normal file
25
src/test/ui/rust-2021/future-prelude-collision-macros.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
warning: trait method `try_into` will become ambiguous in Rust 2021
|
||||
--> $DIR/future-prelude-collision-macros.rs:39:5
|
||||
|
|
||||
LL | foo!().try_into(todo!());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyTry::try_into(foo!(), todo!())`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/future-prelude-collision-macros.rs:4:9
|
||||
|
|
||||
LL | #![warn(rust_2021_prelude_collisions)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
|
||||
|
||||
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
|
||||
--> $DIR/future-prelude-collision-macros.rs:42:5
|
||||
|
|
||||
LL | <bar!()>::try_from(0);
|
||||
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<bar!() as TryFromU8>::try_from`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
Loading…
x
Reference in New Issue
Block a user