Skip to content

Commit 179a718

Browse files
authored
Rollup merge of rust-lang#42826 - Yorwba:type-mismatch-same-absolute-paths, r=arielb1
Note different versions of same crate when absolute paths of different types match. The current check to address rust-lang#22750 only works when the paths of the mismatched types relative to the current crate are equal, but this does not always work if one of the types is only included through an indirect dependency. If reexports are involved, the indirectly included path can e.g. [contain private modules](rust-lang#22750 (comment)). This PR takes care of these cases by also comparing the *absolute* path, which is equal if the type hasn't moved in the module hierarchy between versions. A more coarse check would be to compare only the crate names instead of full paths, but that might lead to too many false positives. Additionally, I believe it would be helpful to show where the differing crates came from, i.e. the information in `rustc::middle::cstore::CrateSource`, but I'm not sure yet how to nicely display all of that, so I'm leaving it to a future PR.
2 parents c28cbfb + 8205c34 commit 179a718

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

src/librustc/infer/error_reporting/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
337337
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
338338
let exp_path = self.tcx.item_path_str(did1);
339339
let found_path = self.tcx.item_path_str(did2);
340+
let exp_abs_path = self.tcx.absolute_item_path_str(did1);
341+
let found_abs_path = self.tcx.absolute_item_path_str(did2);
340342
// We compare strings because DefPath can be different
341343
// for imported and non-imported crates
342-
if exp_path == found_path {
344+
if exp_path == found_path
345+
|| exp_abs_path == found_abs_path {
343346
let crate_name = self.tcx.sess.cstore.crate_name(did1.krate);
344347
err.span_note(sp, &format!("Perhaps two different versions \
345348
of crate `{}` are being used?",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-include ../tools.mk
2+
3+
all:
4+
# compile two different versions of crateA
5+
$(RUSTC) --crate-type=rlib crateA.rs -C metadata=-1 -C extra-filename=-1
6+
$(RUSTC) --crate-type=rlib crateA.rs -C metadata=-2 -C extra-filename=-2
7+
# make crateB depend on version 1 of crateA
8+
$(RUSTC) --crate-type=rlib crateB.rs --extern crateA=$(TMPDIR)/libcrateA-1.rlib
9+
# make crateC depend on version 2 of crateA
10+
$(RUSTC) crateC.rs --extern crateA=$(TMPDIR)/libcrateA-2.rlib 2>&1 | \
11+
grep -z \
12+
"mismatched types.*\
13+
crateB::try_foo(foo2);.*\
14+
expected struct \`crateA::foo::Foo\`, found struct \`crateA::Foo\`.*\
15+
different versions of crate \`crateA\`.*\
16+
mismatched types.*\
17+
crateB::try_bar(bar2);.*\
18+
expected trait \`crateA::bar::Bar\`, found trait \`crateA::Bar\`.*\
19+
different versions of crate \`crateA\`"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
mod foo {
12+
pub struct Foo;
13+
}
14+
15+
mod bar {
16+
pub trait Bar{}
17+
18+
pub fn bar() -> Box<Bar> {
19+
unimplemented!()
20+
}
21+
}
22+
23+
// This makes the publicly accessible path
24+
// differ from the internal one.
25+
pub use foo::Foo;
26+
pub use bar::{Bar, bar};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate crateA;
12+
13+
pub fn try_foo(x: crateA::Foo){}
14+
pub fn try_bar(x: Box<crateA::Bar>){}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This tests the extra note reported when a type error deals with
12+
// seemingly identical types.
13+
// The main use case of this error is when there are two crates
14+
// (generally different versions of the same crate) with the same name
15+
// causing a type mismatch.
16+
17+
// The test is nearly the same as the one in
18+
// compile-fail/type-mismatch-same-crate-name.rs
19+
// but deals with the case where one of the crates
20+
// is only introduced as an indirect dependency.
21+
// and the type is accessed via a reexport.
22+
// This is similar to how the error can be introduced
23+
// when using cargo's automatic dependency resolution.
24+
25+
extern crate crateA;
26+
27+
fn main() {
28+
let foo2 = crateA::Foo;
29+
let bar2 = crateA::bar();
30+
{
31+
extern crate crateB;
32+
crateB::try_foo(foo2);
33+
crateB::try_bar(bar2);
34+
}
35+
}

0 commit comments

Comments
 (0)