Skip to content

Commit

Permalink
Account for fully-qualified path case of conflicting crate versions
Browse files Browse the repository at this point in the history
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);
    |                 ~~~~~~
```
  • Loading branch information
estebank committed Aug 7, 2024
1 parent 92f08dd commit d03d9a2
Showing 1 changed file with 40 additions and 12 deletions.
52 changes: 40 additions & 12 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3495,7 +3495,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if pick.autoderefs == 0 && !skip {
suggest = self.detect_and_explain_multiple_crate_versions(
err,
&pick.item,
pick.item.def_id,
pick.item.ident(self.tcx).span,
rcvr.hir_id.owner,
*rcvr_ty,
);
Expand Down Expand Up @@ -3685,6 +3686,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}

if let SelfSource::QPath(ty) = source
&& !valid_out_of_scope_traits.is_empty()
&& let hir::TyKind::Path(path) = ty.kind
&& let hir::QPath::Resolved(_, path) = path
&& let Some(def_id) = path.res.opt_def_id()
&& let Some(assoc) = self
.tcx
.associated_items(valid_out_of_scope_traits[0])
.filter_by_name_unhygienic(item_name.name)
.next()
{
// See if the `Type::function(val)` where `function` wasn't found corresponds to a
// `Trait` that is imported directly, but `Type` came from a different version of the
// same crate.
let rcvr_ty = self.tcx.type_of(def_id).instantiate_identity();
suggest = self.detect_and_explain_multiple_crate_versions(
err,
assoc.def_id,
self.tcx.def_span(assoc.def_id),
ty.hir_id.owner,
rcvr_ty,
);
}
if suggest && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) {
return;
}
Expand Down Expand Up @@ -4053,42 +4078,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn detect_and_explain_multiple_crate_versions(
&self,
err: &mut Diag<'_>,
item: &ty::AssocItem,
item_def_id: DefId,
item_span: Span,
owner: hir::OwnerId,
rcvr_ty: Ty<'_>,
) -> bool {
let pick_name = self.tcx.crate_name(item.def_id.krate);
let pick_name = self.tcx.crate_name(item_def_id.krate);
let trait_did = self.tcx.parent(item_def_id);
let trait_name = self.tcx.item_name(trait_did);
if let Some(map) = self.tcx.in_scope_traits_map(owner) {
for trait_candidate in map.to_sorted_stable_ord().into_iter().flat_map(|v| v.1.iter()) {
let name = self.tcx.crate_name(trait_candidate.def_id.krate);
if trait_candidate.def_id.krate != item.def_id.krate && name == pick_name {
let crate_name = self.tcx.crate_name(trait_candidate.def_id.krate);
if trait_candidate.def_id.krate != item_def_id.krate && crate_name == pick_name {
let msg = format!(
"there are multiple different versions of crate `{name}` in the \
"there are multiple different versions of crate `{crate_name}` in the \
dependency graph",
);
let tdid = self.tcx.parent(item.def_id);
if self.tcx.item_name(trait_candidate.def_id) == self.tcx.item_name(tdid)
let candidate_name = self.tcx.item_name(trait_candidate.def_id);
if candidate_name == trait_name
&& let Some(def_id) = trait_candidate.import_ids.get(0)
{
let span = self.tcx.def_span(*def_id);
let mut multi_span: MultiSpan = span.into();
multi_span.push_span_label(
span,
format!(
"`{name}` imported here doesn't correspond to the right crate \
version",
"`{crate_name}` imported here doesn't correspond to the right \
crate version",
),
);
multi_span.push_span_label(
self.tcx.def_span(trait_candidate.def_id),
format!("this is the trait that was imported"),
);
multi_span.push_span_label(
self.tcx.def_span(tdid),
self.tcx.def_span(trait_did),
format!("this is the trait that is needed"),
);
multi_span.push_span_label(
item.ident(self.tcx).span,
item_span,
format!("the method is available for `{rcvr_ty}` here"),
);
err.span_note(multi_span, msg);
Expand Down

0 comments on commit d03d9a2

Please sign in to comment.