Rollup merge of #117655 - compiler-errors:method-tweaks, r=estebank

Method suggestion code tweaks

I was rummaging around the method suggestion code after https://github.com/rust-lang/rust/pull/117006#discussion_r1384153722 and saw a few things to simplify.

This is two unrelated commits, both in the same file. Review them separately, if you'd like.

r? estebank
This commit is contained in:
Matthias Krüger 2023-11-08 00:47:52 +01:00 committed by GitHub
commit f72e974e3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 178 additions and 198 deletions

View file

@ -13,7 +13,7 @@ use crate::errors::{
YieldExprOutsideOfCoroutine, YieldExprOutsideOfCoroutine,
}; };
use crate::fatally_break_rust; use crate::fatally_break_rust;
use crate::method::{MethodCallComponents, SelfSource}; use crate::method::SelfSource;
use crate::type_error_struct; use crate::type_error_struct;
use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
use crate::{ use crate::{
@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let (res, opt_ty, segs) = let (res, opt_ty, segs) =
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args));
let ty = match res { let ty = match res {
Res::Err => { Res::Err => {
self.suggest_assoc_method_call(segs); self.suggest_assoc_method_call(segs);
@ -1332,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segment.ident, segment.ident,
SelfSource::MethodCall(rcvr), SelfSource::MethodCall(rcvr),
error, error,
Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }), Some(args),
expected, expected,
false, false,
) { ) {

View file

@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath: &'tcx QPath<'tcx>, qpath: &'tcx QPath<'tcx>,
hir_id: hir::HirId, hir_id: hir::HirId,
span: Span, span: Span,
args: Option<&'tcx [hir::Expr<'tcx>]>,
) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) { ) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
debug!( debug!(
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
@ -898,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name, item_name,
SelfSource::QPath(qself), SelfSource::QPath(qself),
error, error,
None, args,
Expectation::NoExpectation, Expectation::NoExpectation,
trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021 trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
) { ) {

View file

@ -7,7 +7,7 @@ mod prelude2021;
pub mod probe; pub mod probe;
mod suggest; mod suggest;
pub use self::suggest::{MethodCallComponents, SelfSource}; pub use self::suggest::SelfSource;
pub use self::MethodError::*; pub use self::MethodError::*;
use crate::errors::OpMethodGenericParams; use crate::errors::OpMethodGenericParams;

View file

@ -34,7 +34,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::def_id::DefIdSet; use rustc_span::def_id::DefIdSet;
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span}; use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span};
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _; use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor;
use std::cmp::{self, Ordering}; use std::cmp::{self, Ordering};
use std::iter; use std::iter;
/// After identifying that `full_expr` is a method call, we use this type to keep the expression's
/// components readily available to us to point at the right place in diagnostics.
#[derive(Debug, Clone, Copy)]
pub struct MethodCallComponents<'tcx> {
pub receiver: &'tcx hir::Expr<'tcx>,
pub args: &'tcx [hir::Expr<'tcx>],
pub full_expr: &'tcx hir::Expr<'tcx>,
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
let tcx = self.tcx; let tcx = self.tcx;
@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: Ident, item_name: Ident,
source: SelfSource<'tcx>, source: SelfSource<'tcx>,
error: MethodError<'tcx>, error: MethodError<'tcx>,
args: Option<MethodCallComponents<'tcx>>, args: Option<&'tcx [hir::Expr<'tcx>]>,
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
trait_missing_method: bool, trait_missing_method: bool,
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_candidates_on_method_error( self.note_candidates_on_method_error(
rcvr_ty, rcvr_ty,
item_name, item_name,
source,
args, args,
span, span,
&mut err, &mut err,
@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn suggest_missing_writer( fn suggest_missing_writer(
&self, &self,
rcvr_ty: Ty<'tcx>, rcvr_ty: Ty<'tcx>,
args: MethodCallComponents<'tcx>, rcvr_expr: &hir::Expr<'tcx>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> { ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty); let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
let mut err = struct_span_err!( let mut err = struct_span_err!(
self.tcx.sess, self.tcx.sess,
args.receiver.span, rcvr_expr.span,
E0599, E0599,
"cannot write into `{}`", "cannot write into `{}`",
ty_str ty_str
); );
err.span_note( err.span_note(
args.receiver.span, rcvr_expr.span,
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method", "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
); );
if let ExprKind::Lit(_) = args.receiver.kind { if let ExprKind::Lit(_) = rcvr_expr.kind {
err.span_help( err.span_help(
args.receiver.span.shrink_to_lo(), rcvr_expr.span.shrink_to_lo(),
"a writer is needed before this format string", "a writer is needed before this format string",
); );
}; };
@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rcvr_ty: Ty<'tcx>, rcvr_ty: Ty<'tcx>,
item_name: Ident, item_name: Ident,
source: SelfSource<'tcx>, source: SelfSource<'tcx>,
args: Option<MethodCallComponents<'tcx>>, args: Option<&'tcx [hir::Expr<'tcx>]>,
sugg_span: Span, sugg_span: Span,
no_match_data: &mut NoMatchData<'tcx>, no_match_data: &mut NoMatchData<'tcx>,
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.is_diagnostic_item(sym::write_macro, def_id) tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_name.name == Symbol::intern("write_fmt"); }) && item_name.name == Symbol::intern("write_fmt");
let mut err = if is_write && let Some(args) = args { let mut err =
self.suggest_missing_writer(rcvr_ty, args) if is_write && let SelfSource::MethodCall(rcvr_expr) = source
} else { {
tcx.sess.create_err(NoAssociatedItem { self.suggest_missing_writer(rcvr_ty, rcvr_expr)
span, } else {
item_kind, tcx.sess.create_err(NoAssociatedItem {
item_name, span,
ty_prefix: if trait_missing_method { item_kind,
// FIXME(mu001999) E0599 maybe not suitable here because it is for types item_name,
Cow::from("trait") ty_prefix: if trait_missing_method {
} else { // FIXME(mu001999) E0599 maybe not suitable here because it is for types
rcvr_ty.prefix_string(self.tcx) Cow::from("trait")
}, } else {
ty_str: ty_str_reported, rcvr_ty.prefix_string(self.tcx)
trait_missing_method, },
}) ty_str: ty_str_reported,
}; trait_missing_method,
})
};
if tcx.sess.source_map().is_multiline(sugg_span) { if tcx.sess.source_map().is_multiline(sugg_span) {
err.span_label(sugg_span.with_hi(span.lo()), ""); err.span_label(sugg_span.with_hi(span.lo()), "");
} }
@ -409,7 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.downgrade_to_delayed_bug(); err.downgrade_to_delayed_bug();
} }
self.find_builder_fn(&mut err, rcvr_ty, source); if matches!(source, SelfSource::QPath(_)) && args.is_some() {
self.find_builder_fn(&mut err, rcvr_ty);
}
if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
err.help(format!( err.help(format!(
"method `poll` found on `Pin<&mut {ty_str}>`, \ "method `poll` found on `Pin<&mut {ty_str}>`, \
@ -523,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_candidates_on_method_error( self.note_candidates_on_method_error(
rcvr_ty, rcvr_ty,
item_name, item_name,
source,
args, args,
span, span,
&mut err, &mut err,
@ -533,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_candidates_on_method_error( self.note_candidates_on_method_error(
rcvr_ty, rcvr_ty,
item_name, item_name,
source,
args, args,
span, span,
&mut err, &mut err,
@ -976,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
unsatisfied_bounds = true; unsatisfied_bounds = true;
} }
} else if let ty::Adt(def, targs) = rcvr_ty.kind() } else if let ty::Adt(def, targs) = rcvr_ty.kind()
&& let Some(args) = args && let SelfSource::MethodCall(rcvr_expr) = source
{ {
// This is useful for methods on arbitrary self types that might have a simple // This is useful for methods on arbitrary self types that might have a simple
// mutability difference, like calling a method on `Pin<&mut Self>` that is on // mutability difference, like calling a method on `Pin<&mut Self>` that is on
@ -999,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rcvr_ty, rcvr_ty,
&item_segment, &item_segment,
span, span,
args.full_expr, tcx.hir().get_parent(rcvr_expr.hir_id).expect_expr(),
args.receiver, rcvr_expr,
) { ) {
err.span_note( err.span_note(
tcx.def_span(method.def_id), tcx.def_span(method.def_id),
@ -1169,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span, span,
rcvr_ty, rcvr_ty,
item_name, item_name,
args.map(|MethodCallComponents { args, .. }| args.len() + 1), args.map(|args| args.len() + 1),
source, source,
no_match_data.out_of_scope_traits.clone(), no_match_data.out_of_scope_traits.clone(),
&unsatisfied_predicates, &unsatisfied_predicates,
@ -1250,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
rcvr_ty: Ty<'tcx>, rcvr_ty: Ty<'tcx>,
item_name: Ident, item_name: Ident,
args: Option<MethodCallComponents<'tcx>>, self_source: SelfSource<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>,
span: Span, span: Span,
err: &mut Diagnostic, err: &mut Diagnostic,
sources: &mut Vec<CandidateSource>, sources: &mut Vec<CandidateSource>,
@ -1320,38 +1320,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
if let Some(sugg_span) = sugg_span if let Some(sugg_span) = sugg_span
&& let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did)
{ && let Some(sugg) = print_disambiguation_help(
let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); self.tcx,
let ty = match item.kind {
ty::AssocKind::Const | ty::AssocKind::Type => impl_ty,
ty::AssocKind::Fn => self
.tcx
.fn_sig(item.def_id)
.instantiate_identity()
.inputs()
.skip_binder()
.get(0)
.filter(|ty| ty.is_ref() && !rcvr_ty.is_ref())
.copied()
.unwrap_or(rcvr_ty),
};
if let Some(sugg) = print_disambiguation_help(
item_name,
args,
err, err,
path, self_source,
ty, args,
Some(impl_ty), trait_ref.instantiate(
item.kind, self.tcx,
self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), self.fresh_args_for_item(sugg_span, impl_did)
sugg_span, ).with_self_ty(self.tcx, rcvr_ty),
idx, idx,
self.tcx.sess.source_map(), sugg_span,
item.fn_has_self_parameter, item,
) { )
suggs.push(sugg); {
} suggs.push(sugg);
} }
} }
CandidateSource::Trait(trait_did) => { CandidateSource::Trait(trait_did) => {
@ -1373,24 +1356,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_note(item_span, msg); err.span_note(item_span, msg);
None None
}; };
if let Some(sugg_span) = sugg_span { if let Some(sugg_span) = sugg_span
let path = self.tcx.def_path_str(trait_did); && let Some(sugg) = print_disambiguation_help(
if let Some(sugg) = print_disambiguation_help( self.tcx,
item_name,
args,
err, err,
path, self_source,
rcvr_ty, args,
None, ty::TraitRef::new(
item.kind, self.tcx,
self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), trait_did,
sugg_span, self.fresh_args_for_item(sugg_span, trait_did)
).with_self_ty(self.tcx, rcvr_ty),
idx, idx,
self.tcx.sess.source_map(), sugg_span,
item.fn_has_self_parameter, item,
) { )
suggs.push(sugg); {
} suggs.push(sugg);
} }
} }
} }
@ -1410,18 +1392,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Look at all the associated functions without receivers in the type's inherent impls /// Look at all the associated functions without receivers in the type's inherent impls
/// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`. /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>) { fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) {
let ty::Adt(adt_def, _) = rcvr_ty.kind() else { let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
return; return;
}; };
let SelfSource::QPath(ty) = source else {
return;
};
let hir = self.tcx.hir();
if let Some(Node::Pat(_)) = hir.find(hir.parent_id(ty.hir_id)) {
// Do not suggest a fn call when a pattern is expected.
return;
}
let mut items = self let mut items = self
.tcx .tcx
.inherent_impls(adt_def.did()) .inherent_impls(adt_def.did())
@ -1504,7 +1478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rcvr_ty: Ty<'tcx>, rcvr_ty: Ty<'tcx>,
source: SelfSource<'tcx>, source: SelfSource<'tcx>,
item_name: Ident, item_name: Ident,
args: Option<MethodCallComponents<'tcx>>, args: Option<&'tcx [hir::Expr<'tcx>]>,
sugg_span: Span, sugg_span: Span,
) { ) {
let mut has_unsuggestable_args = false; let mut has_unsuggestable_args = false;
@ -1578,38 +1552,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None None
}; };
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let args = if let Some(MethodCallComponents { receiver, args, .. }) = args { let args = if let SelfSource::MethodCall(receiver) = source
// The first arg is the same kind as the receiver && let Some(args) = args
let explicit_args = if first_arg.is_some() { {
std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>() // The first arg is the same kind as the receiver
let explicit_args = if first_arg.is_some() {
std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
} else {
// There is no `Self` kind to infer the arguments from
if has_unsuggestable_args {
applicability = Applicability::HasPlaceholders;
}
args.iter().collect()
};
format!(
"({}{})",
first_arg.unwrap_or(""),
explicit_args
.iter()
.map(|arg| self
.tcx
.sess
.source_map()
.span_to_snippet(arg.span)
.unwrap_or_else(|_| {
applicability = Applicability::HasPlaceholders;
"_".to_owned()
}))
.collect::<Vec<_>>()
.join(", "),
)
} else { } else {
// There is no `Self` kind to infer the arguments from applicability = Applicability::HasPlaceholders;
if has_unsuggestable_args { "(...)".to_owned()
applicability = Applicability::HasPlaceholders;
}
args.iter().collect()
}; };
format!(
"({}{})",
first_arg.unwrap_or(""),
explicit_args
.iter()
.map(|arg| self
.tcx
.sess
.source_map()
.span_to_snippet(arg.span)
.unwrap_or_else(|_| {
applicability = Applicability::HasPlaceholders;
"_".to_owned()
}))
.collect::<Vec<_>>()
.join(", "),
)
} else {
applicability = Applicability::HasPlaceholders;
"(...)".to_owned()
};
err.span_suggestion( err.span_suggestion(
sugg_span, sugg_span,
"use associated function syntax instead", "use associated function syntax instead",
@ -3267,56 +3243,59 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
} }
fn print_disambiguation_help<'tcx>( fn print_disambiguation_help<'tcx>(
item_name: Ident, tcx: TyCtxt<'tcx>,
args: Option<MethodCallComponents<'tcx>>,
err: &mut Diagnostic, err: &mut Diagnostic,
trait_name: String, source: SelfSource<'tcx>,
rcvr_ty: Ty<'_>, args: Option<&'tcx [hir::Expr<'tcx>]>,
impl_self_ty: Option<Ty<'_>>, trait_ref: ty::TraitRef<'tcx>,
kind: ty::AssocKind, candidate_idx: Option<usize>,
def_kind_descr: &'static str,
span: Span, span: Span,
candidate: Option<usize>, item: ty::AssocItem,
source_map: &source_map::SourceMap,
fn_has_self_parameter: bool,
) -> Option<String> { ) -> Option<String> {
let trait_ref = if item.fn_has_self_parameter {
trait_ref.print_only_trait_name().to_string()
} else {
format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
};
Some( Some(
if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args) if matches!(item.kind, ty::AssocKind::Fn)
&& let SelfSource::MethodCall(receiver) = source
&& let Some(args) = args
{ {
let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
let item_name = item.ident(tcx);
let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0]
.ref_mutability()
.map_or("", |mutbl| mutbl.ref_prefix_str());
let args = format!( let args = format!(
"({}{})", "({}{})",
rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), rcvr_ref,
std::iter::once(receiver) std::iter::once(receiver)
.chain(args.iter()) .chain(args.iter())
.map(|arg| source_map .map(|arg| tcx
.sess
.source_map()
.span_to_snippet(arg.span) .span_to_snippet(arg.span)
.unwrap_or_else(|_| { "_".to_owned() })) .unwrap_or_else(|_| { "_".to_owned() }))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "), .join(", "),
); );
let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty {
format!("<{impl_self_ty} as {trait_name}>")
} else {
trait_name
};
err.span_suggestion_verbose( err.span_suggestion_verbose(
span, span,
format!( format!(
"disambiguate the {def_kind_descr} for {}", "disambiguate the {def_kind_descr} for {}",
if let Some(candidate) = candidate { if let Some(candidate) = candidate_idx {
format!("candidate #{candidate}") format!("candidate #{candidate}")
} else { } else {
"the candidate".to_string() "the candidate".to_string()
}, },
), ),
format!("{trait_name}::{item_name}{args}"), format!("{trait_ref}::{item_name}{args}"),
Applicability::HasPlaceholders, Applicability::HasPlaceholders,
); );
return None; return None;
} else if let Some(impl_self_ty) = impl_self_ty {
format!("<{impl_self_ty} as {trait_name}>::")
} else { } else {
format!("{trait_name}::") format!("{trait_ref}::")
}, },
) )
} }

View file

@ -166,9 +166,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) { fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info; let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
let path_res = match &pat.kind { let path_res = match &pat.kind {
PatKind::Path(qpath) => { PatKind::Path(qpath) => Some(
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
} ),
_ => None, _ => None,
}; };
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Resolve the path and check the definition for errors. // Resolve the path and check the definition for errors.
let (res, opt_ty, segments) = let (res, opt_ty, segments) =
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
if res == Res::Err { if res == Res::Err {
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e); self.set_tainted_by_errors(e);

View file

@ -29,10 +29,10 @@ LL | fn foo(&self) {}
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | <T as A>::foo(&s); LL | A::foo(&s);
| ~~~~~~~~~~ | ~~~
LL | <T as B>::foo(&s); LL | B::foo(&s);
| ~~~~~~~~~~ | ~~~
error[E0034]: multiple applicable items in scope error[E0034]: multiple applicable items in scope
--> $DIR/disambiguate-multiple-blanket-impl.rs:33:8 --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8
@ -52,9 +52,9 @@ LL | const CONST: usize = 2;
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | <T as A>::CONST; LL | <S as A>::CONST;
| ~~~~~~~~~~ | ~~~~~~~~~~
LL | <T as B>::CONST; LL | <S as B>::CONST;
| ~~~~~~~~~~ | ~~~~~~~~~~
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -29,10 +29,10 @@ LL | fn foo(&self) {}
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | <S as A>::foo(&s); LL | A::foo(&s);
| ~~~~~~~~~~ | ~~~
LL | <S as B>::foo(&s); LL | B::foo(&s);
| ~~~~~~~~~~ | ~~~
error[E0034]: multiple applicable items in scope error[E0034]: multiple applicable items in scope
--> $DIR/disambiguate-multiple-impl.rs:34:16 --> $DIR/disambiguate-multiple-impl.rs:34:16

View file

@ -37,12 +37,12 @@ LL | fn foo(&self);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
help: disambiguate the method for candidate #1 help: disambiguate the method for candidate #1
| |
LL | A::foo(t); LL | A::foo(&t);
| ~~~~~~~~~ | ~~~~~~~~~~
help: disambiguate the method for candidate #2 help: disambiguate the method for candidate #2
| |
LL | B::foo(t); LL | B::foo(&t);
| ~~~~~~~~~ | ~~~~~~~~~~
error[E0034]: multiple applicable items in scope error[E0034]: multiple applicable items in scope
--> $DIR/disambiguate-multiple-trait-2.rs:20:16 --> $DIR/disambiguate-multiple-trait-2.rs:20:16
@ -62,10 +62,10 @@ LL | const CONST: usize;
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | let _ = A::CONST; LL | let _ = <T as A>::CONST;
| ~~~ | ~~~~~~~~~~
LL | let _ = B::CONST; LL | let _ = <T as B>::CONST;
| ~~~ | ~~~~~~~~~~
error[E0223]: ambiguous associated type error[E0223]: ambiguous associated type
--> $DIR/disambiguate-multiple-trait-2.rs:52:12 --> $DIR/disambiguate-multiple-trait-2.rs:52:12
@ -98,10 +98,10 @@ LL | fn foo(&self) {}
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | <T as A>::foo(&s); LL | A::foo(&s);
| ~~~~~~~~~~ | ~~~
LL | <T as B>::foo(&s); LL | B::foo(&s);
| ~~~~~~~~~~ | ~~~
error[E0034]: multiple applicable items in scope error[E0034]: multiple applicable items in scope
--> $DIR/disambiguate-multiple-trait-2.rs:49:16 --> $DIR/disambiguate-multiple-trait-2.rs:49:16
@ -121,9 +121,9 @@ LL | const CONST: usize = 1;
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | let _ = <T as A>::CONST; LL | let _ = <S as A>::CONST;
| ~~~~~~~~~~ | ~~~~~~~~~~
LL | let _ = <T as B>::CONST; LL | let _ = <S as B>::CONST;
| ~~~~~~~~~~ | ~~~~~~~~~~
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -29,10 +29,10 @@ LL | fn foo(&self) {}
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | <T as A>::foo(&s); LL | A::foo(&s);
| ~~~~~~~~~~ | ~~~
LL | <T as B>::foo(&s); LL | B::foo(&s);
| ~~~~~~~~~~ | ~~~
error[E0034]: multiple applicable items in scope error[E0034]: multiple applicable items in scope
--> $DIR/disambiguate-multiple-trait.rs:27:16 --> $DIR/disambiguate-multiple-trait.rs:27:16
@ -52,9 +52,9 @@ LL | const CONST: usize = 2;
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
help: use fully-qualified syntax to disambiguate help: use fully-qualified syntax to disambiguate
| |
LL | let _ = <T as A>::CONST; LL | let _ = <S as A>::CONST;
| ~~~~~~~~~~ | ~~~~~~~~~~
LL | let _ = <T as B>::CONST; LL | let _ = <S as B>::CONST;
| ~~~~~~~~~~ | ~~~~~~~~~~
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -16,12 +16,12 @@ LL | trait B { fn foo(&self); }
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
help: disambiguate the method for candidate #1 help: disambiguate the method for candidate #1
| |
LL | A::foo(t); LL | A::foo(&t);
| ~~~~~~~~~ | ~~~~~~~~~~
help: disambiguate the method for candidate #2 help: disambiguate the method for candidate #2
| |
LL | B::foo(t); LL | B::foo(&t);
| ~~~~~~~~~ | ~~~~~~~~~~
error: aborting due to previous error error: aborting due to previous error

View file

@ -54,8 +54,8 @@ LL | let z = NuisanceFoo::foo(x);
| ~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~
help: disambiguate the method for candidate #3 help: disambiguate the method for candidate #3
| |
LL | let z = FinalFoo::foo(x); LL | let z = FinalFoo::foo(&x);
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24 --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24

View file

@ -16,12 +16,12 @@ LL | fn foo(&mut self) {}
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
help: disambiguate the method for candidate #1 help: disambiguate the method for candidate #1
| |
LL | A::foo(&a) LL | A::foo(&mut a)
| ~~~~~~~~~~ | ~~~~~~~~~~~~~~
help: disambiguate the method for candidate #2 help: disambiguate the method for candidate #2
| |
LL | B::foo(&a) LL | B::foo(&mut a)
| ~~~~~~~~~~ | ~~~~~~~~~~~~~~
error[E0034]: multiple applicable items in scope error[E0034]: multiple applicable items in scope
--> $DIR/issue-37767.rs:22:7 --> $DIR/issue-37767.rs:22:7