Skip to content

Commit 91c4fee

Browse files
authoredAug 31, 2021
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 #88347 r? `@estebank`
2 parents c5a34d8 + 7c0479b commit 91c4fee

File tree

6 files changed

+148
-19
lines changed

6 files changed

+148
-19
lines changed
 

‎compiler/rustc_span/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,14 @@ impl Span {
597597
if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
598598
}
599599

600+
/// Walk down the expansion ancestors to find a span that's contained within `outer`.
601+
pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
602+
while !outer.contains(self) {
603+
self = self.parent()?;
604+
}
605+
Some(self)
606+
}
607+
600608
/// Edition of the crate from which this span came.
601609
pub fn edition(self) -> edition::Edition {
602610
self.ctxt().edition()

‎compiler/rustc_typeck/src/check/method/prelude2021.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
156156
segment.ident.name
157157
));
158158

159-
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr);
159+
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
160160
if precise {
161161
let args = args
162162
.iter()
163163
.skip(1)
164164
.map(|arg| {
165+
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
165166
format!(
166167
", {}",
167-
self.sess().source_map().span_to_snippet(arg.span).unwrap()
168+
self.sess().source_map().span_to_snippet(span).unwrap()
168169
)
169170
})
170171
.collect::<String>();
@@ -272,11 +273,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
272273
method_name.name
273274
));
274275

275-
let mut self_ty_name = self
276-
.sess()
277-
.source_map()
278-
.span_to_snippet(self_ty_span)
279-
.unwrap_or_else(|_| self_ty.to_string());
276+
let mut self_ty_name = self_ty_span
277+
.find_ancestor_inside(span)
278+
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
279+
.unwrap_or_else(|| self_ty.to_string());
280280

281281
// Get the number of generics the self type has (if an Adt) unless we can determine that
282282
// 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> {
370370
/// Creates a string version of the `expr` that includes explicit adjustments.
371371
/// Returns the string and also a bool indicating whther this is a *precise*
372372
/// suggestion.
373-
fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, bool) {
373+
fn adjust_expr(
374+
&self,
375+
pick: &Pick<'tcx>,
376+
expr: &hir::Expr<'tcx>,
377+
outer: Span,
378+
) -> (String, bool) {
374379
let derefs = "*".repeat(pick.autoderefs);
375380

376381
let autoref = match pick.autoref_or_ptr_adjustment {
@@ -379,12 +384,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
379384
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
380385
};
381386

382-
let (expr_text, precise) =
383-
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
384-
(expr_text, true)
385-
} else {
386-
("(..)".to_string(), false)
387-
};
387+
let (expr_text, precise) = if let Some(expr_text) = expr
388+
.span
389+
.find_ancestor_inside(outer)
390+
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
391+
{
392+
(expr_text, true)
393+
} else {
394+
("(..)".to_string(), false)
395+
};
388396

389397
let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
390398
pick.autoref_or_ptr_adjustment

‎compiler/rustc_typeck/src/check/upvar.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -680,15 +680,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
680680
migrated_variables_concat
681681
);
682682

683-
let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
684-
685683
// If the body was entirely expanded from a macro
686684
// invocation, i.e. the body is not contained inside the
687685
// closure span, then we walk up the expansion until we
688686
// find the span before the expansion.
689-
while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
690-
closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
691-
}
687+
let closure_body_span = self.tcx.hir().span(body_id.hir_id)
688+
.find_ancestor_inside(closure_span)
689+
.unwrap_or(DUMMY_SP);
692690

693691
if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
694692
let mut lines = s.lines();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// run-rustfix
2+
// edition:2018
3+
// check-pass
4+
#![warn(rust_2021_prelude_collisions)]
5+
#![allow(unreachable_code)]
6+
7+
macro_rules! foo {
8+
() => {{
9+
123;
10+
S
11+
}};
12+
}
13+
14+
trait MyTry<T> {
15+
fn try_into(self, _: u8);
16+
}
17+
18+
struct S;
19+
20+
impl MyTry<i32> for S {
21+
fn try_into(self, _: u8) {}
22+
}
23+
24+
trait TryFromU8: Sized {
25+
fn try_from(_: u8);
26+
}
27+
28+
impl TryFromU8 for u32 {
29+
fn try_from(_: u8) {}
30+
}
31+
32+
macro_rules! bar {
33+
() => {
34+
u32
35+
};
36+
}
37+
38+
fn main() {
39+
MyTry::try_into(foo!(), todo!());
40+
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
41+
//~| WARNING this is accepted in the current edition
42+
<bar!() as TryFromU8>::try_from(0);
43+
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
44+
//~| WARNING this is accepted in the current edition
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// run-rustfix
2+
// edition:2018
3+
// check-pass
4+
#![warn(rust_2021_prelude_collisions)]
5+
#![allow(unreachable_code)]
6+
7+
macro_rules! foo {
8+
() => {{
9+
123;
10+
S
11+
}};
12+
}
13+
14+
trait MyTry<T> {
15+
fn try_into(self, _: u8);
16+
}
17+
18+
struct S;
19+
20+
impl MyTry<i32> for S {
21+
fn try_into(self, _: u8) {}
22+
}
23+
24+
trait TryFromU8: Sized {
25+
fn try_from(_: u8);
26+
}
27+
28+
impl TryFromU8 for u32 {
29+
fn try_from(_: u8) {}
30+
}
31+
32+
macro_rules! bar {
33+
() => {
34+
u32
35+
};
36+
}
37+
38+
fn main() {
39+
foo!().try_into(todo!());
40+
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
41+
//~| WARNING this is accepted in the current edition
42+
<bar!()>::try_from(0);
43+
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
44+
//~| WARNING this is accepted in the current edition
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: trait method `try_into` will become ambiguous in Rust 2021
2+
--> $DIR/future-prelude-collision-macros.rs:39:5
3+
|
4+
LL | foo!().try_into(todo!());
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyTry::try_into(foo!(), todo!())`
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/future-prelude-collision-macros.rs:4:9
9+
|
10+
LL | #![warn(rust_2021_prelude_collisions)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
13+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
14+
15+
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
16+
--> $DIR/future-prelude-collision-macros.rs:42:5
17+
|
18+
LL | <bar!()>::try_from(0);
19+
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<bar!() as TryFromU8>::try_from`
20+
|
21+
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
22+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
23+
24+
warning: 2 warnings emitted
25+

0 commit comments

Comments
 (0)
Please sign in to comment.