authorbors <bors@rust-lang.org> 2025-11-11 21:54:08 UTC
committerbors <bors@rust-lang.org> 2025-11-11 21:54:08 UTC
log11339a0ef5ed586bb7ea4f85a9b7287880caac3a
tree159a4fe10f7c1e6f246d4d7113c4baef7e534804
parent25d319a0f656ee8faa7a534da299e76e96068a40
parentc8c04663c56fa99ac973f103ade5660650875bbd

Auto merge of #144674 - rperier:add_note_if_a_type_impl_a_trait_with_the_same_name, r=lcnr

Add a diagnostic for similarly named traits cc rust-lang/rust#133123 This is a first proposal, suggestions are welcome

15 files changed, 386 insertions(+), 528 deletions(-)

compiler/rustc_hir_typeck/src/method/suggest.rs+10-43
......@@ -4212,7 +4212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
42124212 err: &mut Diag<'_>,
42134213 item_def_id: DefId,
42144214 hir_id: hir::HirId,
4215 rcvr_ty: Option<Ty<'_>>,
4215 rcvr_ty: Option<Ty<'tcx>>,
42164216 ) -> bool {
42174217 let hir_id = self.tcx.parent_hir_id(hir_id);
42184218 let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false };
......@@ -4223,49 +4223,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
42234223 if !self.tcx.is_trait(trait_def_id) {
42244224 return false;
42254225 }
4226 let krate = self.tcx.crate_name(trait_def_id.krate);
4227 let name = self.tcx.item_name(trait_def_id);
4228 let candidates: Vec<_> = traits
4229 .iter()
4230 .filter(|c| {
4231 c.def_id.krate != trait_def_id.krate
4232 && self.tcx.crate_name(c.def_id.krate) == krate
4233 && self.tcx.item_name(c.def_id) == name
4234 })
4235 .map(|c| (c.def_id, c.import_ids.get(0).cloned()))
4236 .collect();
4237 if candidates.is_empty() {
4226 let hir::Node::Expr(rcvr) = self.tcx.hir_node(hir_id) else {
42384227 return false;
4239 }
4240 let item_span = self.tcx.def_span(item_def_id);
4241 let msg = format!(
4242 "there are multiple different versions of crate `{krate}` in the dependency graph",
4243 );
4244 let trait_span = self.tcx.def_span(trait_def_id);
4245 let mut multi_span: MultiSpan = trait_span.into();
4246 multi_span.push_span_label(trait_span, "this is the trait that is needed".to_string());
4247 let descr = self.tcx.associated_item(item_def_id).descr();
4248 let rcvr_ty =
4249 rcvr_ty.map(|t| format!("`{t}`")).unwrap_or_else(|| "the receiver".to_string());
4250 multi_span
4251 .push_span_label(item_span, format!("the {descr} is available for {rcvr_ty} here"));
4252 for (def_id, import_def_id) in candidates {
4253 if let Some(import_def_id) = import_def_id {
4254 multi_span.push_span_label(
4255 self.tcx.def_span(import_def_id),
4256 format!(
4257 "`{name}` imported here doesn't correspond to the right version of crate \
4258 `{krate}`",
4259 ),
4260 );
4261 }
4262 multi_span.push_span_label(
4263 self.tcx.def_span(def_id),
4264 "this is the trait that was imported".to_string(),
4265 );
4266 }
4267 err.span_note(multi_span, msg);
4268 true
4228 };
4229 let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, rcvr_ty.into_iter());
4230 let trait_pred = ty::Binder::dummy(ty::TraitPredicate {
4231 trait_ref,
4232 polarity: ty::PredicatePolarity::Positive,
4233 });
4234 let obligation = Obligation::new(self.tcx, self.misc(rcvr.span), self.param_env, trait_ref);
4235 self.err_ctxt().note_different_trait_with_same_name(err, &obligation, trait_pred)
42694236 }
42704237
42714238 /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs+17-206
......@@ -51,11 +51,8 @@ use std::path::PathBuf;
5151use std::{cmp, fmt, iter};
5252
5353use rustc_abi::ExternAbi;
54use rustc_ast::join_path_syms;
5554use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
56use rustc_errors::{
57 Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize,
58};
55use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize};
5956use rustc_hir::def::DefKind;
6057use rustc_hir::def_id::DefId;
6158use rustc_hir::intravisit::Visitor;
......@@ -66,15 +63,12 @@ use rustc_middle::bug;
6663use rustc_middle::dep_graph::DepContext;
6764use rustc_middle::traits::PatternOriginExpr;
6865use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt};
69use rustc_middle::ty::print::{
70 PrintError, PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths,
71};
66use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths};
7267use rustc_middle::ty::{
7368 self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
7469 TypeVisitableExt,
7570};
76use rustc_span::def_id::LOCAL_CRATE;
77use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, Symbol, sym};
71use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, sym};
7872use tracing::{debug, instrument};
7973
8074use crate::error_reporting::TypeErrCtxt;
......@@ -216,201 +210,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
216210
217211 /// Adds a note if the types come from similarly named crates
218212 fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) -> bool {
219 // FIXME(estebank): unify with `report_similar_impl_candidates`. The message is similar,
220 // even if the logic needed to detect the case is very different.
221 use hir::def_id::CrateNum;
222 use rustc_hir::definitions::DisambiguatedDefPathData;
223 use ty::GenericArg;
224 use ty::print::Printer;
225
226 struct ConflictingPathPrinter<'tcx> {
227 tcx: TyCtxt<'tcx>,
228 segments: Vec<Symbol>,
229 }
230
231 impl<'tcx> Printer<'tcx> for ConflictingPathPrinter<'tcx> {
232 fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
233 self.tcx
234 }
235
236 fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
237 unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
238 }
239
240 fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> {
241 unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
242 }
243
244 fn print_dyn_existential(
245 &mut self,
246 _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
247 ) -> Result<(), PrintError> {
248 unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
249 }
250
251 fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> {
252 unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
253 }
254
255 fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
256 self.segments = vec![self.tcx.crate_name(cnum)];
257 Ok(())
258 }
259
260 fn print_path_with_qualified(
261 &mut self,
262 _self_ty: Ty<'tcx>,
263 _trait_ref: Option<ty::TraitRef<'tcx>>,
264 ) -> Result<(), PrintError> {
265 Err(fmt::Error)
266 }
267
268 fn print_path_with_impl(
269 &mut self,
270 _print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
271 _self_ty: Ty<'tcx>,
272 _trait_ref: Option<ty::TraitRef<'tcx>>,
273 ) -> Result<(), PrintError> {
274 Err(fmt::Error)
275 }
276
277 fn print_path_with_simple(
278 &mut self,
279 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
280 disambiguated_data: &DisambiguatedDefPathData,
281 ) -> Result<(), PrintError> {
282 print_prefix(self)?;
283 self.segments.push(disambiguated_data.as_sym(true));
284 Ok(())
285 }
286
287 fn print_path_with_generic_args(
288 &mut self,
289 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
290 _args: &[GenericArg<'tcx>],
291 ) -> Result<(), PrintError> {
292 print_prefix(self)
293 }
294 }
295
296 let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId, ty: &str| -> bool {
297 // Only report definitions from different crates. If both definitions
298 // are from a local module we could have false positives, e.g.
299 // let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
300 if did1.krate != did2.krate {
301 let abs_path = |def_id| {
302 let mut p = ConflictingPathPrinter { tcx: self.tcx, segments: vec![] };
303 p.print_def_path(def_id, &[]).map(|_| p.segments)
304 };
305
306 // We compare strings because DefPath can be different for imported and
307 // non-imported crates.
308 let expected_str = self.tcx.def_path_str(did1);
309 let found_str = self.tcx.def_path_str(did2);
310 let Ok(expected_abs) = abs_path(did1) else { return false };
311 let Ok(found_abs) = abs_path(did2) else { return false };
312 let same_path = expected_str == found_str || expected_abs == found_abs;
313 if same_path {
314 // We want to use as unique a type path as possible. If both types are "locally
315 // known" by the same name, we use the "absolute path" which uses the original
316 // crate name instead.
317 let (expected, found) = if expected_str == found_str {
318 (join_path_syms(&expected_abs), join_path_syms(&found_abs))
319 } else {
320 (expected_str, found_str)
321 };
322
323 // We've displayed "expected `a::b`, found `a::b`". We add context to
324 // differentiate the different cases where that might happen.
325 let expected_crate_name = self.tcx.crate_name(did1.krate);
326 let found_crate_name = self.tcx.crate_name(did2.krate);
327 let same_crate = expected_crate_name == found_crate_name;
328 let expected_sp = self.tcx.def_span(did1);
329 let found_sp = self.tcx.def_span(did2);
330
331 let both_direct_dependencies = if !did1.is_local()
332 && !did2.is_local()
333 && let Some(data1) = self.tcx.extern_crate(did1.krate)
334 && let Some(data2) = self.tcx.extern_crate(did2.krate)
335 && data1.dependency_of == LOCAL_CRATE
336 && data2.dependency_of == LOCAL_CRATE
337 {
338 // If both crates are directly depended on, we don't want to mention that
339 // in the final message, as it is redundant wording.
340 // We skip the case of semver trick, where one version of the local crate
341 // depends on another version of itself by checking that both crates at play
342 // are not the current one.
343 true
344 } else {
345 false
346 };
347
348 let mut span: MultiSpan = vec![expected_sp, found_sp].into();
349 span.push_span_label(
350 self.tcx.def_span(did1),
351 format!("this is the expected {ty} `{expected}`"),
352 );
353 span.push_span_label(
354 self.tcx.def_span(did2),
355 format!("this is the found {ty} `{found}`"),
356 );
357 for def_id in [did1, did2] {
358 let crate_name = self.tcx.crate_name(def_id.krate);
359 if !def_id.is_local()
360 && let Some(data) = self.tcx.extern_crate(def_id.krate)
361 {
362 let descr = if same_crate {
363 "one version of".to_string()
364 } else {
365 format!("one {ty} comes from")
366 };
367 let dependency = if both_direct_dependencies {
368 if let rustc_session::cstore::ExternCrateSource::Extern(def_id) =
369 data.src
370 && let Some(name) = self.tcx.opt_item_name(def_id)
371 {
372 format!(", which is renamed locally to `{name}`")
373 } else {
374 String::new()
375 }
376 } else if data.dependency_of == LOCAL_CRATE {
377 ", as a direct dependency of the current crate".to_string()
378 } else {
379 let dep = self.tcx.crate_name(data.dependency_of);
380 format!(", as a dependency of crate `{dep}`")
381 };
382 span.push_span_label(
383 data.span,
384 format!("{descr} crate `{crate_name}` used here{dependency}"),
385 );
386 }
387 }
388 let msg = if (did1.is_local() || did2.is_local()) && same_crate {
389 format!(
390 "the crate `{expected_crate_name}` is compiled multiple times, \
391 possibly with different configurations",
392 )
393 } else if same_crate {
394 format!(
395 "two different versions of crate `{expected_crate_name}` are being \
396 used; two types coming from two different versions of the same crate \
397 are different types even if they look the same",
398 )
399 } else {
400 format!(
401 "two types coming from two different crates are different types even \
402 if they look the same",
403 )
404 };
405 err.span_note(span, msg);
406 if same_crate {
407 err.help("you can use `cargo tree` to explore your dependency tree");
408 }
409 return true;
410 }
411 }
412 false
413 };
414213 match terr {
415214 TypeError::Sorts(ref exp_found) => {
416215 // if they are both "path types", there's a chance of ambiguity
......@@ -418,11 +217,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
418217 if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
419218 (exp_found.expected.kind(), exp_found.found.kind())
420219 {
421 return report_path_match(err, exp_adt.did(), found_adt.did(), "type");
220 return self.check_same_definition_different_crate(
221 err,
222 exp_adt.did(),
223 [found_adt.did()].into_iter(),
224 |did| vec![self.tcx.def_span(did)],
225 "type",
226 );
422227 }
423228 }
424229 TypeError::Traits(ref exp_found) => {
425 return report_path_match(err, exp_found.expected, exp_found.found, "trait");
230 return self.check_same_definition_different_crate(
231 err,
232 exp_found.expected,
233 [exp_found.found].into_iter(),
234 |did| vec![self.tcx.def_span(did)],
235 "trait",
236 );
426237 }
427238 _ => (), // FIXME(#22750) handle traits and stuff
428239 }
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs+95-148
......@@ -468,7 +468,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
468468 span,
469469 leaf_trait_predicate,
470470 );
471 self.note_trait_version_mismatch(&mut err, leaf_trait_predicate);
471 self.note_different_trait_with_same_name(&mut err, &obligation, leaf_trait_predicate);
472472 self.note_adt_version_mismatch(&mut err, leaf_trait_predicate);
473473 self.suggest_remove_await(&obligation, &mut err);
474474 self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);
......@@ -1974,115 +1974,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
19741974 impl_candidates
19751975 };
19761976
1977 // We'll check for the case where the reason for the mismatch is that the trait comes from
1978 // one crate version and the type comes from another crate version, even though they both
1979 // are from the same crate.
1980 let trait_def_id = trait_pred.def_id();
1981 let trait_name = self.tcx.item_name(trait_def_id);
1982 let crate_name = self.tcx.crate_name(trait_def_id.krate);
1983 if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| {
1984 trait_name == self.tcx.item_name(trait_def_id)
1985 && trait_def_id.krate != def_id.krate
1986 && crate_name == self.tcx.crate_name(def_id.krate)
1987 }) {
1988 // We've found two different traits with the same name, same crate name, but
1989 // different crate `DefId`. We highlight the traits.
1990
1991 let found_type =
1992 if let ty::Adt(def, _) = trait_pred.self_ty().skip_binder().peel_refs().kind() {
1993 Some(def.did())
1994 } else {
1995 None
1996 };
1997 let candidates = if impl_candidates.is_empty() {
1998 alternative_candidates(trait_def_id)
1999 } else {
2000 impl_candidates.into_iter().map(|cand| (cand.trait_ref, cand.impl_def_id)).collect()
2001 };
2002 let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into();
2003 span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
2004 for (sp, label) in [trait_def_id, other_trait_def_id]
2005 .iter()
2006 // The current crate-version might depend on another version of the same crate
2007 // (Think "semver-trick"). Do not call `extern_crate` in that case for the local
2008 // crate as that doesn't make sense and ICEs (#133563).
2009 .filter(|def_id| !def_id.is_local())
2010 .filter_map(|def_id| self.tcx.extern_crate(def_id.krate))
2011 .map(|data| {
2012 let dependency = if data.dependency_of == LOCAL_CRATE {
2013 "direct dependency of the current crate".to_string()
2014 } else {
2015 let dep = self.tcx.crate_name(data.dependency_of);
2016 format!("dependency of crate `{dep}`")
2017 };
2018 (
2019 data.span,
2020 format!("one version of crate `{crate_name}` used here, as a {dependency}"),
2021 )
2022 })
2023 {
2024 span.push_span_label(sp, label);
2025 }
2026 let mut points_at_type = false;
2027 if let Some(found_type) = found_type {
2028 span.push_span_label(
2029 self.tcx.def_span(found_type),
2030 "this type doesn't implement the required trait",
2031 );
2032 for (trait_ref, _) in candidates {
2033 if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
2034 && let candidate_def_id = def.did()
2035 && let Some(name) = self.tcx.opt_item_name(candidate_def_id)
2036 && let Some(found) = self.tcx.opt_item_name(found_type)
2037 && name == found
2038 && candidate_def_id.krate != found_type.krate
2039 && self.tcx.crate_name(candidate_def_id.krate)
2040 == self.tcx.crate_name(found_type.krate)
2041 {
2042 // A candidate was found of an item with the same name, from two separate
2043 // versions of the same crate, let's clarify.
2044 let candidate_span = self.tcx.def_span(candidate_def_id);
2045 span.push_span_label(
2046 candidate_span,
2047 "this type implements the required trait",
2048 );
2049 points_at_type = true;
2050 }
2051 }
2052 }
2053 span.push_span_label(self.tcx.def_span(other_trait_def_id), "this is the found trait");
2054 err.highlighted_span_note(
2055 span,
2056 vec![
2057 StringPart::normal("there are ".to_string()),
2058 StringPart::highlighted("multiple different versions".to_string()),
2059 StringPart::normal(" of crate `".to_string()),
2060 StringPart::highlighted(format!("{crate_name}")),
2061 StringPart::normal("` in the dependency graph".to_string()),
2062 ],
2063 );
2064 if points_at_type {
2065 // We only clarify that the same type from different crate versions are not the
2066 // same when we *find* the same type coming from different crate versions, otherwise
2067 // it could be that it was a type provided by a different crate than the one that
2068 // provides the trait, and mentioning this adds verbosity without clarification.
2069 err.highlighted_note(vec![
2070 StringPart::normal(
2071 "two types coming from two different versions of the same crate are \
2072 different types "
2073 .to_string(),
2074 ),
2075 StringPart::highlighted("even if they look the same".to_string()),
2076 ]);
2077 }
2078 err.highlighted_help(vec![
2079 StringPart::normal("you can use `".to_string()),
2080 StringPart::highlighted("cargo tree".to_string()),
2081 StringPart::normal("` to explore your dependency tree".to_string()),
2082 ]);
2083 return true;
2084 }
2085
20861977 if let [single] = &impl_candidates {
20871978 // If we have a single implementation, try to unify it with the trait ref
20881979 // that failed. This should uncover a better hint for what *is* implemented.
......@@ -2478,10 +2369,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
24782369 }
24792370 }
24802371
2481 /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
2482 /// with the same path as `trait_ref`, a help message about
2483 /// a probable version mismatch is added to `err`
2484 fn note_trait_version_mismatch(
2372 fn check_same_trait_different_version(
24852373 &self,
24862374 err: &mut Diag<'_>,
24872375 trait_pred: ty::PolyTraitPredicate<'tcx>,
......@@ -2492,46 +2380,33 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
24922380 trait_def_id,
24932381 trait_pred.skip_binder().self_ty(),
24942382 |impl_def_id| {
2495 trait_impls.push(impl_def_id);
2383 let impl_trait_header = self.tcx.impl_trait_header(impl_def_id);
2384 trait_impls
2385 .push(self.tcx.def_span(impl_trait_header.trait_ref.skip_binder().def_id));
24962386 },
24972387 );
24982388 trait_impls
24992389 };
2500
2501 let required_trait_path = self.tcx.def_path_str(trait_pred.def_id());
2502 let traits_with_same_path: UnordSet<_> = self
2503 .tcx
2504 .visible_traits()
2505 .filter(|trait_def_id| *trait_def_id != trait_pred.def_id())
2506 .map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id))
2507 .filter(|(p, _)| *p == required_trait_path)
2508 .collect();
2509
2510 let traits_with_same_path =
2511 traits_with_same_path.into_items().into_sorted_stable_ord_by_key(|(p, _)| p);
2512 let mut suggested = false;
2513 for (_, trait_with_same_path) in traits_with_same_path {
2514 let trait_impls = get_trait_impls(trait_with_same_path);
2515 if trait_impls.is_empty() {
2516 continue;
2517 }
2518 let impl_spans: Vec<_> =
2519 trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
2520 err.span_help(
2521 impl_spans,
2522 format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
2523 );
2524 self.note_two_crate_versions(trait_with_same_path, err);
2525 suggested = true;
2526 }
2527 suggested
2390 self.check_same_definition_different_crate(
2391 err,
2392 trait_pred.def_id(),
2393 self.tcx.visible_traits(),
2394 get_trait_impls,
2395 "trait",
2396 )
25282397 }
25292398
2530 fn note_two_crate_versions(&self, did: DefId, err: &mut Diag<'_>) {
2399 pub fn note_two_crate_versions(
2400 &self,
2401 did: DefId,
2402 sp: impl Into<MultiSpan>,
2403 err: &mut Diag<'_>,
2404 ) {
25312405 let crate_name = self.tcx.crate_name(did.krate);
2532 let crate_msg =
2533 format!("perhaps two different versions of crate `{crate_name}` are being used?");
2534 err.note(crate_msg);
2406 let crate_msg = format!(
2407 "there are multiple different versions of crate `{crate_name}` in the dependency graph"
2408 );
2409 err.span_note(sp, crate_msg);
25352410 }
25362411
25372412 fn note_adt_version_mismatch(
......@@ -2592,8 +2467,80 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
25922467
25932468 for (similar_item, _) in similar_items {
25942469 err.span_help(self.tcx.def_span(similar_item), "item with same name found");
2595 self.note_two_crate_versions(similar_item, err);
2470 self.note_two_crate_versions(similar_item, MultiSpan::new(), err);
2471 }
2472 }
2473
2474 fn check_same_name_different_path(
2475 &self,
2476 err: &mut Diag<'_>,
2477 obligation: &PredicateObligation<'tcx>,
2478 trait_pred: ty::PolyTraitPredicate<'tcx>,
2479 ) -> bool {
2480 let mut suggested = false;
2481 let trait_def_id = trait_pred.def_id();
2482 let trait_has_same_params = |other_trait_def_id: DefId| -> bool {
2483 let trait_generics = self.tcx.generics_of(trait_def_id);
2484 let other_trait_generics = self.tcx.generics_of(other_trait_def_id);
2485
2486 if trait_generics.count() != other_trait_generics.count() {
2487 return false;
2488 }
2489 trait_generics.own_params.iter().zip(other_trait_generics.own_params.iter()).all(
2490 |(a, b)| match (&a.kind, &b.kind) {
2491 (ty::GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Lifetime)
2492 | (
2493 ty::GenericParamDefKind::Type { .. },
2494 ty::GenericParamDefKind::Type { .. },
2495 )
2496 | (
2497 ty::GenericParamDefKind::Const { .. },
2498 ty::GenericParamDefKind::Const { .. },
2499 ) => true,
2500 _ => false,
2501 },
2502 )
2503 };
2504 let trait_name = self.tcx.item_name(trait_def_id);
2505 if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| {
2506 trait_def_id != *def_id
2507 && trait_name == self.tcx.item_name(def_id)
2508 && trait_has_same_params(*def_id)
2509 && self.predicate_must_hold_modulo_regions(&Obligation::new(
2510 self.tcx,
2511 obligation.cause.clone(),
2512 obligation.param_env,
2513 trait_pred.map_bound(|tr| ty::TraitPredicate {
2514 trait_ref: ty::TraitRef::new(self.tcx, *def_id, tr.trait_ref.args),
2515 ..tr
2516 }),
2517 ))
2518 }) {
2519 err.note(format!(
2520 "`{}` implements similarly named trait `{}`, but not `{}`",
2521 trait_pred.self_ty(),
2522 self.tcx.def_path_str(other_trait_def_id),
2523 trait_pred.print_modifiers_and_trait_path()
2524 ));
2525 suggested = true;
2526 }
2527 suggested
2528 }
2529
2530 /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
2531 /// with the same path as `trait_ref`, a help message about a multiple different
2532 /// versions of the same crate is added to `err`. Otherwise if it implements another
2533 /// trait with the same name, a note message about a similarly named trait is added to `err`.
2534 pub fn note_different_trait_with_same_name(
2535 &self,
2536 err: &mut Diag<'_>,
2537 obligation: &PredicateObligation<'tcx>,
2538 trait_pred: ty::PolyTraitPredicate<'tcx>,
2539 ) -> bool {
2540 if self.check_same_trait_different_version(err, trait_pred) {
2541 return true;
25962542 }
2543 self.check_same_name_different_path(err, obligation, trait_pred)
25972544 }
25982545
25992546 /// Add a `::` prefix when comparing paths so that paths with just one item
compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs+77-2
......@@ -1,6 +1,6 @@
11pub mod ambiguity;
22pub mod call_kind;
3mod fulfillment_errors;
3pub mod fulfillment_errors;
44pub mod on_unimplemented;
55pub mod on_unimplemented_condition;
66pub mod on_unimplemented_format;
......@@ -10,6 +10,7 @@ pub mod suggestions;
1010use std::{fmt, iter};
1111
1212use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
13use rustc_data_structures::unord::UnordSet;
1314use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
1415use rustc_hir::def_id::{DefId, LocalDefId};
1516use rustc_hir::intravisit::Visitor;
......@@ -21,7 +22,7 @@ use rustc_infer::traits::{
2122};
2223use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
2324use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
24use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span};
25use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span, Symbol};
2526use tracing::{info, instrument};
2627
2728pub use self::overflow::*;
......@@ -351,6 +352,80 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
351352 FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle),
352353 }
353354 }
355
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
364 }
365 }
366
367 pub fn check_same_definition_different_crate<F>(
368 &self,
369 err: &mut Diag<'_>,
370 expected_did: DefId,
371 found_dids: impl Iterator<Item = DefId>,
372 get_impls: F,
373 ty: &str,
374 ) -> bool
375 where
376 F: Fn(DefId) -> Vec<Span>,
377 {
378 let krate = self.tcx.crate_name(expected_did.krate);
379 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 });
383 let definitions_with_same_path: UnordSet<_> = found_dids
384 .filter(|def_id| {
385 def_id.krate != expected_did.krate
386 && (locally_renamed_krate == self.get_extern_crate_renamed_symbol(*def_id)
387 || self.tcx.crate_name(def_id.krate) == krate)
388 && self.tcx.item_name(def_id) == name
389 })
390 .map(|def_id| (self.tcx.def_path_str(def_id), def_id))
391 .collect();
392
393 let definitions_with_same_path =
394 definitions_with_same_path.into_items().into_sorted_stable_ord_by_key(|(p, _)| p);
395 let mut suggested = false;
396 let mut trait_is_impl = false;
397
398 if !definitions_with_same_path.is_empty() {
399 let mut span: MultiSpan = self.tcx.def_span(expected_did).into();
400 span.push_span_label(
401 self.tcx.def_span(expected_did),
402 format!("this is the expected {ty}"),
403 );
404 suggested = true;
405 for (_, definition_with_same_path) in &definitions_with_same_path {
406 let definitions_impls = get_impls(*definition_with_same_path);
407 if definitions_impls.is_empty() {
408 continue;
409 }
410
411 for candidate_span in definitions_impls {
412 span.push_span_label(candidate_span, format!("this is the found {ty}"));
413 trait_is_impl = true;
414 }
415 }
416 if !trait_is_impl {
417 for (_, def_id) in definitions_with_same_path {
418 span.push_span_label(
419 self.tcx.def_span(def_id),
420 format!("this is the {ty} that was imported"),
421 );
422 }
423 }
424 self.note_two_crate_versions(expected_did, span, err);
425 err.help("you can use `cargo tree` to explore your dependency tree");
426 }
427 suggested
428 }
354429}
355430
356431/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
tests/incremental/circular-dependencies.rs+6-8
......@@ -6,12 +6,12 @@
66//@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies
77
88pub struct Foo;
9//[cfail2]~^ NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
10//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations
11//[cfail2]~| NOTE this is the expected type `Foo`
12//[cfail2]~| NOTE this is the expected type `circular_dependencies::Foo`
13//[cfail2]~| NOTE this is the found type `Foo`
14//[cfail2]~| NOTE this is the found type `circular_dependencies::Foo`
9//[cfail2]~^ NOTE there are multiple different versions of crate `circular_dependencies` in the dependency graph
10//[cfail2]~| NOTE there are multiple different versions of crate `circular_dependencies` in the dependency graph
11//[cfail2]~| NOTE this is the expected type
12//[cfail2]~| NOTE this is the expected type
13//[cfail2]~| NOTE this is the found type
14//[cfail2]~| NOTE this is the found type
1515
1616pub fn consume_foo(_: Foo) {}
1717//[cfail2]~^ NOTE function defined here
......@@ -27,8 +27,6 @@ fn test() {
2727 //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo`
2828 //[cfail2]~| NOTE arguments to this function are incorrect
2929 //[cfail2]~| NOTE function defined here
30 //[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux`
31 //[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux`
3230
3331 consume_foo(aux::produce_foo());
3432 //[cfail2]~^ ERROR mismatched types [E0308]
tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr+6-9
......@@ -7,22 +7,19 @@ error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied
77note: there are multiple different versions of crate `foo` in the dependency graph
88 --> foo-current.rs:7:1
99 |
10 4 | extern crate foo;
11 | ----------------- one version of crate `foo` used here, as a direct dependency of the current crate
12 5 |
13 6 | pub struct Struct;
14 | ----------------- this type implements the required trait
1510 7 | pub trait Trait {}
16 | ^^^^^^^^^^^^^^^ this is the required trait
11 | ^^^^^^^^^^^^^^^ this is the expected trait
1712 |
1813 ::: foo-prev.rs:X:Y
1914 |
20 4 | pub struct Struct;
21 | ----------------- this type doesn't implement the required trait
2215 5 | pub trait Trait {}
2316 | --------------- this is the found trait
24 = note: two types coming from two different versions of the same crate are different types even if they look the same
2517 = help: you can use `cargo tree` to explore your dependency tree
18help: the trait `Trait` is implemented for `Struct`
19 --> foo-current.rs:8:1
20 |
21 8 | impl Trait for Struct {}
22 | ^^^^^^^^^^^^^^^^^^^^^
2623note: required by a bound in `check_trait`
2724 --> foo-current.rs:10:19
2825 |
tests/run-make/crate-loading/multiple-dep-versions.stderr+22-63
......@@ -9,26 +9,19 @@ LL | do_something(Type);
99note: there are multiple different versions of crate `dependency` in the dependency graph
1010 --> replaced
1111 |
12LL | pub struct Type(pub i32);
13 | --------------- this type implements the required trait
1412LL | pub trait Trait {
15 | ^^^^^^^^^^^^^^^ this is the required trait
16 |
17 ::: replaced
18 |
19LL | extern crate dep_2_reexport;
20 | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
21LL | extern crate dependency;
22 | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
13 | ^^^^^^^^^^^^^^^ this is the expected trait
2314 |
2415 ::: replaced
2516 |
26LL | pub struct Type;
27 | --------------- this type doesn't implement the required trait
2817LL | pub trait Trait {
2918 | --------------- this is the found trait
30 = note: two types coming from two different versions of the same crate are different types even if they look the same
3119 = help: you can use `cargo tree` to explore your dependency tree
20help: the trait `Trait` is implemented for `dependency::Type`
21 --> replaced
22 |
23LL | impl Trait for Type {
24 | ^^^^^^^^^^^^^^^^^^^
3225note: required by a bound in `do_something`
3326 --> replaced
3427 |
......@@ -45,19 +38,13 @@ note: there are multiple different versions of crate `dependency` in the depende
4538 --> replaced
4639 |
4740LL | pub trait Trait {
48 | ^^^^^^^^^^^^^^^ this is the trait that is needed
49LL | fn foo(&self);
50 | -------------- the method is available for `dep_2_reexport::Type` here
51 |
52 ::: replaced
53 |
54LL | use dependency::{Trait, do_something, do_something_trait, do_something_type};
55 | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
41 | ^^^^^^^^^^^^^^^ this is the expected trait
5642 |
5743 ::: replaced
5844 |
5945LL | pub trait Trait {
6046 | --------------- this is the trait that was imported
47 = help: you can use `cargo tree` to explore your dependency tree
6148
6249error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope
6350 --> replaced
......@@ -69,20 +56,13 @@ note: there are multiple different versions of crate `dependency` in the depende
6956 --> replaced
7057 |
7158LL | pub trait Trait {
72 | ^^^^^^^^^^^^^^^ this is the trait that is needed
73LL | fn foo(&self);
74LL | fn bar();
75 | --------- the associated function is available for `dep_2_reexport::Type` here
76 |
77 ::: replaced
78 |
79LL | use dependency::{Trait, do_something, do_something_trait, do_something_type};
80 | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`
59 | ^^^^^^^^^^^^^^^ this is the expected trait
8160 |
8261 ::: replaced
8362 |
8463LL | pub trait Trait {
8564 | --------------- this is the trait that was imported
65 = help: you can use `cargo tree` to explore your dependency tree
8666
8767error[E0277]: the trait bound `OtherType: Trait` is not satisfied
8868 --> replaced
......@@ -96,25 +76,18 @@ note: there are multiple different versions of crate `dependency` in the depende
9676 --> replaced
9777 |
9878LL | pub trait Trait {
99 | ^^^^^^^^^^^^^^^ this is the required trait
100 |
101 ::: replaced
102 |
103LL | extern crate dep_2_reexport;
104 | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
105LL | extern crate dependency;
106 | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
107 |
108 ::: replaced
109 |
110LL | pub struct OtherType;
111 | -------------------- this type doesn't implement the required trait
79 | ^^^^^^^^^^^^^^^ this is the expected trait
11280 |
11381 ::: replaced
11482 |
11583LL | pub trait Trait {
11684 | --------------- this is the found trait
11785 = help: you can use `cargo tree` to explore your dependency tree
86help: the trait `Trait` is implemented for `dependency::Type`
87 --> replaced
88 |
89LL | impl Trait for Type {
90 | ^^^^^^^^^^^^^^^^^^^
11891note: required by a bound in `do_something`
11992 --> replaced
12093 |
......@@ -129,23 +102,16 @@ LL | do_something_type(Type);
129102 | |
130103 | arguments to this function are incorrect
131104 |
132note: 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
105note: there are multiple different versions of crate `dependency` in the dependency graph
133106 --> replaced
134107 |
135108LL | pub struct Type(pub i32);
136 | ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type`
109 | ^^^^^^^^^^^^^^^ this is the expected type
137110 |
138111 ::: replaced
139112 |
140113LL | pub struct Type;
141 | ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type`
142 |
143 ::: replaced
144 |
145LL | extern crate dep_2_reexport;
146 | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
147LL | extern crate dependency;
148 | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
114 | --------------- this is the found type
149115 = help: you can use `cargo tree` to explore your dependency tree
150116note: function defined here
151117 --> replaced
......@@ -161,23 +127,16 @@ LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>);
161127 | |
162128 | arguments to this function are incorrect
163129 |
164note: 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
130note: there are multiple different versions of crate `dependency` in the dependency graph
165131 --> replaced
166132 |
167133LL | pub trait Trait2 {}
168 | ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2`
134 | ^^^^^^^^^^^^^^^^ this is the expected trait
169135 |
170136 ::: replaced
171137 |
172138LL | pub trait Trait2 {}
173 | ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2`
174 |
175 ::: replaced
176 |
177LL | extern crate dep_2_reexport;
178 | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo`
179LL | extern crate dependency;
180 | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate
139 | ---------------- this is the found trait
181140 = help: you can use `cargo tree` to explore your dependency tree
182141note: function defined here
183142 --> replaced
tests/run-make/duplicate-dependency/main.stderr+1-1
......@@ -11,7 +11,7 @@ help: item with same name found
1111 |
1212LL | pub struct Foo;
1313 | ^^^^^^^^^^^^^^
14 = note: perhaps two different versions of crate `foo` are being used?
14 = note: there are multiple different versions of crate `foo` in the dependency graph
1515 = note: required for `Bar` to implement `Into<re_export_foo::foo::Foo>`
1616note: required by a bound in `into_foo`
1717 --> $DIR/re-export-foo.rs:3:25
tests/ui/traits/bound/same-crate-name.rs+8-2
......@@ -32,13 +32,15 @@ fn main() {
3232 extern crate crate_a1 as a;
3333 a::try_foo(foo);
3434 //~^ ERROR E0277
35 //~| HELP trait impl with same name found
36 //~| NOTE perhaps two different versions of crate `crate_a2`
35 //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph
36 //~| HELP you can use `cargo tree` to explore your dependency tree
3737
3838 // We don't want to see the "version mismatch" help message here
3939 // because `implements_no_traits` has no impl for `Foo`
4040 a::try_foo(implements_no_traits);
4141 //~^ ERROR E0277
42 //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph
43 //~| HELP you can use `cargo tree` to explore your dependency tree
4244
4345 // We don't want to see the "version mismatch" help message here
4446 // because `other_variant_implements_mismatched_trait`
......@@ -46,6 +48,8 @@ fn main() {
4648 // only for its `<usize>` variant.
4749 a::try_foo(other_variant_implements_mismatched_trait);
4850 //~^ ERROR E0277
51 //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph
52 //~| HELP you can use `cargo tree` to explore your dependency tree
4953
5054 // We don't want to see the "version mismatch" help message here
5155 // because `ImplementsTraitForUsize` only has
......@@ -53,5 +57,7 @@ fn main() {
5357 a::try_foo(other_variant_implements_correct_trait);
5458 //~^ ERROR E0277
5559 //~| HELP the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
60 //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph
61 //~| HELP you can use `cargo tree` to explore your dependency tree
5662 }
5763}
tests/ui/traits/bound/same-crate-name.stderr+44-12
......@@ -6,12 +6,17 @@ LL | a::try_foo(foo);
66 | |
77 | required by a bound introduced by this call
88 |
9help: trait impl with same name found
10 --> $DIR/auxiliary/crate_a2.rs:5:1
9note: there are multiple different versions of crate `crate_a1` in the dependency graph
10 --> $DIR/auxiliary/crate_a1.rs:1:1
1111 |
12LL | impl Bar for Foo {}
13 | ^^^^^^^^^^^^^^^^
14 = note: perhaps two different versions of crate `crate_a2` are being used?
12LL | pub trait Bar {}
13 | ^^^^^^^^^^^^^ this is the expected trait
14 |
15 ::: $DIR/auxiliary/crate_a2.rs:3:1
16 |
17LL | pub trait Bar {}
18 | ------------- this is the found trait
19 = help: you can use `cargo tree` to explore your dependency tree
1520help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
1621 --> $DIR/auxiliary/crate_a1.rs:9:1
1722 |
......@@ -31,6 +36,17 @@ LL | a::try_foo(implements_no_traits);
3136 | |
3237 | required by a bound introduced by this call
3338 |
39note: there are multiple different versions of crate `crate_a1` in the dependency graph
40 --> $DIR/auxiliary/crate_a1.rs:1:1
41 |
42LL | pub trait Bar {}
43 | ^^^^^^^^^^^^^ this is the expected trait
44 |
45 ::: $DIR/auxiliary/crate_a2.rs:3:1
46 |
47LL | pub trait Bar {}
48 | ------------- this is the trait that was imported
49 = help: you can use `cargo tree` to explore your dependency tree
3450help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
3551 --> $DIR/auxiliary/crate_a1.rs:9:1
3652 |
......@@ -43,19 +59,24 @@ LL | pub fn try_foo(x: impl Bar) {}
4359 | ^^^ required by this bound in `try_foo`
4460
4561error[E0277]: the trait bound `ImplementsWrongTraitConditionally<isize>: main::a::Bar` is not satisfied
46 --> $DIR/same-crate-name.rs:47:20
62 --> $DIR/same-crate-name.rs:49:20
4763 |
4864LL | a::try_foo(other_variant_implements_mismatched_trait);
4965 | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
5066 | |
5167 | required by a bound introduced by this call
5268 |
53help: trait impl with same name found
54 --> $DIR/auxiliary/crate_a2.rs:13:1
69note: there are multiple different versions of crate `crate_a1` in the dependency graph
70 --> $DIR/auxiliary/crate_a1.rs:1:1
5571 |
56LL | impl Bar for ImplementsWrongTraitConditionally<isize> {}
57 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58 = note: perhaps two different versions of crate `crate_a2` are being used?
72LL | pub trait Bar {}
73 | ^^^^^^^^^^^^^ this is the expected trait
74 |
75 ::: $DIR/auxiliary/crate_a2.rs:3:1
76 |
77LL | pub trait Bar {}
78 | ------------- this is the found trait
79 = help: you can use `cargo tree` to explore your dependency tree
5980help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
6081 --> $DIR/auxiliary/crate_a1.rs:9:1
6182 |
......@@ -68,13 +89,24 @@ LL | pub fn try_foo(x: impl Bar) {}
6889 | ^^^ required by this bound in `try_foo`
6990
7091error[E0277]: the trait bound `ImplementsTraitForUsize<isize>: main::a::Bar` is not satisfied
71 --> $DIR/same-crate-name.rs:53:20
92 --> $DIR/same-crate-name.rs:57:20
7293 |
7394LL | a::try_foo(other_variant_implements_correct_trait);
7495 | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
7596 | |
7697 | required by a bound introduced by this call
7798 |
99note: there are multiple different versions of crate `crate_a1` in the dependency graph
100 --> $DIR/auxiliary/crate_a1.rs:1:1
101 |
102LL | pub trait Bar {}
103 | ^^^^^^^^^^^^^ this is the expected trait
104 |
105 ::: $DIR/auxiliary/crate_a2.rs:3:1
106 |
107LL | pub trait Bar {}
108 | ------------- this is the trait that was imported
109 = help: you can use `cargo tree` to explore your dependency tree
78110help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>`
79111 --> $DIR/auxiliary/crate_a1.rs:9:1
80112 |
tests/ui/traits/similarly_named_trait.rs created+28
......@@ -0,0 +1,28 @@
1trait Trait {} //~ HELP this trait has no implementations, consider adding one
2trait TraitWithParam<T> {} //~ HELP this trait has no implementations, consider adding one
3
4mod m {
5 pub trait Trait {}
6 pub trait TraitWithParam<T> {}
7 pub struct St; //~ HELP the trait `Trait` is not implemented for `St`
8 //~| HELP the trait `TraitWithParam<St>` is not implemented for `St`
9 impl Trait for St {}
10 impl<T> TraitWithParam<T> for St {}
11}
12
13fn func<T: Trait>(_: T) {} //~ NOTE required by a bound in `func`
14//~^ NOTE required by this bound in `func`
15
16fn func2<T: TraitWithParam<T>> (_: T) {} //~ NOTE required by a bound in `func2`
17//~^ NOTE required by this bound in `func2`
18
19fn main() {
20 func(m::St); //~ ERROR the trait bound `St: Trait` is not satisfied
21 //~^ NOTE unsatisfied trait bound
22 //~| NOTE required by a bound introduced by this call
23 //~| NOTE `St` implements similarly named trait `m::Trait`, but not `Trait`
24 func2(m::St); //~ ERROR the trait bound `St: TraitWithParam<St>` is not satisfied
25 //~^ NOTE unsatisfied trait bound
26 //~| NOTE required by a bound introduced by this call
27 //~| NOTE `St` implements similarly named trait `m::TraitWithParam`, but not `TraitWithParam<St>`
28}
tests/ui/traits/similarly_named_trait.stderr created+53
......@@ -0,0 +1,53 @@
1error[E0277]: the trait bound `St: Trait` is not satisfied
2 --> $DIR/similarly_named_trait.rs:20:10
3 |
4LL | func(m::St);
5 | ---- ^^^^^ unsatisfied trait bound
6 | |
7 | required by a bound introduced by this call
8 |
9help: the trait `Trait` is not implemented for `St`
10 --> $DIR/similarly_named_trait.rs:7:5
11 |
12LL | pub struct St;
13 | ^^^^^^^^^^^^^
14 = note: `St` implements similarly named trait `m::Trait`, but not `Trait`
15help: this trait has no implementations, consider adding one
16 --> $DIR/similarly_named_trait.rs:1:1
17 |
18LL | trait Trait {}
19 | ^^^^^^^^^^^
20note: required by a bound in `func`
21 --> $DIR/similarly_named_trait.rs:13:12
22 |
23LL | fn func<T: Trait>(_: T) {}
24 | ^^^^^ required by this bound in `func`
25
26error[E0277]: the trait bound `St: TraitWithParam<St>` is not satisfied
27 --> $DIR/similarly_named_trait.rs:24:11
28 |
29LL | func2(m::St);
30 | ----- ^^^^^ unsatisfied trait bound
31 | |
32 | required by a bound introduced by this call
33 |
34help: the trait `TraitWithParam<St>` is not implemented for `St`
35 --> $DIR/similarly_named_trait.rs:7:5
36 |
37LL | pub struct St;
38 | ^^^^^^^^^^^^^
39 = note: `St` implements similarly named trait `m::TraitWithParam`, but not `TraitWithParam<St>`
40help: this trait has no implementations, consider adding one
41 --> $DIR/similarly_named_trait.rs:2:1
42 |
43LL | trait TraitWithParam<T> {}
44 | ^^^^^^^^^^^^^^^^^^^^^^^
45note: required by a bound in `func2`
46 --> $DIR/similarly_named_trait.rs:16:13
47 |
48LL | fn func2<T: TraitWithParam<T>> (_: T) {}
49 | ^^^^^^^^^^^^^^^^^ required by this bound in `func2`
50
51error: aborting due to 2 previous errors
52
53For more information about this error, try `rustc --explain E0277`.
tests/ui/type/type-mismatch-same-crate-name.rs+4-6
......@@ -11,24 +11,22 @@
1111
1212fn main() {
1313 let foo2 = {extern crate crate_a2 as a; a::Foo};
14 //~^ NOTE one type comes from crate `crate_a2` used here, which is renamed locally to `a`
15 //~| NOTE one trait comes from crate `crate_a2` used here, which is renamed locally to `a`
1614 let bar2 = {extern crate crate_a2 as a; a::bar()};
1715 {
1816 extern crate crate_a1 as a;
19 //~^ NOTE one type comes from crate `crate_a1` used here, which is renamed locally to `a`
20 //~| NOTE one trait comes from crate `crate_a1` used here, which is renamed locally to `a`
2117 a::try_foo(foo2);
2218 //~^ ERROR mismatched types
2319 //~| NOTE expected `main::a::Foo`, found a different `main::a::Foo`
2420 //~| NOTE arguments to this function are incorrect
25 //~| NOTE two types coming from two different crates are different types even if they look the same
21 //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph
2622 //~| NOTE function defined here
23 //~| HELP you can use `cargo tree` to explore your dependency tree
2724 a::try_bar(bar2);
2825 //~^ ERROR mismatched types
2926 //~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar`
3027 //~| NOTE arguments to this function are incorrect
31 //~| NOTE two types coming from two different crates are different types even if they look the same
28 //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph
3229 //~| NOTE function defined here
30 //~| HELP you can use `cargo tree` to explore your dependency tree
3331 }
3432}
tests/ui/type/type-mismatch-same-crate-name.stderr+14-28
......@@ -1,29 +1,22 @@
11error[E0308]: mismatched types
2 --> $DIR/type-mismatch-same-crate-name.rs:21:20
2 --> $DIR/type-mismatch-same-crate-name.rs:17:20
33 |
44LL | a::try_foo(foo2);
55 | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo`
66 | |
77 | arguments to this function are incorrect
88 |
9note: two types coming from two different crates are different types even if they look the same
10 --> $DIR/auxiliary/crate_a2.rs:1:1
9note: there are multiple different versions of crate `crate_a1` in the dependency graph
10 --> $DIR/auxiliary/crate_a1.rs:1:1
1111 |
1212LL | pub struct Foo;
13 | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo`
13 | ^^^^^^^^^^^^^^ this is the expected type
1414 |
15 ::: $DIR/auxiliary/crate_a1.rs:1:1
15 ::: $DIR/auxiliary/crate_a2.rs:1:1
1616 |
1717LL | pub struct Foo;
18 | ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo`
19 |
20 ::: $DIR/type-mismatch-same-crate-name.rs:13:17
21 |
22LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
23 | --------------------------- one type comes from crate `crate_a2` used here, which is renamed locally to `a`
24...
25LL | extern crate crate_a1 as a;
26 | --------------------------- one type comes from crate `crate_a1` used here, which is renamed locally to `a`
18 | -------------- this is the found type
19 = help: you can use `cargo tree` to explore your dependency tree
2720note: function defined here
2821 --> $DIR/auxiliary/crate_a1.rs:10:8
2922 |
......@@ -31,31 +24,24 @@ LL | pub fn try_foo(x: Foo){}
3124 | ^^^^^^^
3225
3326error[E0308]: mismatched types
34 --> $DIR/type-mismatch-same-crate-name.rs:27:20
27 --> $DIR/type-mismatch-same-crate-name.rs:24:20
3528 |
3629LL | a::try_bar(bar2);
3730 | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
3831 | |
3932 | arguments to this function are incorrect
4033 |
41note: two types coming from two different crates are different types even if they look the same
42 --> $DIR/auxiliary/crate_a2.rs:3:1
34note: there are multiple different versions of crate `crate_a1` in the dependency graph
35 --> $DIR/auxiliary/crate_a1.rs:3:1
4336 |
4437LL | pub trait Bar {}
45 | ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar`
38 | ^^^^^^^^^^^^^ this is the expected trait
4639 |
47 ::: $DIR/auxiliary/crate_a1.rs:3:1
40 ::: $DIR/auxiliary/crate_a2.rs:3:1
4841 |
4942LL | pub trait Bar {}
50 | ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar`
51 |
52 ::: $DIR/type-mismatch-same-crate-name.rs:13:17
53 |
54LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
55 | --------------------------- one trait comes from crate `crate_a2` used here, which is renamed locally to `a`
56...
57LL | extern crate crate_a1 as a;
58 | --------------------------- one trait comes from crate `crate_a1` used here, which is renamed locally to `a`
43 | ------------- this is the found trait
44 = help: you can use `cargo tree` to explore your dependency tree
5945note: function defined here
6046 --> $DIR/auxiliary/crate_a1.rs:11:8
6147 |
tests/ui/union/issue-81199.stderr+1
......@@ -16,6 +16,7 @@ error[E0277]: the trait bound `T: Pointee` is not satisfied
1616LL | components: PtrComponents<T>,
1717 | ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T`
1818 |
19 = note: `T` implements similarly named trait `std::ptr::Pointee`, but not `Pointee`
1920note: required by a bound in `PtrComponents`
2021 --> $DIR/issue-81199.rs:11:25
2122 |