Skip to content

Commit eeb7283

Browse files
committed
Account for fully-qualified path case of conflicting crate versions
When encountering the following, mention the precense of conflicting crates: ``` error[E0599]: no function or associated item named `get_decoded` found for struct `HpkeConfig` in the current scope --> src/main.rs:7:17 | 7 | HpkeConfig::get_decoded(&foo); | ^^^^^^^^^^^ function or associated item not found in `HpkeConfig` | note: if you're trying to build a new `HpkeConfig`, consider using `HpkeConfig::new` which returns `HpkeConfig` --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/janus_messages-0.3.1/src/lib.rs:908:5 | 908 | / pub fn new( 909 | | id: HpkeConfigId, 910 | | kem_id: HpkeKemId, 911 | | kdf_id: HpkeKdfId, 912 | | aead_id: HpkeAeadId, 913 | | public_key: HpkePublicKey, 914 | | ) -> HpkeConfig { | |___________________^ note: there are multiple different versions of crate `prio` in the dependency graph --> src/main.rs:1:5 | 1 | use prio::codec::Decode; | ^^^^^^^^^^^^^^^^^^^ `prio` imported here doesn't correspond to the right crate version | ::: ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/prio-0.9.1/src/codec.rs:35:1 | 35 | pub trait Decode: Sized { | ----------------------- this is the trait that was imported | ::: ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/prio-0.10.3/src/codec.rs:35:1 | 35 | pub trait Decode: Sized { | ----------------------- this is the trait that is needed ... 43 | fn get_decoded(bytes: &[u8]) -> Result<Self, CodecError> { | -------------------------------------------------------- the method is available for `HpkeConfig` here help: there is an associated function `decode` with a similar name | 7 | HpkeConfig::decode(&foo); | ~~~~~~ ```
1 parent 5c427b4 commit eeb7283

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

Diff for: compiler/rustc_hir_typeck/src/method/suggest.rs

+40-12
Original file line numberDiff line numberDiff line change
@@ -3494,7 +3494,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34943494
if pick.autoderefs == 0 && !skip {
34953495
suggest = self.detect_and_explain_multiple_crate_versions(
34963496
err,
3497-
&pick.item,
3497+
pick.item.def_id,
3498+
pick.item.ident(self.tcx).span,
34983499
rcvr.hir_id.owner,
34993500
*rcvr_ty,
35003501
);
@@ -3684,6 +3685,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
36843685
}
36853686
}
36863687
}
3688+
3689+
if let SelfSource::QPath(ty) = source
3690+
&& !valid_out_of_scope_traits.is_empty()
3691+
&& let hir::TyKind::Path(path) = ty.kind
3692+
&& let hir::QPath::Resolved(_, path) = path
3693+
&& let Some(def_id) = path.res.opt_def_id()
3694+
&& let Some(assoc) = self
3695+
.tcx
3696+
.associated_items(valid_out_of_scope_traits[0])
3697+
.filter_by_name_unhygienic(item_name.name)
3698+
.next()
3699+
{
3700+
// See if the `Type::function(val)` where `function` wasn't found corresponds to a
3701+
// `Trait` that is imported directly, but `Type` came from a different version of the
3702+
// same crate.
3703+
let rcvr_ty = self.tcx.type_of(def_id).instantiate_identity();
3704+
suggest = self.detect_and_explain_multiple_crate_versions(
3705+
err,
3706+
assoc.def_id,
3707+
self.tcx.def_span(assoc.def_id),
3708+
ty.hir_id.owner,
3709+
rcvr_ty,
3710+
);
3711+
}
36873712
if suggest && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) {
36883713
return;
36893714
}
@@ -4052,42 +4077,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
40524077
fn detect_and_explain_multiple_crate_versions(
40534078
&self,
40544079
err: &mut Diag<'_>,
4055-
item: &ty::AssocItem,
4080+
item_def_id: DefId,
4081+
item_span: Span,
40564082
owner: hir::OwnerId,
40574083
rcvr_ty: Ty<'_>,
40584084
) -> bool {
4059-
let pick_name = self.tcx.crate_name(item.def_id.krate);
4085+
let pick_name = self.tcx.crate_name(item_def_id.krate);
4086+
let trait_did = self.tcx.parent(item_def_id);
4087+
let trait_name = self.tcx.item_name(trait_did);
40604088
if let Some(map) = self.tcx.in_scope_traits_map(owner) {
40614089
for trait_candidate in map.to_sorted_stable_ord().into_iter().flat_map(|v| v.1.iter()) {
4062-
let name = self.tcx.crate_name(trait_candidate.def_id.krate);
4063-
if trait_candidate.def_id.krate != item.def_id.krate && name == pick_name {
4090+
let crate_name = self.tcx.crate_name(trait_candidate.def_id.krate);
4091+
if trait_candidate.def_id.krate != item_def_id.krate && crate_name == pick_name {
40644092
let msg = format!(
4065-
"there are multiple different versions of crate `{name}` in the \
4093+
"there are multiple different versions of crate `{crate_name}` in the \
40664094
dependency graph",
40674095
);
4068-
let tdid = self.tcx.parent(item.def_id);
4069-
if self.tcx.item_name(trait_candidate.def_id) == self.tcx.item_name(tdid)
4096+
let candidate_name = self.tcx.item_name(trait_candidate.def_id);
4097+
if candidate_name == trait_name
40704098
&& let Some(def_id) = trait_candidate.import_ids.get(0)
40714099
{
40724100
let span = self.tcx.def_span(*def_id);
40734101
let mut multi_span: MultiSpan = span.into();
40744102
multi_span.push_span_label(
40754103
span,
40764104
format!(
4077-
"`{name}` imported here doesn't correspond to the right crate \
4078-
version",
4105+
"`{crate_name}` imported here doesn't correspond to the right \
4106+
crate version",
40794107
),
40804108
);
40814109
multi_span.push_span_label(
40824110
self.tcx.def_span(trait_candidate.def_id),
40834111
format!("this is the trait that was imported"),
40844112
);
40854113
multi_span.push_span_label(
4086-
self.tcx.def_span(tdid),
4114+
self.tcx.def_span(trait_did),
40874115
format!("this is the trait that is needed"),
40884116
);
40894117
multi_span.push_span_label(
4090-
item.ident(self.tcx).span,
4118+
item_span,
40914119
format!("the method is available for `{rcvr_ty}` here"),
40924120
);
40934121
err.span_note(multi_span, msg);

0 commit comments

Comments
 (0)