| author | bors <bors@rust-lang.org> 2025-11-11 21:54:08 UTC |
| committer | bors <bors@rust-lang.org> 2025-11-11 21:54:08 UTC |
| log | 11339a0ef5ed586bb7ea4f85a9b7287880caac3a |
| tree | 159a4fe10f7c1e6f246d4d7113c4baef7e534804 |
| parent | 25d319a0f656ee8faa7a534da299e76e96068a40 |
| parent | c8c04663c56fa99ac973f103ade5660650875bbd |
Add a diagnostic for similarly named traits
cc rust-lang/rust#133123
This is a first proposal, suggestions are welcome15 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> { |
| 4212 | 4212 | err: &mut Diag<'_>, |
| 4213 | 4213 | item_def_id: DefId, |
| 4214 | 4214 | hir_id: hir::HirId, |
| 4215 | rcvr_ty: Option<Ty<'_>>, | |
| 4215 | rcvr_ty: Option<Ty<'tcx>>, | |
| 4216 | 4216 | ) -> bool { |
| 4217 | 4217 | let hir_id = self.tcx.parent_hir_id(hir_id); |
| 4218 | 4218 | let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false }; |
| ... | ... | @@ -4223,49 +4223,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 4223 | 4223 | if !self.tcx.is_trait(trait_def_id) { |
| 4224 | 4224 | return false; |
| 4225 | 4225 | } |
| 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 { | |
| 4238 | 4227 | 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) | |
| 4269 | 4236 | } |
| 4270 | 4237 | |
| 4271 | 4238 | /// 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; |
| 51 | 51 | use std::{cmp, fmt, iter}; |
| 52 | 52 | |
| 53 | 53 | use rustc_abi::ExternAbi; |
| 54 | use rustc_ast::join_path_syms; | |
| 55 | 54 | use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; |
| 56 | use rustc_errors::{ | |
| 57 | Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize, | |
| 58 | }; | |
| 55 | use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; | |
| 59 | 56 | use rustc_hir::def::DefKind; |
| 60 | 57 | use rustc_hir::def_id::DefId; |
| 61 | 58 | use rustc_hir::intravisit::Visitor; |
| ... | ... | @@ -66,15 +63,12 @@ use rustc_middle::bug; |
| 66 | 63 | use rustc_middle::dep_graph::DepContext; |
| 67 | 64 | use rustc_middle::traits::PatternOriginExpr; |
| 68 | 65 | use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; |
| 69 | use rustc_middle::ty::print::{ | |
| 70 | PrintError, PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths, | |
| 71 | }; | |
| 66 | use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths}; | |
| 72 | 67 | use rustc_middle::ty::{ |
| 73 | 68 | self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, |
| 74 | 69 | TypeVisitableExt, |
| 75 | 70 | }; |
| 76 | use rustc_span::def_id::LOCAL_CRATE; | |
| 77 | use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, Symbol, sym}; | |
| 71 | use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, sym}; | |
| 78 | 72 | use tracing::{debug, instrument}; |
| 79 | 73 | |
| 80 | 74 | use crate::error_reporting::TypeErrCtxt; |
| ... | ... | @@ -216,201 +210,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 216 | 210 | |
| 217 | 211 | /// Adds a note if the types come from similarly named crates |
| 218 | 212 | 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 | }; | |
| 414 | 213 | match terr { |
| 415 | 214 | TypeError::Sorts(ref exp_found) => { |
| 416 | 215 | // if they are both "path types", there's a chance of ambiguity |
| ... | ... | @@ -418,11 +217,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 418 | 217 | if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) = |
| 419 | 218 | (exp_found.expected.kind(), exp_found.found.kind()) |
| 420 | 219 | { |
| 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 | ); | |
| 422 | 227 | } |
| 423 | 228 | } |
| 424 | 229 | 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 | ); | |
| 426 | 237 | } |
| 427 | 238 | _ => (), // FIXME(#22750) handle traits and stuff |
| 428 | 239 | } |
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs+95-148| ... | ... | @@ -468,7 +468,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 468 | 468 | span, |
| 469 | 469 | leaf_trait_predicate, |
| 470 | 470 | ); |
| 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); | |
| 472 | 472 | self.note_adt_version_mismatch(&mut err, leaf_trait_predicate); |
| 473 | 473 | self.suggest_remove_await(&obligation, &mut err); |
| 474 | 474 | self.suggest_derive(&obligation, &mut err, leaf_trait_predicate); |
| ... | ... | @@ -1974,115 +1974,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 1974 | 1974 | impl_candidates |
| 1975 | 1975 | }; |
| 1976 | 1976 | |
| 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 | ||
| 2086 | 1977 | if let [single] = &impl_candidates { |
| 2087 | 1978 | // If we have a single implementation, try to unify it with the trait ref |
| 2088 | 1979 | // that failed. This should uncover a better hint for what *is* implemented. |
| ... | ... | @@ -2478,10 +2369,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 2478 | 2369 | } |
| 2479 | 2370 | } |
| 2480 | 2371 | |
| 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( | |
| 2485 | 2373 | &self, |
| 2486 | 2374 | err: &mut Diag<'_>, |
| 2487 | 2375 | trait_pred: ty::PolyTraitPredicate<'tcx>, |
| ... | ... | @@ -2492,46 +2380,33 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 2492 | 2380 | trait_def_id, |
| 2493 | 2381 | trait_pred.skip_binder().self_ty(), |
| 2494 | 2382 | |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)); | |
| 2496 | 2386 | }, |
| 2497 | 2387 | ); |
| 2498 | 2388 | trait_impls |
| 2499 | 2389 | }; |
| 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 | ) | |
| 2528 | 2397 | } |
| 2529 | 2398 | |
| 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 | ) { | |
| 2531 | 2405 | 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); | |
| 2535 | 2410 | } |
| 2536 | 2411 | |
| 2537 | 2412 | fn note_adt_version_mismatch( |
| ... | ... | @@ -2592,8 +2467,80 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 2592 | 2467 | |
| 2593 | 2468 | for (similar_item, _) in similar_items { |
| 2594 | 2469 | 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; | |
| 2596 | 2542 | } |
| 2543 | self.check_same_name_different_path(err, obligation, trait_pred) | |
| 2597 | 2544 | } |
| 2598 | 2545 | |
| 2599 | 2546 | /// 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 @@ |
| 1 | 1 | pub mod ambiguity; |
| 2 | 2 | pub mod call_kind; |
| 3 | mod fulfillment_errors; | |
| 3 | pub mod fulfillment_errors; | |
| 4 | 4 | pub mod on_unimplemented; |
| 5 | 5 | pub mod on_unimplemented_condition; |
| 6 | 6 | pub mod on_unimplemented_format; |
| ... | ... | @@ -10,6 +10,7 @@ pub mod suggestions; |
| 10 | 10 | use std::{fmt, iter}; |
| 11 | 11 | |
| 12 | 12 | use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; |
| 13 | use rustc_data_structures::unord::UnordSet; | |
| 13 | 14 | use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; |
| 14 | 15 | use rustc_hir::def_id::{DefId, LocalDefId}; |
| 15 | 16 | use rustc_hir::intravisit::Visitor; |
| ... | ... | @@ -21,7 +22,7 @@ use rustc_infer::traits::{ |
| 21 | 22 | }; |
| 22 | 23 | use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; |
| 23 | 24 | use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; |
| 24 | use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span}; | |
| 25 | use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span, Symbol}; | |
| 25 | 26 | use tracing::{info, instrument}; |
| 26 | 27 | |
| 27 | 28 | pub use self::overflow::*; |
| ... | ... | @@ -351,6 +352,80 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 351 | 352 | FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle), |
| 352 | 353 | } |
| 353 | 354 | } |
| 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 | } | |
| 354 | 429 | } |
| 355 | 430 | |
| 356 | 431 | /// 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 @@ |
| 6 | 6 | //@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies |
| 7 | 7 | |
| 8 | 8 | pub 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 | |
| 15 | 15 | |
| 16 | 16 | pub fn consume_foo(_: Foo) {} |
| 17 | 17 | //[cfail2]~^ NOTE function defined here |
| ... | ... | @@ -27,8 +27,6 @@ fn test() { |
| 27 | 27 | //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo` |
| 28 | 28 | //[cfail2]~| NOTE arguments to this function are incorrect |
| 29 | 29 | //[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` | |
| 32 | 30 | |
| 33 | 31 | consume_foo(aux::produce_foo()); |
| 34 | 32 | //[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 |
| 7 | 7 | note: there are multiple different versions of crate `foo` in the dependency graph |
| 8 | 8 | --> foo-current.rs:7:1 |
| 9 | 9 | | |
| 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 | |
| 15 | 10 | 7 | pub trait Trait {} |
| 16 | | ^^^^^^^^^^^^^^^ this is the required trait | |
| 11 | | ^^^^^^^^^^^^^^^ this is the expected trait | |
| 17 | 12 | | |
| 18 | 13 | ::: foo-prev.rs:X:Y |
| 19 | 14 | | |
| 20 | 4 | pub struct Struct; | |
| 21 | | ----------------- this type doesn't implement the required trait | |
| 22 | 15 | 5 | pub trait Trait {} |
| 23 | 16 | | --------------- 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 | |
| 25 | 17 | = help: you can use `cargo tree` to explore your dependency tree |
| 18 | help: the trait `Trait` is implemented for `Struct` | |
| 19 | --> foo-current.rs:8:1 | |
| 20 | | | |
| 21 | 8 | impl Trait for Struct {} | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^ | |
| 26 | 23 | note: required by a bound in `check_trait` |
| 27 | 24 | --> foo-current.rs:10:19 |
| 28 | 25 | | |
tests/run-make/crate-loading/multiple-dep-versions.stderr+22-63| ... | ... | @@ -9,26 +9,19 @@ LL | do_something(Type); |
| 9 | 9 | note: there are multiple different versions of crate `dependency` in the dependency graph |
| 10 | 10 | --> replaced |
| 11 | 11 | | |
| 12 | LL | pub struct Type(pub i32); | |
| 13 | | --------------- this type implements the required trait | |
| 14 | 12 | LL | pub trait Trait { |
| 15 | | ^^^^^^^^^^^^^^^ this is the required trait | |
| 16 | | | |
| 17 | ::: replaced | |
| 18 | | | |
| 19 | LL | extern crate dep_2_reexport; | |
| 20 | | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` | |
| 21 | LL | 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 | |
| 23 | 14 | | |
| 24 | 15 | ::: replaced |
| 25 | 16 | | |
| 26 | LL | pub struct Type; | |
| 27 | | --------------- this type doesn't implement the required trait | |
| 28 | 17 | LL | pub trait Trait { |
| 29 | 18 | | --------------- 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 | |
| 31 | 19 | = help: you can use `cargo tree` to explore your dependency tree |
| 20 | help: the trait `Trait` is implemented for `dependency::Type` | |
| 21 | --> replaced | |
| 22 | | | |
| 23 | LL | impl Trait for Type { | |
| 24 | | ^^^^^^^^^^^^^^^^^^^ | |
| 32 | 25 | note: required by a bound in `do_something` |
| 33 | 26 | --> replaced |
| 34 | 27 | | |
| ... | ... | @@ -45,19 +38,13 @@ note: there are multiple different versions of crate `dependency` in the depende |
| 45 | 38 | --> replaced |
| 46 | 39 | | |
| 47 | 40 | LL | pub trait Trait { |
| 48 | | ^^^^^^^^^^^^^^^ this is the trait that is needed | |
| 49 | LL | fn foo(&self); | |
| 50 | | -------------- the method is available for `dep_2_reexport::Type` here | |
| 51 | | | |
| 52 | ::: replaced | |
| 53 | | | |
| 54 | LL | 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 | |
| 56 | 42 | | |
| 57 | 43 | ::: replaced |
| 58 | 44 | | |
| 59 | 45 | LL | pub trait Trait { |
| 60 | 46 | | --------------- this is the trait that was imported |
| 47 | = help: you can use `cargo tree` to explore your dependency tree | |
| 61 | 48 | |
| 62 | 49 | error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope |
| 63 | 50 | --> replaced |
| ... | ... | @@ -69,20 +56,13 @@ note: there are multiple different versions of crate `dependency` in the depende |
| 69 | 56 | --> replaced |
| 70 | 57 | | |
| 71 | 58 | LL | pub trait Trait { |
| 72 | | ^^^^^^^^^^^^^^^ this is the trait that is needed | |
| 73 | LL | fn foo(&self); | |
| 74 | LL | fn bar(); | |
| 75 | | --------- the associated function is available for `dep_2_reexport::Type` here | |
| 76 | | | |
| 77 | ::: replaced | |
| 78 | | | |
| 79 | LL | 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 | |
| 81 | 60 | | |
| 82 | 61 | ::: replaced |
| 83 | 62 | | |
| 84 | 63 | LL | pub trait Trait { |
| 85 | 64 | | --------------- this is the trait that was imported |
| 65 | = help: you can use `cargo tree` to explore your dependency tree | |
| 86 | 66 | |
| 87 | 67 | error[E0277]: the trait bound `OtherType: Trait` is not satisfied |
| 88 | 68 | --> replaced |
| ... | ... | @@ -96,25 +76,18 @@ note: there are multiple different versions of crate `dependency` in the depende |
| 96 | 76 | --> replaced |
| 97 | 77 | | |
| 98 | 78 | LL | pub trait Trait { |
| 99 | | ^^^^^^^^^^^^^^^ this is the required trait | |
| 100 | | | |
| 101 | ::: replaced | |
| 102 | | | |
| 103 | LL | extern crate dep_2_reexport; | |
| 104 | | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` | |
| 105 | LL | extern crate dependency; | |
| 106 | | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate | |
| 107 | | | |
| 108 | ::: replaced | |
| 109 | | | |
| 110 | LL | pub struct OtherType; | |
| 111 | | -------------------- this type doesn't implement the required trait | |
| 79 | | ^^^^^^^^^^^^^^^ this is the expected trait | |
| 112 | 80 | | |
| 113 | 81 | ::: replaced |
| 114 | 82 | | |
| 115 | 83 | LL | pub trait Trait { |
| 116 | 84 | | --------------- this is the found trait |
| 117 | 85 | = help: you can use `cargo tree` to explore your dependency tree |
| 86 | help: the trait `Trait` is implemented for `dependency::Type` | |
| 87 | --> replaced | |
| 88 | | | |
| 89 | LL | impl Trait for Type { | |
| 90 | | ^^^^^^^^^^^^^^^^^^^ | |
| 118 | 91 | note: required by a bound in `do_something` |
| 119 | 92 | --> replaced |
| 120 | 93 | | |
| ... | ... | @@ -129,23 +102,16 @@ LL | do_something_type(Type); |
| 129 | 102 | | | |
| 130 | 103 | | arguments to this function are incorrect |
| 131 | 104 | | |
| 132 | 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 | |
| 105 | note: there are multiple different versions of crate `dependency` in the dependency graph | |
| 133 | 106 | --> replaced |
| 134 | 107 | | |
| 135 | 108 | LL | pub struct Type(pub i32); |
| 136 | | ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type` | |
| 109 | | ^^^^^^^^^^^^^^^ this is the expected type | |
| 137 | 110 | | |
| 138 | 111 | ::: replaced |
| 139 | 112 | | |
| 140 | 113 | LL | pub struct Type; |
| 141 | | ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type` | |
| 142 | | | |
| 143 | ::: replaced | |
| 144 | | | |
| 145 | LL | extern crate dep_2_reexport; | |
| 146 | | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` | |
| 147 | LL | 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 | |
| 149 | 115 | = help: you can use `cargo tree` to explore your dependency tree |
| 150 | 116 | note: function defined here |
| 151 | 117 | --> replaced |
| ... | ... | @@ -161,23 +127,16 @@ LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>); |
| 161 | 127 | | | |
| 162 | 128 | | arguments to this function are incorrect |
| 163 | 129 | | |
| 164 | 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 | |
| 130 | note: there are multiple different versions of crate `dependency` in the dependency graph | |
| 165 | 131 | --> replaced |
| 166 | 132 | | |
| 167 | 133 | LL | pub trait Trait2 {} |
| 168 | | ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2` | |
| 134 | | ^^^^^^^^^^^^^^^^ this is the expected trait | |
| 169 | 135 | | |
| 170 | 136 | ::: replaced |
| 171 | 137 | | |
| 172 | 138 | LL | pub trait Trait2 {} |
| 173 | | ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2` | |
| 174 | | | |
| 175 | ::: replaced | |
| 176 | | | |
| 177 | LL | extern crate dep_2_reexport; | |
| 178 | | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` | |
| 179 | LL | 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 | |
| 181 | 140 | = help: you can use `cargo tree` to explore your dependency tree |
| 182 | 141 | note: function defined here |
| 183 | 142 | --> replaced |
tests/run-make/duplicate-dependency/main.stderr+1-1| ... | ... | @@ -11,7 +11,7 @@ help: item with same name found |
| 11 | 11 | | |
| 12 | 12 | LL | pub struct Foo; |
| 13 | 13 | | ^^^^^^^^^^^^^^ |
| 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 | |
| 15 | 15 | = note: required for `Bar` to implement `Into<re_export_foo::foo::Foo>` |
| 16 | 16 | note: required by a bound in `into_foo` |
| 17 | 17 | --> $DIR/re-export-foo.rs:3:25 |
tests/ui/traits/bound/same-crate-name.rs+8-2| ... | ... | @@ -32,13 +32,15 @@ fn main() { |
| 32 | 32 | extern crate crate_a1 as a; |
| 33 | 33 | a::try_foo(foo); |
| 34 | 34 | //~^ 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 | |
| 37 | 37 | |
| 38 | 38 | // We don't want to see the "version mismatch" help message here |
| 39 | 39 | // because `implements_no_traits` has no impl for `Foo` |
| 40 | 40 | a::try_foo(implements_no_traits); |
| 41 | 41 | //~^ 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 | |
| 42 | 44 | |
| 43 | 45 | // We don't want to see the "version mismatch" help message here |
| 44 | 46 | // because `other_variant_implements_mismatched_trait` |
| ... | ... | @@ -46,6 +48,8 @@ fn main() { |
| 46 | 48 | // only for its `<usize>` variant. |
| 47 | 49 | a::try_foo(other_variant_implements_mismatched_trait); |
| 48 | 50 | //~^ 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 | |
| 49 | 53 | |
| 50 | 54 | // We don't want to see the "version mismatch" help message here |
| 51 | 55 | // because `ImplementsTraitForUsize` only has |
| ... | ... | @@ -53,5 +57,7 @@ fn main() { |
| 53 | 57 | a::try_foo(other_variant_implements_correct_trait); |
| 54 | 58 | //~^ ERROR E0277 |
| 55 | 59 | //~| 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 | |
| 56 | 62 | } |
| 57 | 63 | } |
tests/ui/traits/bound/same-crate-name.stderr+44-12| ... | ... | @@ -6,12 +6,17 @@ LL | a::try_foo(foo); |
| 6 | 6 | | | |
| 7 | 7 | | required by a bound introduced by this call |
| 8 | 8 | | |
| 9 | help: trait impl with same name found | |
| 10 | --> $DIR/auxiliary/crate_a2.rs:5:1 | |
| 9 | note: there are multiple different versions of crate `crate_a1` in the dependency graph | |
| 10 | --> $DIR/auxiliary/crate_a1.rs:1:1 | |
| 11 | 11 | | |
| 12 | LL | impl Bar for Foo {} | |
| 13 | | ^^^^^^^^^^^^^^^^ | |
| 14 | = note: perhaps two different versions of crate `crate_a2` are being used? | |
| 12 | LL | pub trait Bar {} | |
| 13 | | ^^^^^^^^^^^^^ this is the expected trait | |
| 14 | | | |
| 15 | ::: $DIR/auxiliary/crate_a2.rs:3:1 | |
| 16 | | | |
| 17 | LL | pub trait Bar {} | |
| 18 | | ------------- this is the found trait | |
| 19 | = help: you can use `cargo tree` to explore your dependency tree | |
| 15 | 20 | help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` |
| 16 | 21 | --> $DIR/auxiliary/crate_a1.rs:9:1 |
| 17 | 22 | | |
| ... | ... | @@ -31,6 +36,17 @@ LL | a::try_foo(implements_no_traits); |
| 31 | 36 | | | |
| 32 | 37 | | required by a bound introduced by this call |
| 33 | 38 | | |
| 39 | note: there are multiple different versions of crate `crate_a1` in the dependency graph | |
| 40 | --> $DIR/auxiliary/crate_a1.rs:1:1 | |
| 41 | | | |
| 42 | LL | pub trait Bar {} | |
| 43 | | ^^^^^^^^^^^^^ this is the expected trait | |
| 44 | | | |
| 45 | ::: $DIR/auxiliary/crate_a2.rs:3:1 | |
| 46 | | | |
| 47 | LL | pub trait Bar {} | |
| 48 | | ------------- this is the trait that was imported | |
| 49 | = help: you can use `cargo tree` to explore your dependency tree | |
| 34 | 50 | help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` |
| 35 | 51 | --> $DIR/auxiliary/crate_a1.rs:9:1 |
| 36 | 52 | | |
| ... | ... | @@ -43,19 +59,24 @@ LL | pub fn try_foo(x: impl Bar) {} |
| 43 | 59 | | ^^^ required by this bound in `try_foo` |
| 44 | 60 | |
| 45 | 61 | error[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 | |
| 47 | 63 | | |
| 48 | 64 | LL | a::try_foo(other_variant_implements_mismatched_trait); |
| 49 | 65 | | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>` |
| 50 | 66 | | | |
| 51 | 67 | | required by a bound introduced by this call |
| 52 | 68 | | |
| 53 | help: trait impl with same name found | |
| 54 | --> $DIR/auxiliary/crate_a2.rs:13:1 | |
| 69 | note: there are multiple different versions of crate `crate_a1` in the dependency graph | |
| 70 | --> $DIR/auxiliary/crate_a1.rs:1:1 | |
| 55 | 71 | | |
| 56 | LL | impl Bar for ImplementsWrongTraitConditionally<isize> {} | |
| 57 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 58 | = note: perhaps two different versions of crate `crate_a2` are being used? | |
| 72 | LL | pub trait Bar {} | |
| 73 | | ^^^^^^^^^^^^^ this is the expected trait | |
| 74 | | | |
| 75 | ::: $DIR/auxiliary/crate_a2.rs:3:1 | |
| 76 | | | |
| 77 | LL | pub trait Bar {} | |
| 78 | | ------------- this is the found trait | |
| 79 | = help: you can use `cargo tree` to explore your dependency tree | |
| 59 | 80 | help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` |
| 60 | 81 | --> $DIR/auxiliary/crate_a1.rs:9:1 |
| 61 | 82 | | |
| ... | ... | @@ -68,13 +89,24 @@ LL | pub fn try_foo(x: impl Bar) {} |
| 68 | 89 | | ^^^ required by this bound in `try_foo` |
| 69 | 90 | |
| 70 | 91 | error[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 | |
| 72 | 93 | | |
| 73 | 94 | LL | a::try_foo(other_variant_implements_correct_trait); |
| 74 | 95 | | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>` |
| 75 | 96 | | | |
| 76 | 97 | | required by a bound introduced by this call |
| 77 | 98 | | |
| 99 | note: there are multiple different versions of crate `crate_a1` in the dependency graph | |
| 100 | --> $DIR/auxiliary/crate_a1.rs:1:1 | |
| 101 | | | |
| 102 | LL | pub trait Bar {} | |
| 103 | | ^^^^^^^^^^^^^ this is the expected trait | |
| 104 | | | |
| 105 | ::: $DIR/auxiliary/crate_a2.rs:3:1 | |
| 106 | | | |
| 107 | LL | pub trait Bar {} | |
| 108 | | ------------- this is the trait that was imported | |
| 109 | = help: you can use `cargo tree` to explore your dependency tree | |
| 78 | 110 | help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` |
| 79 | 111 | --> $DIR/auxiliary/crate_a1.rs:9:1 |
| 80 | 112 | | |
tests/ui/traits/similarly_named_trait.rs created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | trait Trait {} //~ HELP this trait has no implementations, consider adding one | |
| 2 | trait TraitWithParam<T> {} //~ HELP this trait has no implementations, consider adding one | |
| 3 | ||
| 4 | mod 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 | ||
| 13 | fn func<T: Trait>(_: T) {} //~ NOTE required by a bound in `func` | |
| 14 | //~^ NOTE required by this bound in `func` | |
| 15 | ||
| 16 | fn func2<T: TraitWithParam<T>> (_: T) {} //~ NOTE required by a bound in `func2` | |
| 17 | //~^ NOTE required by this bound in `func2` | |
| 18 | ||
| 19 | fn 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 @@ |
| 1 | error[E0277]: the trait bound `St: Trait` is not satisfied | |
| 2 | --> $DIR/similarly_named_trait.rs:20:10 | |
| 3 | | | |
| 4 | LL | func(m::St); | |
| 5 | | ---- ^^^^^ unsatisfied trait bound | |
| 6 | | | | |
| 7 | | required by a bound introduced by this call | |
| 8 | | | |
| 9 | help: the trait `Trait` is not implemented for `St` | |
| 10 | --> $DIR/similarly_named_trait.rs:7:5 | |
| 11 | | | |
| 12 | LL | pub struct St; | |
| 13 | | ^^^^^^^^^^^^^ | |
| 14 | = note: `St` implements similarly named trait `m::Trait`, but not `Trait` | |
| 15 | help: this trait has no implementations, consider adding one | |
| 16 | --> $DIR/similarly_named_trait.rs:1:1 | |
| 17 | | | |
| 18 | LL | trait Trait {} | |
| 19 | | ^^^^^^^^^^^ | |
| 20 | note: required by a bound in `func` | |
| 21 | --> $DIR/similarly_named_trait.rs:13:12 | |
| 22 | | | |
| 23 | LL | fn func<T: Trait>(_: T) {} | |
| 24 | | ^^^^^ required by this bound in `func` | |
| 25 | ||
| 26 | error[E0277]: the trait bound `St: TraitWithParam<St>` is not satisfied | |
| 27 | --> $DIR/similarly_named_trait.rs:24:11 | |
| 28 | | | |
| 29 | LL | func2(m::St); | |
| 30 | | ----- ^^^^^ unsatisfied trait bound | |
| 31 | | | | |
| 32 | | required by a bound introduced by this call | |
| 33 | | | |
| 34 | help: the trait `TraitWithParam<St>` is not implemented for `St` | |
| 35 | --> $DIR/similarly_named_trait.rs:7:5 | |
| 36 | | | |
| 37 | LL | pub struct St; | |
| 38 | | ^^^^^^^^^^^^^ | |
| 39 | = note: `St` implements similarly named trait `m::TraitWithParam`, but not `TraitWithParam<St>` | |
| 40 | help: this trait has no implementations, consider adding one | |
| 41 | --> $DIR/similarly_named_trait.rs:2:1 | |
| 42 | | | |
| 43 | LL | trait TraitWithParam<T> {} | |
| 44 | | ^^^^^^^^^^^^^^^^^^^^^^^ | |
| 45 | note: required by a bound in `func2` | |
| 46 | --> $DIR/similarly_named_trait.rs:16:13 | |
| 47 | | | |
| 48 | LL | fn func2<T: TraitWithParam<T>> (_: T) {} | |
| 49 | | ^^^^^^^^^^^^^^^^^ required by this bound in `func2` | |
| 50 | ||
| 51 | error: aborting due to 2 previous errors | |
| 52 | ||
| 53 | For more information about this error, try `rustc --explain E0277`. |
tests/ui/type/type-mismatch-same-crate-name.rs+4-6| ... | ... | @@ -11,24 +11,22 @@ |
| 11 | 11 | |
| 12 | 12 | fn main() { |
| 13 | 13 | 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` | |
| 16 | 14 | let bar2 = {extern crate crate_a2 as a; a::bar()}; |
| 17 | 15 | { |
| 18 | 16 | 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` | |
| 21 | 17 | a::try_foo(foo2); |
| 22 | 18 | //~^ ERROR mismatched types |
| 23 | 19 | //~| NOTE expected `main::a::Foo`, found a different `main::a::Foo` |
| 24 | 20 | //~| 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 | |
| 26 | 22 | //~| NOTE function defined here |
| 23 | //~| HELP you can use `cargo tree` to explore your dependency tree | |
| 27 | 24 | a::try_bar(bar2); |
| 28 | 25 | //~^ ERROR mismatched types |
| 29 | 26 | //~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar` |
| 30 | 27 | //~| 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 | |
| 32 | 29 | //~| NOTE function defined here |
| 30 | //~| HELP you can use `cargo tree` to explore your dependency tree | |
| 33 | 31 | } |
| 34 | 32 | } |
tests/ui/type/type-mismatch-same-crate-name.stderr+14-28| ... | ... | @@ -1,29 +1,22 @@ |
| 1 | 1 | error[E0308]: mismatched types |
| 2 | --> $DIR/type-mismatch-same-crate-name.rs:21:20 | |
| 2 | --> $DIR/type-mismatch-same-crate-name.rs:17:20 | |
| 3 | 3 | | |
| 4 | 4 | LL | a::try_foo(foo2); |
| 5 | 5 | | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo` |
| 6 | 6 | | | |
| 7 | 7 | | arguments to this function are incorrect |
| 8 | 8 | | |
| 9 | note: two types coming from two different crates are different types even if they look the same | |
| 10 | --> $DIR/auxiliary/crate_a2.rs:1:1 | |
| 9 | note: there are multiple different versions of crate `crate_a1` in the dependency graph | |
| 10 | --> $DIR/auxiliary/crate_a1.rs:1:1 | |
| 11 | 11 | | |
| 12 | 12 | LL | pub struct Foo; |
| 13 | | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo` | |
| 13 | | ^^^^^^^^^^^^^^ this is the expected type | |
| 14 | 14 | | |
| 15 | ::: $DIR/auxiliary/crate_a1.rs:1:1 | |
| 15 | ::: $DIR/auxiliary/crate_a2.rs:1:1 | |
| 16 | 16 | | |
| 17 | 17 | LL | pub struct Foo; |
| 18 | | ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo` | |
| 19 | | | |
| 20 | ::: $DIR/type-mismatch-same-crate-name.rs:13:17 | |
| 21 | | | |
| 22 | LL | 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 | ... | |
| 25 | LL | 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 | |
| 27 | 20 | note: function defined here |
| 28 | 21 | --> $DIR/auxiliary/crate_a1.rs:10:8 |
| 29 | 22 | | |
| ... | ... | @@ -31,31 +24,24 @@ LL | pub fn try_foo(x: Foo){} |
| 31 | 24 | | ^^^^^^^ |
| 32 | 25 | |
| 33 | 26 | error[E0308]: mismatched types |
| 34 | --> $DIR/type-mismatch-same-crate-name.rs:27:20 | |
| 27 | --> $DIR/type-mismatch-same-crate-name.rs:24:20 | |
| 35 | 28 | | |
| 36 | 29 | LL | a::try_bar(bar2); |
| 37 | 30 | | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` |
| 38 | 31 | | | |
| 39 | 32 | | arguments to this function are incorrect |
| 40 | 33 | | |
| 41 | note: two types coming from two different crates are different types even if they look the same | |
| 42 | --> $DIR/auxiliary/crate_a2.rs:3:1 | |
| 34 | note: there are multiple different versions of crate `crate_a1` in the dependency graph | |
| 35 | --> $DIR/auxiliary/crate_a1.rs:3:1 | |
| 43 | 36 | | |
| 44 | 37 | LL | pub trait Bar {} |
| 45 | | ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar` | |
| 38 | | ^^^^^^^^^^^^^ this is the expected trait | |
| 46 | 39 | | |
| 47 | ::: $DIR/auxiliary/crate_a1.rs:3:1 | |
| 40 | ::: $DIR/auxiliary/crate_a2.rs:3:1 | |
| 48 | 41 | | |
| 49 | 42 | LL | pub trait Bar {} |
| 50 | | ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar` | |
| 51 | | | |
| 52 | ::: $DIR/type-mismatch-same-crate-name.rs:13:17 | |
| 53 | | | |
| 54 | LL | 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 | ... | |
| 57 | LL | 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 | |
| 59 | 45 | note: function defined here |
| 60 | 46 | --> $DIR/auxiliary/crate_a1.rs:11:8 |
| 61 | 47 | | |
tests/ui/union/issue-81199.stderr+1| ... | ... | @@ -16,6 +16,7 @@ error[E0277]: the trait bound `T: Pointee` is not satisfied |
| 16 | 16 | LL | components: PtrComponents<T>, |
| 17 | 17 | | ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T` |
| 18 | 18 | | |
| 19 | = note: `T` implements similarly named trait `std::ptr::Pointee`, but not `Pointee` | |
| 19 | 20 | note: required by a bound in `PtrComponents` |
| 20 | 21 | --> $DIR/issue-81199.rs:11:25 |
| 21 | 22 | | |