diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d0cbb58fb10..e6a2c5d5d14 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -466,7 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span); + let (res, opt_ty, segs) = + self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); let ty = match res { Res::Err => { self.set_tainted_by_errors(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 96569ae0e77..8e33f4f9e12 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -906,13 +906,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Resolves an associated value path into a base type and associated constant, or method /// resolution. The newly resolved definition is written into `type_dependent_defs`. - pub fn resolve_ty_and_res_ufcs( + pub fn resolve_ty_and_res_fully_qualified_call( &self, qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { - debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span); + debug!( + "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", + qpath, hir_id, span + ); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, ref path) => { return ( @@ -922,7 +925,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment), - QPath::LangItem(..) => bug!("`resolve_ty_and_res_ufcs` called on `LangItem`"), + QPath::LangItem(..) => { + bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") + } }; if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id) { @@ -932,25 +937,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return (def, Some(ty), slice::from_ref(&**item_segment)); } let item_name = item_segment.ident; - let result = self.resolve_ufcs(span, item_name, ty, hir_id).or_else(|error| { - let result = match error { - method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), - _ => Err(ErrorReported), - }; - if item_name.name != kw::Empty { - if let Some(mut e) = self.report_method_error( - span, - ty, - item_name, - SelfSource::QPath(qself), - error, - None, - ) { - e.emit(); + let result = self + .resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id) + .or_else(|error| { + let result = match error { + method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), + _ => Err(ErrorReported), + }; + if item_name.name != kw::Empty { + if let Some(mut e) = self.report_method_error( + span, + ty, + item_name, + SelfSource::QPath(qself), + error, + None, + ) { + e.emit(); + } } - } - result - }); + result + }); if result.is_ok() { self.maybe_lint_bare_trait(qpath, hir_id); diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index a1383fc4af0..2198455c163 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -501,8 +501,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(InferOk { obligations, value: callee }) } - /// Performs "universal function call" lookup. If lookup is successful, it will return the type - /// of definition and the [`DefId`] of the found function definition. + /// Performs a [full-qualified function call] (formerly "universal function call") lookup. If + /// lookup is successful, it will return the type of definition and the [`DefId`] of the found + /// function definition. + /// + /// [full-qualified function call]: https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls /// /// # Arguments /// @@ -512,17 +515,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// * `span`: the span of the call, excluding arguments (`Foo::bar::`) /// * `method_name`: the identifier of the function within the container type (`bar`) /// * `self_ty`: the type to search within (`Foo`) + /// * `self_ty_span` the span for the type being searched within (span of `Foo`) /// * `expr_id`: the [`hir::HirId`] of the expression composing the entire call #[instrument(level = "debug", skip(self))] - pub fn resolve_ufcs( + pub fn resolve_fully_qualified_call( &self, span: Span, method_name: Ident, self_ty: Ty<'tcx>, + self_ty_span: Span, expr_id: hir::HirId, ) -> Result<(DefKind, DefId), MethodError<'tcx>> { debug!( - "resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", + "resolve_fully_qualified_call: method_name={:?} self_ty={:?} expr_id={:?}", method_name, self_ty, expr_id, ); @@ -589,6 +594,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_name.name )); + let self_ty = self + .sess() + .source_map() + .span_to_snippet(self_ty_span) + .unwrap_or_else(|_| self_ty.to_string()); + lint.span_suggestion( span, "disambiguate the associated function", @@ -602,18 +613,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - debug!("resolve_ufcs: pick={:?}", pick); + debug!("resolve_fully_qualified_call: pick={:?}", pick); { let mut typeck_results = self.typeck_results.borrow_mut(); let used_trait_imports = Lrc::get_mut(&mut typeck_results.used_trait_imports).unwrap(); for import_id in pick.import_ids { - debug!("resolve_ufcs: used_trait_import: {:?}", import_id); + debug!("resolve_fully_qualified_call: used_trait_import: {:?}", import_id); used_trait_imports.insert(import_id); } } let def_kind = pick.item.kind.as_def_kind(); - debug!("resolve_ufcs: def_kind={:?}, def_id={:?}", def_kind, pick.item.def_id); + debug!( + "resolve_fully_qualified_call: def_kind={:?}, def_id={:?}", + def_kind, pick.item.def_id + ); tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span)); Ok((def_kind, pick.item.def_id)) } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 3ac760e2363..2879614d0c8 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -160,7 +160,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) { let path_res = match &pat.kind { - PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)), + PatKind::Path(qpath) => { + Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) + } _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); @@ -904,7 +906,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Resolve the path and check the definition for errors. - let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); + let (res, opt_ty, segments) = + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); if res == Res::Err { self.set_tainted_by_errors(); on_error(); diff --git a/src/test/ui/lint/future-prelude-collision.fixed b/src/test/ui/lint/future-prelude-collision.fixed index 2a0f74edc09..922c0d54a00 100644 --- a/src/test/ui/lint/future-prelude-collision.fixed +++ b/src/test/ui/lint/future-prelude-collision.fixed @@ -80,4 +80,8 @@ fn main() { 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 + + type U32Alias = u32; + let _ = ::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 } diff --git a/src/test/ui/lint/future-prelude-collision.rs b/src/test/ui/lint/future-prelude-collision.rs index 9a38bc065bf..154dde16d9e 100644 --- a/src/test/ui/lint/future-prelude-collision.rs +++ b/src/test/ui/lint/future-prelude-collision.rs @@ -80,4 +80,8 @@ fn main() { 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 + + type U32Alias = u32; + let _ = U32Alias::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 } diff --git a/src/test/ui/lint/future-prelude-collision.stderr b/src/test/ui/lint/future-prelude-collision.stderr index 13c8b8afddf..9c92074c36f 100644 --- a/src/test/ui/lint/future-prelude-collision.stderr +++ b/src/test/ui/lint/future-prelude-collision.stderr @@ -42,5 +42,11 @@ warning: trait method `try_into` will become ambiguous in Rust 2021 LL | let _: u32 = mut_ptr.try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)` -warning: 7 warnings emitted +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:85:13 + | +LL | let _ = U32Alias::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `::try_from` + +warning: 8 warnings emitted