Skip to content

Commit d03d9a2

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 92f08dd commit d03d9a2

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+40-12
Original file line numberDiff line numberDiff line change
@@ -3495,7 +3495,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34953495
if pick.autoderefs == 0 && !skip {
34963496
suggest = self.detect_and_explain_multiple_crate_versions(
34973497
err,
3498-
&pick.item,
3498+
pick.item.def_id,
3499+
pick.item.ident(self.tcx).span,
34993500
rcvr.hir_id.owner,
35003501
*rcvr_ty,
35013502
);
@@ -3685,6 +3686,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
36853686
}
36863687
}
36873688
}
3689+
3690+
if let SelfSource::QPath(ty) = source
3691+
&& !valid_out_of_scope_traits.is_empty()
3692+
&& let hir::TyKind::Path(path) = ty.kind
3693+
&& let hir::QPath::Resolved(_, path) = path
3694+
&& let Some(def_id) = path.res.opt_def_id()
3695+
&& let Some(assoc) = self
3696+
.tcx
3697+
.associated_items(valid_out_of_scope_traits[0])
3698+
.filter_by_name_unhygienic(item_name.name)
3699+
.next()
3700+
{
3701+
// See if the `Type::function(val)` where `function` wasn't found corresponds to a
3702+
// `Trait` that is imported directly, but `Type` came from a different version of the
3703+
// same crate.
3704+
let rcvr_ty = self.tcx.type_of(def_id).instantiate_identity();
3705+
suggest = self.detect_and_explain_multiple_crate_versions(
3706+
err,
3707+
assoc.def_id,
3708+
self.tcx.def_span(assoc.def_id),
3709+
ty.hir_id.owner,
3710+
rcvr_ty,
3711+
);
3712+
}
36883713
if suggest && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) {
36893714
return;
36903715
}
@@ -4053,42 +4078,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
40534078
fn detect_and_explain_multiple_crate_versions(
40544079
&self,
40554080
err: &mut Diag<'_>,
4056-
item: &ty::AssocItem,
4081+
item_def_id: DefId,
4082+
item_span: Span,
40574083
owner: hir::OwnerId,
40584084
rcvr_ty: Ty<'_>,
40594085
) -> bool {
4060-
let pick_name = self.tcx.crate_name(item.def_id.krate);
4086+
let pick_name = self.tcx.crate_name(item_def_id.krate);
4087+
let trait_did = self.tcx.parent(item_def_id);
4088+
let trait_name = self.tcx.item_name(trait_did);
40614089
if let Some(map) = self.tcx.in_scope_traits_map(owner) {
40624090
for trait_candidate in map.to_sorted_stable_ord().into_iter().flat_map(|v| v.1.iter()) {
4063-
let name = self.tcx.crate_name(trait_candidate.def_id.krate);
4064-
if trait_candidate.def_id.krate != item.def_id.krate && name == pick_name {
4091+
let crate_name = self.tcx.crate_name(trait_candidate.def_id.krate);
4092+
if trait_candidate.def_id.krate != item_def_id.krate && crate_name == pick_name {
40654093
let msg = format!(
4066-
"there are multiple different versions of crate `{name}` in the \
4094+
"there are multiple different versions of crate `{crate_name}` in the \
40674095
dependency graph",
40684096
);
4069-
let tdid = self.tcx.parent(item.def_id);
4070-
if self.tcx.item_name(trait_candidate.def_id) == self.tcx.item_name(tdid)
4097+
let candidate_name = self.tcx.item_name(trait_candidate.def_id);
4098+
if candidate_name == trait_name
40714099
&& let Some(def_id) = trait_candidate.import_ids.get(0)
40724100
{
40734101
let span = self.tcx.def_span(*def_id);
40744102
let mut multi_span: MultiSpan = span.into();
40754103
multi_span.push_span_label(
40764104
span,
40774105
format!(
4078-
"`{name}` imported here doesn't correspond to the right crate \
4079-
version",
4106+
"`{crate_name}` imported here doesn't correspond to the right \
4107+
crate version",
40804108
),
40814109
);
40824110
multi_span.push_span_label(
40834111
self.tcx.def_span(trait_candidate.def_id),
40844112
format!("this is the trait that was imported"),
40854113
);
40864114
multi_span.push_span_label(
4087-
self.tcx.def_span(tdid),
4115+
self.tcx.def_span(trait_did),
40884116
format!("this is the trait that is needed"),
40894117
);
40904118
multi_span.push_span_label(
4091-
item.ident(self.tcx).span,
4119+
item_span,
40924120
format!("the method is available for `{rcvr_ty}` here"),
40934121
);
40944122
err.span_note(multi_span, msg);

0 commit comments

Comments
 (0)