Rework print_disambiguation_help

This commit is contained in:
Michael Goulet 2023-11-07 05:22:20 +00:00
parent 88a37acb26
commit 0add056dee
8 changed files with 93 additions and 113 deletions

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 _;
@ -1320,39 +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,
self_source,
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) => {
@ -1374,25 +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,
self_source,
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);
} }
} }
} }
@ -3263,59 +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<&'tcx [hir::Expr<'tcx>]>,
source: SelfSource<'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 matches!(kind, ty::AssocKind::Fn) if matches!(item.kind, ty::AssocKind::Fn)
&& let SelfSource::MethodCall(receiver) = source && let SelfSource::MethodCall(receiver) = source
&& let Some(args) = args && 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

@ -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