Skip to content

Commit 578fcbd

Browse files
committed
Fix error with suggestion for how to disambiguate associated function when struct is generic
1 parent eba3228 commit 578fcbd

File tree

5 files changed

+126
-3
lines changed

5 files changed

+126
-3
lines changed

Diff for: compiler/rustc_typeck/src/check/method/prelude2021.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::Mutability;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_middle::ty::subst::InternalSubsts;
8-
use rustc_middle::ty::{Ref, Ty};
8+
use rustc_middle::ty::{Adt, Ref, Ty};
99
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
1010
use rustc_span::symbol::kw::Underscore;
1111
use rustc_span::symbol::{sym, Ident};
@@ -255,16 +255,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
255255
method_name.name
256256
));
257257

258-
let self_ty = self
258+
let self_ty_name = self
259259
.sess()
260260
.source_map()
261261
.span_to_snippet(self_ty_span)
262262
.unwrap_or_else(|_| self_ty.to_string());
263263

264+
let self_ty_generics_count = match self_ty.kind() {
265+
// Get the number of generics the self type has (if an Adt) unless we can determine that
266+
// the user has written the self type with generics already which we (naively) do by looking
267+
// for a "<" in `self_ty_name`.
268+
Adt(def, _) if !self_ty_name.contains("<") => self.tcx.generics_of(def.did).count(),
269+
_ => 0,
270+
};
271+
let self_ty_generics = if self_ty_generics_count > 0 {
272+
format!("<{}>", vec!["_"; self_ty_generics_count].join(", "))
273+
} else {
274+
String::new()
275+
};
264276
lint.span_suggestion(
265277
span,
266278
"disambiguate the associated function",
267-
format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
279+
format!(
280+
"<{}{} as {}>::{}",
281+
self_ty_name, self_ty_generics, trait_name, method_name.name,
282+
),
268283
Applicability::MachineApplicable,
269284
);
270285

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// test for https://github.com/rust-lang/rust/issues/86940
2+
// run-rustfix
3+
// edition:2018
4+
// check-pass
5+
#![warn(rust_2021_prelude_collisions)]
6+
#![allow(dead_code)]
7+
#![allow(unused_imports)]
8+
9+
struct Generic<T, U>(T, U);
10+
11+
trait MyFromIter {
12+
fn from_iter(_: i32) -> Self;
13+
}
14+
15+
impl MyFromIter for Generic<i32, i32> {
16+
fn from_iter(x: i32) -> Self {
17+
Self(x, x)
18+
}
19+
}
20+
21+
impl std::iter::FromIterator<i32> for Generic<i32, i32> {
22+
fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
23+
todo!()
24+
}
25+
}
26+
27+
fn main() {
28+
<Generic<_, _> as MyFromIter>::from_iter(1);
29+
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
30+
//~| this is accepted in the current edition (Rust 2018)
31+
<Generic::<i32, i32> as MyFromIter>::from_iter(1);
32+
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
33+
//~| this is accepted in the current edition (Rust 2018)
34+
<Generic::<_, _> as MyFromIter>::from_iter(1);
35+
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
36+
//~| this is accepted in the current edition (Rust 2018)
37+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// test for https://github.com/rust-lang/rust/issues/86940
2+
// run-rustfix
3+
// edition:2018
4+
// check-pass
5+
#![warn(rust_2021_prelude_collisions)]
6+
#![allow(dead_code)]
7+
#![allow(unused_imports)]
8+
9+
struct Generic<T, U>(T, U);
10+
11+
trait MyFromIter {
12+
fn from_iter(_: i32) -> Self;
13+
}
14+
15+
impl MyFromIter for Generic<i32, i32> {
16+
fn from_iter(x: i32) -> Self {
17+
Self(x, x)
18+
}
19+
}
20+
21+
impl std::iter::FromIterator<i32> for Generic<i32, i32> {
22+
fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
23+
todo!()
24+
}
25+
}
26+
27+
fn main() {
28+
Generic::from_iter(1);
29+
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
30+
//~| this is accepted in the current edition (Rust 2018)
31+
Generic::<i32, i32>::from_iter(1);
32+
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
33+
//~| this is accepted in the current edition (Rust 2018)
34+
Generic::<_, _>::from_iter(1);
35+
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
36+
//~| this is accepted in the current edition (Rust 2018)
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
2+
--> $DIR/future-prelude-collision-generic.rs:28:5
3+
|
4+
LL | Generic::from_iter(1);
5+
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<_, _> as MyFromIter>::from_iter`
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/future-prelude-collision-generic.rs:5: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 issue #85684 <https://github.com/rust-lang/rust/issues/85684>
14+
15+
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
16+
--> $DIR/future-prelude-collision-generic.rs:31:5
17+
|
18+
LL | Generic::<i32, i32>::from_iter(1);
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
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 issue #85684 <https://github.com/rust-lang/rust/issues/85684>
23+
24+
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
25+
--> $DIR/future-prelude-collision-generic.rs:34:5
26+
|
27+
LL | Generic::<_, _>::from_iter(1);
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
29+
|
30+
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
31+
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
32+
33+
warning: 3 warnings emitted
34+
File renamed without changes.

0 commit comments

Comments
 (0)