Add more info on type/trait mismatches for different crate versions
When encountering a type or trait mismatch for two types coming from two different crates with the same name, detect if it is either mixing two types/traits from the same crate on different versions: ``` error[E0308]: mismatched types --> replaced | LL | do_something_type(Type); | ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type` | | | arguments to this function are incorrect | note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same --> replaced | LL | pub struct Type(pub i32); | ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type` | ::: replaced | LL | pub struct Type; | ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type` | ::: replaced | LL | extern crate dep_2_reexport; | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` LL | extern crate dependency; | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> replaced | LL | pub fn do_something_type(_: Type) {} | ^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> replaced | LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>); | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2` | | | arguments to this function are incorrect | note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same --> replaced | LL | pub trait Trait2 {} | ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2` | ::: replaced | LL | pub trait Trait2 {} | ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2` | ::: replaced | LL | extern crate dep_2_reexport; | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` LL | extern crate dependency; | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate = help: you can use `cargo tree` to explore your dependency tree note: function defined here --> replaced | LL | pub fn do_something_trait(_: Box<dyn Trait2>) {} | ^^^^^^^^^^^^^^^^^^ ``` or if it is different crates that were renamed to the same name: ``` error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:21:20 | LL | a::try_foo(foo2); | ---------- ^^^^ expected `main:🅰️:Foo`, found a different `main:🅰️:Foo` | | | arguments to this function are incorrect | note: two types coming from two different crates are different types even if they look the same --> $DIR/auxiliary/crate_a2.rs:1:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo` | ::: $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo` | ::: $DIR/type-mismatch-same-crate-name.rs:13:17 | LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; | --------------------------- one type comes from crate `crate_a2` is used here, which is renamed locally to `a` ... LL | extern crate crate_a1 as a; | --------------------------- one type comes from crate `crate_a1` is used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:27:20 | LL | a::try_bar(bar2); | ---------- ^^^^ expected trait `main:🅰️:Bar`, found a different trait `main:🅰️:Bar` | | | arguments to this function are incorrect | note: two types coming from two different crates are different types even if they look the same --> $DIR/auxiliary/crate_a2.rs:3:1 | LL | pub trait Bar {} | ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar` | ::: $DIR/auxiliary/crate_a1.rs:3:1 | LL | pub trait Bar {} | ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar` | ::: $DIR/type-mismatch-same-crate-name.rs:13:17 | LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; | --------------------------- one trait comes from crate `crate_a2` is used here, which is renamed locally to `a` ... LL | extern crate crate_a1 as a; | --------------------------- one trait comes from crate `crate_a1` is used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 | LL | pub fn try_bar(x: Box<Bar>){} | ^^^^^^^ ``` This new output unifies the E0308 errors detail with the pre-existing E0277 errors, and better differentiates the "`extern crate` renamed" and "same crate, different versions" cases.
This commit is contained in:
parent
8dc83770f7
commit
16bf7223ea
15 changed files with 281 additions and 76 deletions
|
@ -52,7 +52,9 @@ use std::{cmp, fmt, iter};
|
||||||
|
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize};
|
use rustc_errors::{
|
||||||
|
Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize,
|
||||||
|
};
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
|
@ -67,6 +69,7 @@ use rustc_middle::ty::{
|
||||||
self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
||||||
TypeVisitableExt,
|
TypeVisitableExt,
|
||||||
};
|
};
|
||||||
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
use rustc_span::{BytePos, DesugaringKind, Pos, Span, sym};
|
use rustc_span::{BytePos, DesugaringKind, Pos, Span, sym};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
@ -211,7 +214,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a note if the types come from similarly named crates
|
/// Adds a note if the types come from similarly named crates
|
||||||
fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) {
|
fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) -> bool {
|
||||||
|
// FIXME(estebank): unify with `report_similar_impl_candidates`. The message is similar,
|
||||||
|
// even if the logic needed to detect the case is very different.
|
||||||
use hir::def_id::CrateNum;
|
use hir::def_id::CrateNum;
|
||||||
use rustc_hir::definitions::DisambiguatedDefPathData;
|
use rustc_hir::definitions::DisambiguatedDefPathData;
|
||||||
use ty::GenericArg;
|
use ty::GenericArg;
|
||||||
|
@ -285,7 +290,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId| {
|
let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId, ty: &str| -> bool {
|
||||||
// Only report definitions from different crates. If both definitions
|
// Only report definitions from different crates. If both definitions
|
||||||
// are from a local module we could have false positives, e.g.
|
// are from a local module we could have false positives, e.g.
|
||||||
// let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
|
// let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
|
||||||
|
@ -297,24 +302,112 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// We compare strings because DefPath can be different
|
// We compare strings because DefPath can be different
|
||||||
// for imported and non-imported crates
|
// for imported and non-imported crates
|
||||||
|
let expected_str = self.tcx.def_path_str(did1);
|
||||||
|
let found_str = self.tcx.def_path_str(did2);
|
||||||
|
let Ok(expected_abs) = abs_path(did1) else { return false };
|
||||||
|
let Ok(found_abs) = abs_path(did2) else { return false };
|
||||||
let same_path = || -> Result<_, PrintError> {
|
let same_path = || -> Result<_, PrintError> {
|
||||||
Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
|
Ok(expected_str == found_str || expected_abs == found_abs)
|
||||||
|| abs_path(did1)? == abs_path(did2)?)
|
};
|
||||||
|
// We want to use as unique a type path as possible. If both types are "locally
|
||||||
|
// known" by the same name, we use the "absolute path" which uses the original
|
||||||
|
// crate name instead.
|
||||||
|
let (expected, found) = if expected_str == found_str {
|
||||||
|
(expected_abs.join("::"), found_abs.join("::"))
|
||||||
|
} else {
|
||||||
|
(expected_str.clone(), found_str.clone())
|
||||||
};
|
};
|
||||||
if same_path().unwrap_or(false) {
|
if same_path().unwrap_or(false) {
|
||||||
let crate_name = self.tcx.crate_name(did1.krate);
|
// We've displayed "expected `a::b`, found `a::b`". We add context to
|
||||||
let msg = if did1.is_local() || did2.is_local() {
|
// differentiate the different cases where that might happen.
|
||||||
|
let expected_crate_name = self.tcx.crate_name(did1.krate);
|
||||||
|
let found_crate_name = self.tcx.crate_name(did2.krate);
|
||||||
|
let same_crate = expected_crate_name == found_crate_name;
|
||||||
|
let expected_sp = self.tcx.def_span(did1);
|
||||||
|
let found_sp = self.tcx.def_span(did2);
|
||||||
|
|
||||||
|
let both_direct_dependencies = if !did1.is_local()
|
||||||
|
&& !did2.is_local()
|
||||||
|
&& let Some(data1) = self.tcx.extern_crate(did1.krate)
|
||||||
|
&& let Some(data2) = self.tcx.extern_crate(did2.krate)
|
||||||
|
&& data1.dependency_of == LOCAL_CRATE
|
||||||
|
&& data2.dependency_of == LOCAL_CRATE
|
||||||
|
{
|
||||||
|
// If both crates are directly depended on, we don't want to mention that
|
||||||
|
// in the final message, as it is redundant wording.
|
||||||
|
// We skip the case of semver trick, where one version of the local crate
|
||||||
|
// depends on another version of itself by checking that both crates at play
|
||||||
|
// are not the current one.
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut span: MultiSpan = vec![expected_sp, found_sp].into();
|
||||||
|
span.push_span_label(
|
||||||
|
self.tcx.def_span(did1),
|
||||||
|
format!("this is the expected {ty} `{expected}`"),
|
||||||
|
);
|
||||||
|
span.push_span_label(
|
||||||
|
self.tcx.def_span(did2),
|
||||||
|
format!("this is the found {ty} `{found}`"),
|
||||||
|
);
|
||||||
|
for def_id in [did1, did2] {
|
||||||
|
let crate_name = self.tcx.crate_name(def_id.krate);
|
||||||
|
if !def_id.is_local()
|
||||||
|
&& let Some(data) = self.tcx.extern_crate(def_id.krate)
|
||||||
|
{
|
||||||
|
let descr = if same_crate {
|
||||||
|
"one version of".to_string()
|
||||||
|
} else {
|
||||||
|
format!("one {ty} comes from")
|
||||||
|
};
|
||||||
|
let dependency = if both_direct_dependencies {
|
||||||
|
if let rustc_session::cstore::ExternCrateSource::Extern(def_id) =
|
||||||
|
data.src
|
||||||
|
&& let Some(name) = self.tcx.opt_item_name(def_id)
|
||||||
|
{
|
||||||
|
format!(", which is renamed locally to `{name}`")
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
} else if data.dependency_of == LOCAL_CRATE {
|
||||||
|
", as a direct dependency of the current crate".to_string()
|
||||||
|
} else {
|
||||||
|
let dep = self.tcx.crate_name(data.dependency_of);
|
||||||
|
format!(", as a dependency of crate `{dep}`")
|
||||||
|
};
|
||||||
|
span.push_span_label(
|
||||||
|
data.span,
|
||||||
|
format!("{descr} crate `{crate_name}` used here{dependency}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let msg = if (did1.is_local() || did2.is_local()) && same_crate {
|
||||||
format!(
|
format!(
|
||||||
"the crate `{crate_name}` is compiled multiple times, possibly with different configurations"
|
"the crate `{expected_crate_name}` is compiled multiple times, \
|
||||||
|
possibly with different configurations",
|
||||||
|
)
|
||||||
|
} else if same_crate {
|
||||||
|
format!(
|
||||||
|
"two different versions of crate `{expected_crate_name}` are being \
|
||||||
|
used; two types coming from two different versions of the same crate \
|
||||||
|
are different types even if they look the same",
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"perhaps two different versions of crate `{crate_name}` are being used?"
|
"two types coming from two different crates are different types even \
|
||||||
|
if they look the same",
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
err.note(msg);
|
err.span_note(span, msg);
|
||||||
|
if same_crate {
|
||||||
|
err.help("you can use `cargo tree` to explore your dependency tree");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
false
|
||||||
};
|
};
|
||||||
match terr {
|
match terr {
|
||||||
TypeError::Sorts(ref exp_found) => {
|
TypeError::Sorts(ref exp_found) => {
|
||||||
|
@ -323,14 +416,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
|
if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
|
||||||
(exp_found.expected.kind(), exp_found.found.kind())
|
(exp_found.expected.kind(), exp_found.found.kind())
|
||||||
{
|
{
|
||||||
report_path_match(err, exp_adt.did(), found_adt.did());
|
return report_path_match(err, exp_adt.did(), found_adt.did(), "type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeError::Traits(ref exp_found) => {
|
TypeError::Traits(ref exp_found) => {
|
||||||
report_path_match(err, exp_found.expected, exp_found.found);
|
return report_path_match(err, exp_found.expected, exp_found.found, "trait");
|
||||||
}
|
}
|
||||||
_ => (), // FIXME(#22750) handle traits and stuff
|
_ => (), // FIXME(#22750) handle traits and stuff
|
||||||
}
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note_error_origin(
|
fn note_error_origin(
|
||||||
|
@ -1409,6 +1503,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
label_or_note(span, terr.to_string(self.tcx));
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.check_and_note_conflicting_crates(diag, terr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some((expected, found, path)) = expected_found {
|
if let Some((expected, found, path)) = expected_found {
|
||||||
let (expected_label, found_label, exp_found) = match exp_found {
|
let (expected_label, found_label, exp_found) = match exp_found {
|
||||||
Mismatch::Variable(ef) => (
|
Mismatch::Variable(ef) => (
|
||||||
|
@ -1470,15 +1568,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|prim: Ty<'tcx>, shadow: Ty<'tcx>, defid: DefId, diag: &mut Diag<'_>| {
|
|prim: Ty<'tcx>, shadow: Ty<'tcx>, defid: DefId, diag: &mut Diag<'_>| {
|
||||||
let name = shadow.sort_string(self.tcx);
|
let name = shadow.sort_string(self.tcx);
|
||||||
diag.note(format!(
|
diag.note(format!(
|
||||||
"{prim} and {name} have similar names, but are actually distinct types"
|
"`{prim}` and {name} have similar names, but are actually distinct types"
|
||||||
|
));
|
||||||
|
diag.note(format!(
|
||||||
|
"one `{prim}` is a primitive defined by the language",
|
||||||
));
|
));
|
||||||
diag.note(format!("{prim} is a primitive defined by the language"));
|
|
||||||
let def_span = self.tcx.def_span(defid);
|
let def_span = self.tcx.def_span(defid);
|
||||||
let msg = if defid.is_local() {
|
let msg = if defid.is_local() {
|
||||||
format!("{name} is defined in the current crate")
|
format!("the other {name} is defined in the current crate")
|
||||||
} else {
|
} else {
|
||||||
let crate_name = self.tcx.crate_name(defid.krate);
|
let crate_name = self.tcx.crate_name(defid.krate);
|
||||||
format!("{name} is defined in crate `{crate_name}`")
|
format!("the other {name} is defined in crate `{crate_name}`")
|
||||||
};
|
};
|
||||||
diag.span_note(def_span, msg);
|
diag.span_note(def_span, msg);
|
||||||
};
|
};
|
||||||
|
@ -1666,8 +1766,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.check_and_note_conflicting_crates(diag, terr);
|
|
||||||
|
|
||||||
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
|
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
|
||||||
if let Some(exp_found) = exp_found
|
if let Some(exp_found) = exp_found
|
||||||
&& let exp_found = TypeError::Sorts(exp_found)
|
&& let exp_found = TypeError::Sorts(exp_found)
|
||||||
|
|
|
@ -1745,9 +1745,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
data.span,
|
data.span,
|
||||||
format!(
|
format!("one version of crate `{crate_name}` used here, as a {dependency}"),
|
||||||
"one version of crate `{crate_name}` is used here, as a {dependency}"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
//@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies
|
//@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies
|
||||||
|
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
//[cfail2]~^ NOTE `Foo` is defined in the current crate
|
//[cfail2]~^ NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
|
||||||
//[cfail2]~| NOTE `Foo` is defined in the current crate
|
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
|
||||||
//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
|
//[cfail2]~| NOTE this is the expected type `Foo`
|
||||||
//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies`
|
//[cfail2]~| NOTE this is the expected type `circular_dependencies::Foo`
|
||||||
|
//[cfail2]~| NOTE this is the found type `Foo`
|
||||||
|
//[cfail2]~| NOTE this is the found type `circular_dependencies::Foo`
|
||||||
|
|
||||||
pub fn consume_foo(_: Foo) {}
|
pub fn consume_foo(_: Foo) {}
|
||||||
//[cfail2]~^ NOTE function defined here
|
//[cfail2]~^ NOTE function defined here
|
||||||
|
@ -24,14 +26,12 @@ fn test() {
|
||||||
//[cfail2]~^ ERROR mismatched types [E0308]
|
//[cfail2]~^ ERROR mismatched types [E0308]
|
||||||
//[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo`
|
//[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo`
|
||||||
//[cfail2]~| NOTE arguments to this function are incorrect
|
//[cfail2]~| NOTE arguments to this function are incorrect
|
||||||
//[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types
|
|
||||||
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
|
|
||||||
//[cfail2]~| NOTE function defined here
|
//[cfail2]~| NOTE function defined here
|
||||||
|
//[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux`
|
||||||
|
//[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux`
|
||||||
|
|
||||||
consume_foo(aux::produce_foo());
|
consume_foo(aux::produce_foo());
|
||||||
//[cfail2]~^ ERROR mismatched types [E0308]
|
//[cfail2]~^ ERROR mismatched types [E0308]
|
||||||
//[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo`
|
//[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo`
|
||||||
//[cfail2]~| NOTE arguments to this function are incorrect
|
//[cfail2]~| NOTE arguments to this function are incorrect
|
||||||
//[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types
|
|
||||||
//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ note: there are multiple different versions of crate `foo` in the dependency gra
|
||||||
--> foo-current.rs:7:1
|
--> foo-current.rs:7:1
|
||||||
|
|
|
|
||||||
4 | extern crate foo;
|
4 | extern crate foo;
|
||||||
| ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate
|
| ----------------- one version of crate `foo` used here, as a direct dependency of the current crate
|
||||||
5 |
|
5 |
|
||||||
6 | pub struct Struct;
|
6 | pub struct Struct;
|
||||||
| ----------------- this type implements the required trait
|
| ----------------- this type implements the required trait
|
||||||
|
|
|
@ -5,8 +5,11 @@ pub trait Trait {
|
||||||
fn foo(&self);
|
fn foo(&self);
|
||||||
fn bar();
|
fn bar();
|
||||||
}
|
}
|
||||||
|
pub trait Trait2 {}
|
||||||
impl Trait for Type {
|
impl Trait for Type {
|
||||||
fn foo(&self) {}
|
fn foo(&self) {}
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
}
|
}
|
||||||
pub fn do_something<X: Trait>(_: X) {}
|
pub fn do_something<X: Trait>(_: X) {}
|
||||||
|
pub fn do_something_type(_: Type) {}
|
||||||
|
pub fn do_something_trait(_: Box<dyn Trait2>) {}
|
||||||
|
|
|
@ -5,8 +5,12 @@ pub trait Trait {
|
||||||
fn foo(&self);
|
fn foo(&self);
|
||||||
fn bar();
|
fn bar();
|
||||||
}
|
}
|
||||||
|
pub trait Trait2 {}
|
||||||
|
impl Trait2 for Type {}
|
||||||
impl Trait for Type {
|
impl Trait for Type {
|
||||||
fn foo(&self) {}
|
fn foo(&self) {}
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
}
|
}
|
||||||
pub fn do_something<X: Trait>(_: X) {}
|
pub fn do_something<X: Trait>(_: X) {}
|
||||||
|
pub fn do_something_type(_: Type) {}
|
||||||
|
pub fn do_something_trait(_: Box<dyn Trait2>) {}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
extern crate dependency;
|
extern crate dependency;
|
||||||
pub use dependency::Type;
|
pub use dependency::{Trait2, Type, do_something_trait, do_something_type};
|
||||||
pub struct OtherType;
|
pub struct OtherType;
|
||||||
impl dependency::Trait for OtherType {
|
impl dependency::Trait for OtherType {
|
||||||
fn foo(&self) {}
|
fn foo(&self) {}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
extern crate dep_2_reexport;
|
extern crate dep_2_reexport;
|
||||||
extern crate dependency;
|
extern crate dependency;
|
||||||
use dep_2_reexport::{OtherType, Type};
|
use dep_2_reexport::{OtherType, Trait2, Type};
|
||||||
use dependency::{Trait, do_something};
|
use dependency::{Trait, do_something, do_something_trait, do_something_type};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
do_something(Type);
|
do_something(Type);
|
||||||
Type.foo();
|
Type.foo();
|
||||||
Type::bar();
|
Type::bar();
|
||||||
do_something(OtherType);
|
do_something(OtherType);
|
||||||
|
do_something_type(Type);
|
||||||
|
do_something_trait(Box::new(Type) as Box<dyn Trait2>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ LL | pub trait Trait {
|
||||||
::: replaced
|
::: replaced
|
||||||
|
|
|
|
||||||
LL | extern crate dep_2_reexport;
|
LL | extern crate dep_2_reexport;
|
||||||
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
|
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
|
||||||
LL | extern crate dependency;
|
LL | extern crate dependency;
|
||||||
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
|
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
|
||||||
|
|
|
|
||||||
::: replaced
|
::: replaced
|
||||||
|
|
|
|
||||||
|
@ -51,7 +51,7 @@ LL | fn foo(&self);
|
||||||
|
|
|
|
||||||
::: replaced
|
::: replaced
|
||||||
|
|
|
|
||||||
LL | use dependency::{Trait, do_something};
|
LL | use dependency::{Trait, do_something, do_something_trait, do_something_type};
|
||||||
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
|
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
|
||||||
|
|
|
|
||||||
::: replaced
|
::: replaced
|
||||||
|
@ -76,7 +76,7 @@ LL | fn bar();
|
||||||
|
|
|
|
||||||
::: replaced
|
::: replaced
|
||||||
|
|
|
|
||||||
LL | use dependency::{Trait, do_something};
|
LL | use dependency::{Trait, do_something, do_something_trait, do_something_type};
|
||||||
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
|
| ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
|
||||||
|
|
|
|
||||||
::: replaced
|
::: replaced
|
||||||
|
@ -101,9 +101,9 @@ LL | pub trait Trait {
|
||||||
::: replaced
|
::: replaced
|
||||||
|
|
|
|
||||||
LL | extern crate dep_2_reexport;
|
LL | extern crate dep_2_reexport;
|
||||||
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
|
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
|
||||||
LL | extern crate dependency;
|
LL | extern crate dependency;
|
||||||
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
|
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
|
||||||
|
|
|
|
||||||
::: replaced
|
::: replaced
|
||||||
|
|
|
|
||||||
|
@ -121,7 +121,71 @@ note: required by a bound in `do_something`
|
||||||
LL | pub fn do_something<X: Trait>(_: X) {}
|
LL | pub fn do_something<X: Trait>(_: X) {}
|
||||||
| ^^^^^ required by this bound in `do_something`
|
| ^^^^^ required by this bound in `do_something`
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> replaced
|
||||||
|
|
|
||||||
|
LL | do_something_type(Type);
|
||||||
|
| ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type`
|
||||||
|
| |
|
||||||
|
| arguments to this function are incorrect
|
||||||
|
|
|
||||||
|
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
|
||||||
|
--> replaced
|
||||||
|
|
|
||||||
|
LL | pub struct Type(pub i32);
|
||||||
|
| ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type`
|
||||||
|
|
|
||||||
|
::: replaced
|
||||||
|
|
|
||||||
|
LL | pub struct Type;
|
||||||
|
| ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type`
|
||||||
|
|
|
||||||
|
::: replaced
|
||||||
|
|
|
||||||
|
LL | extern crate dep_2_reexport;
|
||||||
|
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
|
||||||
|
LL | extern crate dependency;
|
||||||
|
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
|
||||||
|
= help: you can use `cargo tree` to explore your dependency tree
|
||||||
|
note: function defined here
|
||||||
|
--> replaced
|
||||||
|
|
|
||||||
|
LL | pub fn do_something_type(_: Type) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0599.
|
error[E0308]: mismatched types
|
||||||
|
--> replaced
|
||||||
|
|
|
||||||
|
LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>);
|
||||||
|
| ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2`
|
||||||
|
| |
|
||||||
|
| arguments to this function are incorrect
|
||||||
|
|
|
||||||
|
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
|
||||||
|
--> replaced
|
||||||
|
|
|
||||||
|
LL | pub trait Trait2 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2`
|
||||||
|
|
|
||||||
|
::: replaced
|
||||||
|
|
|
||||||
|
LL | pub trait Trait2 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2`
|
||||||
|
|
|
||||||
|
::: replaced
|
||||||
|
|
|
||||||
|
LL | extern crate dep_2_reexport;
|
||||||
|
| ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
|
||||||
|
LL | extern crate dependency;
|
||||||
|
| ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
|
||||||
|
= help: you can use `cargo tree` to explore your dependency tree
|
||||||
|
note: function defined here
|
||||||
|
--> replaced
|
||||||
|
|
|
||||||
|
LL | pub fn do_something_trait(_: Box<dyn Trait2>) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0308, E0599.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
|
@ -1,14 +1,22 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
struct bool;
|
struct bool; //~ NOTE the other `bool` is defined in the current crate
|
||||||
struct str;
|
struct str; //~ NOTE the other `str` is defined in the current crate
|
||||||
|
|
||||||
fn foo(_: bool) {}
|
fn foo(_: bool) {} //~ NOTE function defined here
|
||||||
fn bar(_: &str) {}
|
fn bar(_: &str) {} //~ NOTE function defined here
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
foo(true);
|
foo(true);
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~| NOTE expected `bool`, found a different `bool`
|
||||||
|
//~| NOTE arguments to this function are incorrect
|
||||||
|
//~| NOTE `bool` and `bool` have similar names, but are actually distinct types
|
||||||
|
//~| NOTE one `bool` is a primitive defined by the language
|
||||||
bar("hello");
|
bar("hello");
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~| NOTE expected `str`, found a different `str`
|
||||||
|
//~| NOTE arguments to this function are incorrect
|
||||||
|
//~| NOTE `str` and `str` have similar names, but are actually distinct types
|
||||||
|
//~| NOTE one `str` is a primitive defined by the language
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ LL | foo(true);
|
||||||
| |
|
| |
|
||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: bool and `bool` have similar names, but are actually distinct types
|
= note: `bool` and `bool` have similar names, but are actually distinct types
|
||||||
= note: bool is a primitive defined by the language
|
= note: one `bool` is a primitive defined by the language
|
||||||
note: `bool` is defined in the current crate
|
note: the other `bool` is defined in the current crate
|
||||||
--> $DIR/similar_paths_primitive.rs:3:1
|
--> $DIR/similar_paths_primitive.rs:3:1
|
||||||
|
|
|
|
||||||
LL | struct bool;
|
LL | struct bool;
|
||||||
|
@ -20,16 +20,16 @@ LL | fn foo(_: bool) {}
|
||||||
| ^^^ -------
|
| ^^^ -------
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/similar_paths_primitive.rs:12:9
|
--> $DIR/similar_paths_primitive.rs:16:9
|
||||||
|
|
|
|
||||||
LL | bar("hello");
|
LL | bar("hello");
|
||||||
| --- ^^^^^^^ expected `str`, found a different `str`
|
| --- ^^^^^^^ expected `str`, found a different `str`
|
||||||
| |
|
| |
|
||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: str and `str` have similar names, but are actually distinct types
|
= note: `str` and `str` have similar names, but are actually distinct types
|
||||||
= note: str is a primitive defined by the language
|
= note: one `str` is a primitive defined by the language
|
||||||
note: `str` is defined in the current crate
|
note: the other `str` is defined in the current crate
|
||||||
--> $DIR/similar_paths_primitive.rs:4:1
|
--> $DIR/similar_paths_primitive.rs:4:1
|
||||||
|
|
|
|
||||||
LL | struct str;
|
LL | struct str;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
pub trait Bar{}
|
pub trait Bar {}
|
||||||
|
|
||||||
pub fn bar() -> Box<Bar> {
|
pub fn bar() -> Box<Bar> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
pub trait Bar{}
|
pub trait Bar {}
|
||||||
|
|
||||||
pub fn bar() -> Box<Bar> {
|
pub fn bar() -> Box<Bar> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|
|
@ -3,25 +3,32 @@
|
||||||
|
|
||||||
// This tests the extra note reported when a type error deals with
|
// This tests the extra note reported when a type error deals with
|
||||||
// seemingly identical types.
|
// seemingly identical types.
|
||||||
// The main use case of this error is when there are two crates
|
// The main use case of this error is when there are two crates imported
|
||||||
// (generally different versions of the same crate) with the same name
|
// with the same name, causing a type mismatch. Here, we simulate that error
|
||||||
// causing a type mismatch. Here, we simulate that error using block-scoped
|
// using block-scoped aliased `extern crate` declarations.
|
||||||
// aliased `extern crate` declarations.
|
// This is *not* the same case as two different crate versions in the
|
||||||
|
// dependency tree. That is tested in `tests/run-make/crate-loading/`.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let foo2 = {extern crate crate_a2 as a; a::Foo};
|
let foo2 = {extern crate crate_a2 as a; a::Foo};
|
||||||
|
//~^ NOTE one type comes from crate `crate_a2` used here, which is renamed locally to `a`
|
||||||
|
//~| NOTE one trait comes from crate `crate_a2` used here, which is renamed locally to `a`
|
||||||
let bar2 = {extern crate crate_a2 as a; a::bar()};
|
let bar2 = {extern crate crate_a2 as a; a::bar()};
|
||||||
{
|
{
|
||||||
extern crate crate_a1 as a;
|
extern crate crate_a1 as a;
|
||||||
|
//~^ NOTE one type comes from crate `crate_a1` used here, which is renamed locally to `a`
|
||||||
|
//~| NOTE one trait comes from crate `crate_a1` used here, which is renamed locally to `a`
|
||||||
a::try_foo(foo2);
|
a::try_foo(foo2);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| perhaps two different versions of crate `crate_a1`
|
//~| NOTE expected `main::a::Foo`, found a different `main::a::Foo`
|
||||||
//~| expected `main::a::Foo`, found a different `main::a::Foo`
|
//~| NOTE arguments to this function are incorrect
|
||||||
|
//~| NOTE two types coming from two different crates are different types even if they look the same
|
||||||
|
//~| NOTE function defined here
|
||||||
a::try_bar(bar2);
|
a::try_bar(bar2);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| perhaps two different versions of crate `crate_a1`
|
//~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar`
|
||||||
//~| expected trait `main::a::Bar`
|
//~| NOTE arguments to this function are incorrect
|
||||||
//~| expected struct `Box<(dyn main::a::Bar + 'static)>`
|
//~| NOTE two types coming from two different crates are different types even if they look the same
|
||||||
//~| found struct `Box<dyn main::a::Bar>`
|
//~| NOTE function defined here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,29 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/type-mismatch-same-crate-name.rs:16:20
|
--> $DIR/type-mismatch-same-crate-name.rs:21:20
|
||||||
|
|
|
|
||||||
LL | a::try_foo(foo2);
|
LL | a::try_foo(foo2);
|
||||||
| ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo`
|
| ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo`
|
||||||
| |
|
| |
|
||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: `main::a::Foo` and `main::a::Foo` have similar names, but are actually distinct types
|
note: two types coming from two different crates are different types even if they look the same
|
||||||
note: `main::a::Foo` is defined in crate `crate_a2`
|
|
||||||
--> $DIR/auxiliary/crate_a2.rs:1:1
|
--> $DIR/auxiliary/crate_a2.rs:1:1
|
||||||
|
|
|
|
||||||
LL | pub struct Foo;
|
LL | pub struct Foo;
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo`
|
||||||
note: `main::a::Foo` is defined in crate `crate_a1`
|
|
|
||||||
--> $DIR/auxiliary/crate_a1.rs:1:1
|
::: $DIR/auxiliary/crate_a1.rs:1:1
|
||||||
|
|
|
|
||||||
LL | pub struct Foo;
|
LL | pub struct Foo;
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo`
|
||||||
= note: perhaps two different versions of crate `crate_a1` are being used?
|
|
|
||||||
|
::: $DIR/type-mismatch-same-crate-name.rs:13:17
|
||||||
|
|
|
||||||
|
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
|
||||||
|
| --------------------------- one type comes from crate `crate_a2` used here, which is renamed locally to `a`
|
||||||
|
...
|
||||||
|
LL | extern crate crate_a1 as a;
|
||||||
|
| --------------------------- one type comes from crate `crate_a1` used here, which is renamed locally to `a`
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/auxiliary/crate_a1.rs:10:8
|
--> $DIR/auxiliary/crate_a1.rs:10:8
|
||||||
|
|
|
|
||||||
|
@ -25,16 +31,31 @@ LL | pub fn try_foo(x: Foo){}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/type-mismatch-same-crate-name.rs:20:20
|
--> $DIR/type-mismatch-same-crate-name.rs:27:20
|
||||||
|
|
|
|
||||||
LL | a::try_bar(bar2);
|
LL | a::try_bar(bar2);
|
||||||
| ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
|
| ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
|
||||||
| |
|
| |
|
||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<(dyn main::a::Bar + 'static)>`
|
note: two types coming from two different crates are different types even if they look the same
|
||||||
found struct `Box<dyn main::a::Bar>`
|
--> $DIR/auxiliary/crate_a2.rs:3:1
|
||||||
= note: perhaps two different versions of crate `crate_a1` are being used?
|
|
|
||||||
|
LL | pub trait Bar {}
|
||||||
|
| ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar`
|
||||||
|
|
|
||||||
|
::: $DIR/auxiliary/crate_a1.rs:3:1
|
||||||
|
|
|
||||||
|
LL | pub trait Bar {}
|
||||||
|
| ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar`
|
||||||
|
|
|
||||||
|
::: $DIR/type-mismatch-same-crate-name.rs:13:17
|
||||||
|
|
|
||||||
|
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
|
||||||
|
| --------------------------- one trait comes from crate `crate_a2` used here, which is renamed locally to `a`
|
||||||
|
...
|
||||||
|
LL | extern crate crate_a1 as a;
|
||||||
|
| --------------------------- one trait comes from crate `crate_a1` used here, which is renamed locally to `a`
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/auxiliary/crate_a1.rs:11:8
|
--> $DIR/auxiliary/crate_a1.rs:11:8
|
||||||
|
|
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue