Fix error with suggestion for how to disambiguate associated function when struct is generic

This commit is contained in:
Ryan Levick 2021-07-28 18:34:19 +02:00
parent eba3228b2a
commit 578fcbdb3c
5 changed files with 126 additions and 3 deletions

View File

@ -5,7 +5,7 @@ use rustc_ast::Mutability;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{Ref, Ty};
use rustc_middle::ty::{Adt, Ref, Ty};
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
use rustc_span::symbol::kw::Underscore;
use rustc_span::symbol::{sym, Ident};
@ -255,16 +255,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
method_name.name
));
let self_ty = self
let self_ty_name = self
.sess()
.source_map()
.span_to_snippet(self_ty_span)
.unwrap_or_else(|_| self_ty.to_string());
let self_ty_generics_count = match self_ty.kind() {
// 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
// for a "<" in `self_ty_name`.
Adt(def, _) if !self_ty_name.contains("<") => self.tcx.generics_of(def.did).count(),
_ => 0,
};
let self_ty_generics = if self_ty_generics_count > 0 {
format!("<{}>", vec!["_"; self_ty_generics_count].join(", "))
} else {
String::new()
};
lint.span_suggestion(
span,
"disambiguate the associated function",
format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
format!(
"<{}{} as {}>::{}",
self_ty_name, self_ty_generics, trait_name, method_name.name,
),
Applicability::MachineApplicable,
);

View File

@ -0,0 +1,37 @@
// test for https://github.com/rust-lang/rust/issues/86940
// run-rustfix
// edition:2018
// check-pass
#![warn(rust_2021_prelude_collisions)]
#![allow(dead_code)]
#![allow(unused_imports)]
struct Generic<T, U>(T, U);
trait MyFromIter {
fn from_iter(_: i32) -> Self;
}
impl MyFromIter for Generic<i32, i32> {
fn from_iter(x: i32) -> Self {
Self(x, x)
}
}
impl std::iter::FromIterator<i32> for Generic<i32, i32> {
fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
todo!()
}
}
fn main() {
<Generic<_, _> as MyFromIter>::from_iter(1);
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
//~| this is accepted in the current edition (Rust 2018)
<Generic::<i32, i32> as MyFromIter>::from_iter(1);
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
//~| this is accepted in the current edition (Rust 2018)
<Generic::<_, _> as MyFromIter>::from_iter(1);
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
//~| this is accepted in the current edition (Rust 2018)
}

View File

@ -0,0 +1,37 @@
// test for https://github.com/rust-lang/rust/issues/86940
// run-rustfix
// edition:2018
// check-pass
#![warn(rust_2021_prelude_collisions)]
#![allow(dead_code)]
#![allow(unused_imports)]
struct Generic<T, U>(T, U);
trait MyFromIter {
fn from_iter(_: i32) -> Self;
}
impl MyFromIter for Generic<i32, i32> {
fn from_iter(x: i32) -> Self {
Self(x, x)
}
}
impl std::iter::FromIterator<i32> for Generic<i32, i32> {
fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
todo!()
}
}
fn main() {
Generic::from_iter(1);
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
//~| this is accepted in the current edition (Rust 2018)
Generic::<i32, i32>::from_iter(1);
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
//~| this is accepted in the current edition (Rust 2018)
Generic::<_, _>::from_iter(1);
//~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
//~| this is accepted in the current edition (Rust 2018)
}

View File

@ -0,0 +1,34 @@
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-generic.rs:28:5
|
LL | Generic::from_iter(1);
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<_, _> as MyFromIter>::from_iter`
|
note: the lint level is defined here
--> $DIR/future-prelude-collision-generic.rs:5: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 issue #85684 <https://github.com/rust-lang/rust/issues/85684>
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-generic.rs:31:5
|
LL | Generic::<i32, i32>::from_iter(1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-generic.rs:34:5
|
LL | Generic::<_, _>::from_iter(1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
warning: 3 warnings emitted