Skip to content

Commit

Permalink
Rollup merge of rust-lang#42826 - Yorwba:type-mismatch-same-absolute-…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
Mark-Simulacrum authored Jul 12, 2017
2 parents 500518a + 21bb60a commit 0926f9b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
let exp_path = self.tcx.item_path_str(did1);
let found_path = self.tcx.item_path_str(did2);
let exp_abs_path = self.tcx.absolute_item_path_str(did1);
let found_abs_path = self.tcx.absolute_item_path_str(did2);
// We compare strings because DefPath can be different
// for imported and non-imported crates
if exp_path == found_path {
if exp_path == found_path
|| exp_abs_path == found_abs_path {
let crate_name = self.tcx.sess.cstore.crate_name(did1.krate);
err.span_note(sp, &format!("Perhaps two different versions \
of crate `{}` are being used?",
Expand Down
19 changes: 19 additions & 0 deletions src/test/run-make/type-mismatch-same-crate-name/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-include ../tools.mk

all:
# compile two different versions of crateA
$(RUSTC) --crate-type=rlib crateA.rs -C metadata=-1 -C extra-filename=-1
$(RUSTC) --crate-type=rlib crateA.rs -C metadata=-2 -C extra-filename=-2
# make crateB depend on version 1 of crateA
$(RUSTC) --crate-type=rlib crateB.rs --extern crateA=$(TMPDIR)/libcrateA-1.rlib
# make crateC depend on version 2 of crateA
$(RUSTC) crateC.rs --extern crateA=$(TMPDIR)/libcrateA-2.rlib 2>&1 | \
tr -d '\r\n' | grep \
"mismatched types.*\
crateB::try_foo(foo2);.*\
expected struct \`crateA::foo::Foo\`, found struct \`crateA::Foo\`.*\
different versions of crate \`crateA\`.*\
mismatched types.*\
crateB::try_bar(bar2);.*\
expected trait \`crateA::bar::Bar\`, found trait \`crateA::Bar\`.*\
different versions of crate \`crateA\`"
26 changes: 26 additions & 0 deletions src/test/run-make/type-mismatch-same-crate-name/crateA.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod foo {
pub struct Foo;
}

mod bar {
pub trait Bar{}

pub fn bar() -> Box<Bar> {
unimplemented!()
}
}

// This makes the publicly accessible path
// differ from the internal one.
pub use foo::Foo;
pub use bar::{Bar, bar};
14 changes: 14 additions & 0 deletions src/test/run-make/type-mismatch-same-crate-name/crateB.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate crateA;

pub fn try_foo(x: crateA::Foo){}
pub fn try_bar(x: Box<crateA::Bar>){}
35 changes: 35 additions & 0 deletions src/test/run-make/type-mismatch-same-crate-name/crateC.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This tests the extra note reported when a type error deals with
// seemingly identical types.
// The main use case of this error is when there are two crates
// (generally different versions of the same crate) with the same name
// causing a type mismatch.

// The test is nearly the same as the one in
// compile-fail/type-mismatch-same-crate-name.rs
// but deals with the case where one of the crates
// is only introduced as an indirect dependency.
// and the type is accessed via a reexport.
// This is similar to how the error can be introduced
// when using cargo's automatic dependency resolution.

extern crate crateA;

fn main() {
let foo2 = crateA::Foo;
let bar2 = crateA::bar();
{
extern crate crateB;
crateB::try_foo(foo2);
crateB::try_bar(bar2);
}
}

0 comments on commit 0926f9b

Please sign in to comment.