Skip to content

Commit 7be6ada

Browse files
authored
Rollup merge of #149001 - rperier:untruthful_multiple_different_versions_of_crate, r=lcnr
Fix false positive of "multiple different versions of crate X in the dependency graph" cc #148892
2 parents cdb678c + b25336b commit 7be6ada

File tree

5 files changed

+77
-14
lines changed

5 files changed

+77
-14
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::{fmt, iter};
1212
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
1313
use rustc_data_structures::unord::UnordSet;
1414
use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
15-
use rustc_hir::def_id::{DefId, LocalDefId};
15+
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
1616
use rustc_hir::intravisit::Visitor;
1717
use rustc_hir::{self as hir, AmbigArg};
1818
use rustc_infer::traits::solve::Goal;
@@ -22,7 +22,8 @@ use rustc_infer::traits::{
2222
};
2323
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
2424
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
25-
use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span, Symbol};
25+
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
26+
use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span};
2627
use tracing::{info, instrument};
2728

2829
pub use self::overflow::*;
@@ -353,14 +354,37 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
353354
}
354355
}
355356

356-
fn get_extern_crate_renamed_symbol(&self, trait_def_id: DefId) -> Option<Symbol> {
357-
if !trait_def_id.is_local()
358-
&& let Some(data) = self.tcx.extern_crate(trait_def_id.krate)
359-
&& let rustc_session::cstore::ExternCrateSource::Extern(def_id) = data.src
360-
{
361-
self.tcx.opt_item_name(def_id)
362-
} else {
363-
None
357+
/// If the crates of `expected_def_id` and `trait_def_id` are imported as extern crate
358+
/// under the same name (`extern crate foo as a` and `extern crate bar as a`) returns true,
359+
/// otherwise returns false.
360+
fn extern_crates_with_the_same_name(
361+
&self,
362+
expected_def_id: DefId,
363+
trait_def_id: DefId,
364+
) -> bool {
365+
if expected_def_id.is_local() || trait_def_id.is_local() {
366+
return false;
367+
}
368+
// We only compare direct dependencies of the current crate, so it avoids unnecessary
369+
// processing and excludes indirect dependencies, like `std` or `core`. In such a case
370+
// both would be imported under the same name `std`.
371+
match (
372+
self.tcx.extern_crate(expected_def_id.krate),
373+
self.tcx.extern_crate(trait_def_id.krate),
374+
) {
375+
(
376+
Some(ExternCrate {
377+
src: ExternCrateSource::Extern(expected_def_id),
378+
dependency_of: LOCAL_CRATE,
379+
..
380+
}),
381+
Some(ExternCrate {
382+
src: ExternCrateSource::Extern(trait_def_id),
383+
dependency_of: LOCAL_CRATE,
384+
..
385+
}),
386+
) => self.tcx.item_name(expected_def_id) == self.tcx.item_name(trait_def_id),
387+
_ => false,
364388
}
365389
}
366390

@@ -377,13 +401,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
377401
{
378402
let krate = self.tcx.crate_name(expected_did.krate);
379403
let name = self.tcx.item_name(expected_did);
380-
let locally_renamed_krate = self
381-
.get_extern_crate_renamed_symbol(expected_did)
382-
.map_or(None, |s| if s != krate { Some(s) } else { None });
383404
let definitions_with_same_path: UnordSet<_> = found_dids
384405
.filter(|def_id| {
385406
def_id.krate != expected_did.krate
386-
&& (locally_renamed_krate == self.get_extern_crate_renamed_symbol(*def_id)
407+
&& (self.extern_crates_with_the_same_name(expected_did, *def_id)
387408
|| self.tcx.crate_name(def_id.krate) == krate)
388409
&& self.tcx.item_name(def_id) == name
389410
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//@ aux-crate:crate2=crate2.rs
2+
3+
pub trait Trait {}
4+
5+
pub fn foo(_arg: impl Trait) {}
6+
7+
pub fn bar(_arg: impl crate2::Trait) {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub trait Trait {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test that we do not report false positives of a crate as being found multiple times in the
2+
// dependency graph with different versions, when this crate is only present once. In this test,
3+
// this was happening for `crate1` when two different crates in the dependencies were imported
4+
// as ExternCrateSource::Path.
5+
// Issue #148892.
6+
//@ aux-crate:crate1=crate1.rs
7+
8+
struct MyStruct; //~ HELP the trait `Trait` is not implemented for `MyStruct`
9+
10+
fn main() {
11+
crate1::foo(MyStruct); //~ ERROR the trait bound `MyStruct: Trait` is not satisfied
12+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: the trait bound `MyStruct: Trait` is not satisfied
2+
--> $DIR/wrong-multiple-different-versions-of-a-crate.rs:11:17
3+
|
4+
LL | crate1::foo(MyStruct);
5+
| ----------- ^^^^^^^^ unsatisfied trait bound
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
help: the trait `Trait` is not implemented for `MyStruct`
10+
--> $DIR/wrong-multiple-different-versions-of-a-crate.rs:8:1
11+
|
12+
LL | struct MyStruct;
13+
| ^^^^^^^^^^^^^^^
14+
note: required by a bound in `foo`
15+
--> $DIR/auxiliary/crate1.rs:5:23
16+
|
17+
LL | pub fn foo(_arg: impl Trait) {}
18+
| ^^^^^ required by this bound in `foo`
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)