Fix future_prelude_collision lint breaking for pointer mutabilty coercion

This commit is contained in:
jam1garner 2021-05-27 22:29:22 -04:00 committed by Niko Matsakis
parent 93c60f26bf
commit cb4999242d
4 changed files with 138 additions and 85 deletions

View file

@ -203,60 +203,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if span.edition() < Edition::Edition2021 {
if let sym::try_into = segment.ident.name {
if let probe::PickKind::TraitPick = pick.kind {
if !matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core)
{
self.tcx.struct_span_lint_hir(
FUTURE_PRELUDE_COLLISION,
call_expr.hir_id,
call_expr.span,
|lint| {
let sp = call_expr.span;
let trait_name =
self.tcx.def_path_str(pick.item.container.assert_trait());
if !matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
self.tcx.struct_span_lint_hir(
FUTURE_PRELUDE_COLLISION,
call_expr.hir_id,
call_expr.span,
|lint| {
let sp = call_expr.span;
let type_name = self.tcx.def_path_str(pick.item.container.id());
let type_generics = self.tcx.generics_of(pick.item.container.id());
let parameter_count =
type_generics.count() - (type_generics.has_self as usize);
let trait_name = if parameter_count == 0 {
type_name
} else {
format!(
"{}<{}>",
type_name,
std::iter::repeat("_")
.take(parameter_count)
.collect::<Vec<_>>()
.join(", ")
)
};
let mut lint = lint.build(&format!(
"trait method `{}` will become ambiguous in Rust 2021",
segment.ident.name
));
let mut lint = lint.build(&format!(
"trait method `{}` will become ambiguous in Rust 2021",
segment.ident.name
));
if let Ok(self_expr) =
self.sess().source_map().span_to_snippet(self_expr.span)
{
let derefs = "*".repeat(pick.autoderefs);
let self_adjusted = match pick.autoref_or_ptr_adjustment {
Some(probe::AutorefOrPtrAdjustment::Autoref {
mutbl: Mutability::Mut, ..
}) => format!("&mut {}{}", derefs, self_expr),
Some(probe::AutorefOrPtrAdjustment::Autoref {
mutbl: Mutability::Not, ..
}) => format!("&{}{}", derefs, self_expr),
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None
=> format!("{}{}", derefs, self_expr),
if let Ok(self_expr) =
self.sess().source_map().span_to_snippet(self_expr.span)
{
let derefs = "*".repeat(pick.autoderefs);
let autoref = match pick.autoref_or_ptr_adjustment {
Some(probe::AutorefOrPtrAdjustment::Autoref {
mutbl: Mutability::Mut,
..
}) => "&mut ",
Some(probe::AutorefOrPtrAdjustment::Autoref {
mutbl: Mutability::Not,
..
}) => "&",
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
};
let self_adjusted =
if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
pick.autoref_or_ptr_adjustment
{
format!("{}{} as *const _", derefs, self_expr)
} else {
format!("{}{}{}", autoref, derefs, self_expr)
};
lint.span_suggestion(
sp,
"disambiguate the associated function",
format!(
"{}::{}({})",
trait_name, segment.ident.name, self_adjusted,
),
Applicability::MachineApplicable,
);
} else {
lint.span_help(
sp,
&format!(
"disambiguate the associated function with `{}::{}(...)`",
trait_name, segment.ident,
),
);
}
lint.span_suggestion(
sp,
"disambiguate the associated function",
format!(
"{}::{}({})",
trait_name, segment.ident.name, self_adjusted,
),
Applicability::MachineApplicable,
);
} else {
lint.span_help(
sp,
&format!(
"disambiguate the associated function with `{}::{}(...)`",
trait_name, segment.ident,
),
);
}
lint.emit();
},
);
}
lint.emit();
},
);
}
}
}
@ -541,38 +562,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if span.edition() < Edition::Edition2021 {
if let sym::try_into | sym::try_from | sym::from_iter = method_name.name {
if let probe::PickKind::TraitPick = pick.kind {
if !matches!(tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
let trait_def_id = pick.item.container.assert_trait();
let trait_generics = tcx.generics_of(trait_def_id);
let parameter_count = trait_generics.count() - (trait_generics.has_self as usize);
if !matches!(tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
// "type" refers to either a type or, more likely, a trait from which
// the associated function or method is from.
let type_name = tcx.def_path_str(pick.item.container.id());
let type_generics = tcx.generics_of(pick.item.container.id());
let trait_name = if parameter_count == 0 {
tcx.def_path_str(trait_def_id)
} else {
format!(
"{}<{}>",
tcx.def_path_str(trait_def_id),
std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
)
};
let parameter_count =
type_generics.count() - (type_generics.has_self as usize);
let trait_name = if parameter_count == 0 {
type_name
} else {
format!(
"{}<{}>",
type_name,
std::iter::repeat("_")
.take(parameter_count)
.collect::<Vec<_>>()
.join(", ")
)
};
let mut lint = lint.build(&format!(
"trait-associated function `{}` will become ambiguous in Rust 2021",
method_name.name
));
let mut lint = lint.build(&format!(
"trait-associated function `{}` will become ambiguous in Rust 2021",
method_name.name
));
lint.span_suggestion(
span,
"disambiguate the associated function",
format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
Applicability::MachineApplicable,
);
lint.span_suggestion(
span,
"disambiguate the associated function",
format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
Applicability::MachineApplicable,
);
lint.emit();
});
}
lint.emit();
});
}
}
}

View file

@ -29,6 +29,12 @@ impl TryFromU8 for u32 {
}
}
impl TryIntoU32 for *const u16 {
fn try_into(self) -> Result<u32, ()> {
Ok(unsafe { *self } as u32)
}
}
trait FromByteIterator {
fn from_iter<T>(iter: T) -> Self
where T: Iterator<Item = u8>;
@ -69,4 +75,9 @@ fn main() {
// test autoref
let _: u32 = TryIntoU32::try_into(&3.0).unwrap();
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
let mut data = 3u16;
let mut_ptr = std::ptr::addr_of_mut!(data);
let _: u32 = TryIntoU32::try_into(mut_ptr as *const _).unwrap();
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
}

View file

@ -29,6 +29,12 @@ impl TryFromU8 for u32 {
}
}
impl TryIntoU32 for *const u16 {
fn try_into(self) -> Result<u32, ()> {
Ok(unsafe { *self } as u32)
}
}
trait FromByteIterator {
fn from_iter<T>(iter: T) -> Self
where T: Iterator<Item = u8>;
@ -69,4 +75,9 @@ fn main() {
// test autoref
let _: u32 = 3.0.try_into().unwrap();
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
let mut data = 3u16;
let mut_ptr = std::ptr::addr_of_mut!(data);
let _: u32 = mut_ptr.try_into().unwrap();
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
}

View file

@ -1,5 +1,5 @@
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:47:18
--> $DIR/future-prelude-collision.rs:53:18
|
LL | let _: u32 = 3u8.try_into().unwrap();
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)`
@ -7,34 +7,40 @@ LL | let _: u32 = 3u8.try_into().unwrap();
= note: `#[warn(future_prelude_collision)]` on by default
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:51:13
--> $DIR/future-prelude-collision.rs:57:13
|
LL | let _ = u32::try_from(3u8).unwrap();
| ^^^^^^^^^^^^^ help: disambiguate the associated function: `<u32 as TryFromU8>::try_from`
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:55:13
--> $DIR/future-prelude-collision.rs:61:13
|
LL | let _ = <Vec<u8>>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter());
| ^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Vec<u8> as FromByteIterator>::from_iter`
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:62:18
--> $DIR/future-prelude-collision.rs:68:18
|
LL | let _: u32 = <_>::try_from(3u8).unwrap();
| ^^^^^^^^^^^^^ help: disambiguate the associated function: `<_ as TryFromU8>::try_from`
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:66:18
--> $DIR/future-prelude-collision.rs:72:18
|
LL | let _: u32 = (&3u8).try_into().unwrap();
| ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(*(&3u8))`
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:70:18
--> $DIR/future-prelude-collision.rs:76:18
|
LL | let _: u32 = 3.0.try_into().unwrap();
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(&3.0)`
warning: 6 warnings emitted
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:81:18
|
LL | let _: u32 = mut_ptr.try_into().unwrap();
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)`
warning: 7 warnings emitted