1 use rustc_ast::Mutability;
2 use rustc_errors::Applicability;
4 use rustc_middle::ty::Ty;
5 use rustc_session::lint::builtin::FUTURE_PRELUDE_COLLISION;
6 use rustc_span::symbol::{sym, Ident};
10 method::probe::{self, Pick},
14 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15 pub(super) fn lint_dot_call_from_2018(
18 segment: &hir::PathSegment<'_>,
20 call_expr: &'tcx hir::Expr<'tcx>,
21 self_expr: &'tcx hir::Expr<'tcx>,
23 args: &'tcx [hir::Expr<'tcx>],
26 "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
27 segment.ident, self_ty, call_expr, self_expr
30 // Rust 2021 and later is already using the new prelude
35 // These are the method names that were added to prelude in Rust 2021
36 if !matches!(segment.ident.name, sym::try_into) {
40 // No need to lint if method came from std/core, as that will now be in the prelude
41 if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
45 self.tcx.struct_span_lint_hir(
46 FUTURE_PRELUDE_COLLISION,
50 let sp = call_expr.span;
51 let trait_name = self.tcx.def_path_str(pick.item.container.id());
53 let mut lint = lint.build(&format!(
54 "trait method `{}` will become ambiguous in Rust 2021",
58 if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span) {
59 let derefs = "*".repeat(pick.autoderefs);
61 let autoref = match pick.autoref_or_ptr_adjustment {
62 Some(probe::AutorefOrPtrAdjustment::Autoref {
63 mutbl: Mutability::Mut,
66 Some(probe::AutorefOrPtrAdjustment::Autoref {
67 mutbl: Mutability::Not,
70 Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
72 let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
73 pick.autoref_or_ptr_adjustment
75 format!("{}{} as *const _", derefs, self_expr)
77 format!("{}{}{}", autoref, derefs, self_expr)
85 self.sess().source_map().span_to_snippet(arg.span).unwrap()
92 "disambiguate the associated function",
95 trait_name, segment.ident.name, self_adjusted, args
97 Applicability::MachineApplicable,
103 "disambiguate the associated function with `{}::{}(...)`",
104 trait_name, segment.ident,
114 pub(super) fn lint_fully_qualified_call_from_2018(
123 // Rust 2021 and later is already using the new prelude
124 if span.rust_2021() {
128 // These are the fully qualified methods added to prelude in Rust 2021
129 if !matches!(method_name.name, sym::try_into | sym::try_from | sym::from_iter) {
133 // No need to lint if method came from std/core, as that will now be in the prelude
134 if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
138 // No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
139 // since such methods take precedence over trait methods.
140 if matches!(pick.kind, probe::PickKind::InherentImplPick) {
144 self.tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
145 // "type" refers to either a type or, more likely, a trait from which
146 // the associated function or method is from.
147 let type_name = self.tcx.def_path_str(pick.item.container.id());
148 let type_generics = self.tcx.generics_of(pick.item.container.id());
150 let parameter_count = type_generics.count() - (type_generics.has_self as usize);
151 let trait_name = if parameter_count == 0 {
157 std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
161 let mut lint = lint.build(&format!(
162 "trait-associated function `{}` will become ambiguous in Rust 2021",
169 .span_to_snippet(self_ty_span)
170 .unwrap_or_else(|_| self_ty.to_string());
172 lint.span_suggestion(
174 "disambiguate the associated function",
175 format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,),
176 Applicability::MachineApplicable,