Skip to content

Commit fdf9c09

Browse files
authored
Rollup merge of #88496 - m-ou-se:prelude-collision-lifetime-generics, r=petrochenkov
Fix prelude collision lint suggestion for generics with lifetimes Fixes #88470 cc `@nikomatsakis`
2 parents 4adacfd + 78a7d1c commit fdf9c09

7 files changed

+134
-47
lines changed

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

+38-27
Original file line numberDiff line numberDiff line change
@@ -239,47 +239,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
239239
let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());
240240
let trait_generics = self.tcx.generics_of(pick.item.container.id());
241241

242-
let parameter_count = trait_generics.count() - (trait_generics.has_self as usize);
243-
let trait_name = if parameter_count == 0 {
244-
trait_path
245-
} else {
246-
format!(
247-
"{}<{}>",
248-
trait_path,
249-
std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
250-
)
251-
};
242+
let trait_name =
243+
if trait_generics.params.len() <= trait_generics.has_self as usize {
244+
trait_path
245+
} else {
246+
let counts = trait_generics.own_counts();
247+
format!(
248+
"{}<{}>",
249+
trait_path,
250+
std::iter::repeat("'_")
251+
.take(counts.lifetimes)
252+
.chain(std::iter::repeat("_").take(
253+
counts.types + counts.consts - trait_generics.has_self as usize
254+
))
255+
.collect::<Vec<_>>()
256+
.join(", ")
257+
)
258+
};
252259

253260
let mut lint = lint.build(&format!(
254261
"trait-associated function `{}` will become ambiguous in Rust 2021",
255262
method_name.name
256263
));
257264

258-
let self_ty_name = self
265+
let mut self_ty_name = self
259266
.sess()
260267
.source_map()
261268
.span_to_snippet(self_ty_span)
262269
.unwrap_or_else(|_| self_ty.to_string());
263270

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-
};
271+
// Get the number of generics the self type has (if an Adt) unless we can determine that
272+
// the user has written the self type with generics already which we (naively) do by looking
273+
// for a "<" in `self_ty_name`.
274+
if !self_ty_name.contains('<') {
275+
if let Adt(def, _) = self_ty.kind() {
276+
let generics = self.tcx.generics_of(def.did);
277+
if !generics.params.is_empty() {
278+
let counts = generics.own_counts();
279+
self_ty_name += &format!(
280+
"<{}>",
281+
std::iter::repeat("'_")
282+
.take(counts.lifetimes)
283+
.chain(std::iter::repeat("_").take(counts.types + counts.consts))
284+
.collect::<Vec<_>>()
285+
.join(", ")
286+
);
287+
}
288+
}
289+
}
276290
lint.span_suggestion(
277291
span,
278292
"disambiguate the associated function",
279-
format!(
280-
"<{}{} as {}>::{}",
281-
self_ty_name, self_ty_generics, trait_name, method_name.name,
282-
),
293+
format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
283294
Applicability::MachineApplicable,
284295
);
285296

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// See https://github.com/rust-lang/rust/issues/88470
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+
pub trait PyTryFrom<'v, T>: Sized {
10+
fn try_from<V>(value: V) -> Result<&'v Self, T>;
11+
}
12+
13+
pub trait PyTryInto<T>: Sized {
14+
fn try_into(&self) -> Result<&T, i32>;
15+
}
16+
17+
struct Foo;
18+
19+
impl<U> PyTryInto<U> for Foo
20+
where
21+
U: for<'v> PyTryFrom<'v, i32>,
22+
{
23+
fn try_into(&self) -> Result<&U, i32> {
24+
<U as PyTryFrom<'_, _>>::try_from(self)
25+
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
26+
//~| this is accepted in the current edition (Rust 2018)
27+
}
28+
}
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// See https://github.com/rust-lang/rust/issues/88470
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+
pub trait PyTryFrom<'v, T>: Sized {
10+
fn try_from<V>(value: V) -> Result<&'v Self, T>;
11+
}
12+
13+
pub trait PyTryInto<T>: Sized {
14+
fn try_into(&self) -> Result<&T, i32>;
15+
}
16+
17+
struct Foo;
18+
19+
impl<U> PyTryInto<U> for Foo
20+
where
21+
U: for<'v> PyTryFrom<'v, i32>,
22+
{
23+
fn try_into(&self) -> Result<&U, i32> {
24+
U::try_from(self)
25+
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
26+
//~| this is accepted in the current edition (Rust 2018)
27+
}
28+
}
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
2+
--> $DIR/future-prelude-collision-generic-trait.rs:24:9
3+
|
4+
LL | U::try_from(self)
5+
| ^^^^^^^^^^^ help: disambiguate the associated function: `<U as PyTryFrom<'_, _>>::try_from`
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/future-prelude-collision-generic-trait.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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
14+
15+
warning: 1 warning emitted
16+

src/test/ui/rust-2021/future-prelude-collision-generic.fixed

+8-8
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,32 @@
66
#![allow(dead_code)]
77
#![allow(unused_imports)]
88

9-
struct Generic<T, U>(T, U);
9+
struct Generic<'a, U>(&'a U);
1010

1111
trait MyFromIter {
1212
fn from_iter(_: i32) -> Self;
1313
}
1414

15-
impl MyFromIter for Generic<i32, i32> {
16-
fn from_iter(x: i32) -> Self {
17-
Self(x, x)
15+
impl MyFromIter for Generic<'static, i32> {
16+
fn from_iter(_: i32) -> Self {
17+
todo!()
1818
}
1919
}
2020

21-
impl std::iter::FromIterator<i32> for Generic<i32, i32> {
21+
impl std::iter::FromIterator<i32> for Generic<'static, i32> {
2222
fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
2323
todo!()
2424
}
2525
}
2626

2727
fn main() {
28-
<Generic<_, _> as MyFromIter>::from_iter(1);
28+
<Generic<'_, _> as MyFromIter>::from_iter(1);
2929
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
3030
//~| this is accepted in the current edition (Rust 2018)
31-
<Generic::<i32, i32> as MyFromIter>::from_iter(1);
31+
<Generic::<'static, i32> as MyFromIter>::from_iter(1);
3232
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
3333
//~| this is accepted in the current edition (Rust 2018)
34-
<Generic::<_, _> as MyFromIter>::from_iter(1);
34+
<Generic::<'_, _> as MyFromIter>::from_iter(1);
3535
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
3636
//~| this is accepted in the current edition (Rust 2018)
3737
}

src/test/ui/rust-2021/future-prelude-collision-generic.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
#![allow(dead_code)]
77
#![allow(unused_imports)]
88

9-
struct Generic<T, U>(T, U);
9+
struct Generic<'a, U>(&'a U);
1010

1111
trait MyFromIter {
1212
fn from_iter(_: i32) -> Self;
1313
}
1414

15-
impl MyFromIter for Generic<i32, i32> {
16-
fn from_iter(x: i32) -> Self {
17-
Self(x, x)
15+
impl MyFromIter for Generic<'static, i32> {
16+
fn from_iter(_: i32) -> Self {
17+
todo!()
1818
}
1919
}
2020

21-
impl std::iter::FromIterator<i32> for Generic<i32, i32> {
21+
impl std::iter::FromIterator<i32> for Generic<'static, i32> {
2222
fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
2323
todo!()
2424
}
@@ -28,10 +28,10 @@ fn main() {
2828
Generic::from_iter(1);
2929
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
3030
//~| this is accepted in the current edition (Rust 2018)
31-
Generic::<i32, i32>::from_iter(1);
31+
Generic::<'static, i32>::from_iter(1);
3232
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
3333
//~| this is accepted in the current edition (Rust 2018)
34-
Generic::<_, _>::from_iter(1);
34+
Generic::<'_, _>::from_iter(1);
3535
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
3636
//~| this is accepted in the current edition (Rust 2018)
3737
}

src/test/ui/rust-2021/future-prelude-collision-generic.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: trait-associated function `from_iter` will become ambiguous in Rust 202
22
--> $DIR/future-prelude-collision-generic.rs:28:5
33
|
44
LL | Generic::from_iter(1);
5-
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<_, _> as MyFromIter>::from_iter`
5+
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<'_, _> as MyFromIter>::from_iter`
66
|
77
note: the lint level is defined here
88
--> $DIR/future-prelude-collision-generic.rs:5:9
@@ -15,17 +15,17 @@ LL | #![warn(rust_2021_prelude_collisions)]
1515
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
1616
--> $DIR/future-prelude-collision-generic.rs:31:5
1717
|
18-
LL | Generic::<i32, i32>::from_iter(1);
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
18+
LL | Generic::<'static, i32>::from_iter(1);
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<'static, i32> as MyFromIter>::from_iter`
2020
|
2121
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
2222
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
2323

2424
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
2525
--> $DIR/future-prelude-collision-generic.rs:34:5
2626
|
27-
LL | Generic::<_, _>::from_iter(1);
28-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
27+
LL | Generic::<'_, _>::from_iter(1);
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<'_, _> as MyFromIter>::from_iter`
2929
|
3030
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
3131
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>

0 commit comments

Comments
 (0)