diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index de1a2e6a577..fd16363a1db 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -615,9 +615,10 @@ fn path_generic_args( } let report_path_match = |err: &mut Diagnostic, did1: DefId, did2: DefId| { - // Only external crates, if either is from a local - // module we could have false positives - if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { + // Only report definitions from different crates. If both definitions + // are from a local module we could have false positives, e.g. + // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; + if did1.krate != did2.krate { let abs_path = |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]); @@ -629,10 +630,16 @@ fn path_generic_args( }; if same_path().unwrap_or(false) { let crate_name = self.tcx.crate_name(did1.krate); - err.note(&format!( - "perhaps two different versions of crate `{}` are being used?", - crate_name - )); + let msg = if did1.is_local() || did2.is_local() { + format!( + "the crate `{crate_name}` is compiled multiple times, possibly with different configurations" + ) + } else { + format!( + "perhaps two different versions of crate `{crate_name}` are being used?" + ) + }; + err.note(msg); } } }; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a127875b55d..4d9010d3c4b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -278,13 +278,15 @@ fn should_compile_successfully(&self, pm: Option) -> bool { Incremental => { let revision = self.revision.expect("incremental tests require a list of revisions"); - if revision.starts_with("rpass") || revision.starts_with("rfail") { + if revision.starts_with("cpass") + || revision.starts_with("rpass") + || revision.starts_with("rfail") + { true } else if revision.starts_with("cfail") { - // FIXME: would be nice if incremental revs could start with "cpass" pm.is_some() } else { - panic!("revision name must begin with rpass, rfail, or cfail"); + panic!("revision name must begin with cpass, rpass, rfail, or cfail"); } } mode => panic!("unimplemented for mode {:?}", mode), @@ -384,6 +386,20 @@ fn check_correct_failure_status(&self, proc_res: &ProcRes) { } } + fn run_cpass_test(&self) { + let emit_metadata = self.should_emit_metadata(self.pass_mode()); + let proc_res = self.compile_test(WillExecute::No, emit_metadata); + + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + + // FIXME(#41968): Move this check to tidy? + if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { + self.fatal("compile-pass tests with expected warnings should be moved to ui/"); + } + } + fn run_rpass_test(&self) { let emit_metadata = self.should_emit_metadata(self.pass_mode()); let should_run = self.run_if_enabled(); @@ -393,17 +409,15 @@ fn run_rpass_test(&self) { self.fatal_proc_rec("compilation failed!", &proc_res); } + // FIXME(#41968): Move this check to tidy? + if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { + self.fatal("run-pass tests with expected warnings should be moved to ui/"); + } + if let WillExecute::Disabled = should_run { return; } - // FIXME(#41968): Move this check to tidy? - let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - assert!( - expected_errors.is_empty(), - "run-pass tests with expected warnings should be moved to ui/" - ); - let proc_res = self.exec_compiled_test(); if !proc_res.status.success() { self.fatal_proc_rec("test run failed!", &proc_res); @@ -2913,10 +2927,11 @@ fn init_incremental_test(&self) { fn run_incremental_test(&self) { // Basic plan for a test incremental/foo/bar.rs: // - load list of revisions rpass1, cfail2, rpass3 - // - each should begin with `rpass`, `cfail`, or `rfail` - // - if `rpass`, expect compile and execution to succeed + // - each should begin with `cpass`, `rpass`, `cfail`, or `rfail` + // - if `cpass`, expect compilation to succeed, don't execute + // - if `rpass`, expect compilation and execution to succeed // - if `cfail`, expect compilation to fail - // - if `rfail`, expect execution to fail + // - if `rfail`, expect compilation to succeed and execution to fail // - create a directory build/foo/bar.incremental // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1 // - because name of revision starts with "rpass", expect success @@ -2940,7 +2955,12 @@ fn run_incremental_test(&self) { print!("revision={:?} props={:#?}", revision, self.props); } - if revision.starts_with("rpass") { + if revision.starts_with("cpass") { + if self.props.should_ice { + self.fatal("can only use should-ice in cfail tests"); + } + self.run_cpass_test(); + } else if revision.starts_with("rpass") { if self.props.should_ice { self.fatal("can only use should-ice in cfail tests"); } @@ -2953,7 +2973,7 @@ fn run_incremental_test(&self) { } else if revision.starts_with("cfail") { self.run_cfail_test(); } else { - self.fatal("revision name must begin with rpass, rfail, or cfail"); + self.fatal("revision name must begin with cpass, rpass, rfail, or cfail"); } } diff --git a/tests/incremental/auxiliary/circular-dependencies-aux.rs b/tests/incremental/auxiliary/circular-dependencies-aux.rs new file mode 100644 index 00000000000..0e74eb1b2f2 --- /dev/null +++ b/tests/incremental/auxiliary/circular-dependencies-aux.rs @@ -0,0 +1,10 @@ +// edition: 2021 +// compile-flags: --crate-type lib --extern circular_dependencies={{build-base}}/circular-dependencies/libcircular_dependencies.rmeta --emit dep-info,metadata + +use circular_dependencies::Foo; + +pub fn consume_foo(_: Foo) {} + +pub fn produce_foo() -> Foo { + Foo +} diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs new file mode 100644 index 00000000000..10673066a9d --- /dev/null +++ b/tests/incremental/circular-dependencies.rs @@ -0,0 +1,37 @@ +// ignore-tidy-linelength +// revisions: cpass1 cfail2 +// edition: 2021 +// [cpass1] compile-flags: --crate-type lib --emit dep-info,metadata +// [cfail2] aux-build: circular-dependencies-aux.rs +// [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies + +pub struct Foo; +//[cfail2]~^ NOTE `Foo` is defined in the current crate +//[cfail2]~| NOTE `Foo` is defined in the current crate +//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` +//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` + +pub fn consume_foo(_: Foo) {} +//[cfail2]~^ NOTE function defined here + +pub fn produce_foo() -> Foo { + Foo +} + +#[test] +fn test() { + aux::consume_foo(produce_foo()); + //[cfail2]~^ ERROR mismatched types [E0308] + //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo` + //[cfail2]~| NOTE arguments to this function are incorrect + //[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types + //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations + //[cfail2]~| NOTE function defined here + + consume_foo(aux::produce_foo()); + //[cfail2]~^ ERROR mismatched types [E0308] + //[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo` + //[cfail2]~| NOTE arguments to this function are incorrect + //[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types + //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations +}