diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 495f592baa812..f22f185670447 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -13,9 +13,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{ - Applicability, Diag, DiagStyledString, MultiSpan, StashKey, pluralize, struct_span_code_err, -}; +use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -1572,11 +1570,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() - || restrict_type_params - || suggested_derive - || self.lookup_alternative_tuple_impls(&mut err, &unsatisfied_predicates) - { + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive { } else { self.suggest_traits_to_import( &mut err, @@ -1753,119 +1747,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit() } - /// If the predicate failure is caused by an unmet bound on a tuple, recheck if the bound would - /// succeed if all the types on the tuple had no borrows. This is a common problem for libraries - /// like Bevy and ORMs, which rely heavily on traits being implemented on tuples. - fn lookup_alternative_tuple_impls( - &self, - err: &mut Diag<'_>, - unsatisfied_predicates: &[( - ty::Predicate<'tcx>, - Option>, - Option>, - )], - ) -> bool { - let mut found_tuple = false; - for (pred, root, _ob) in unsatisfied_predicates { - let mut preds = vec![pred]; - if let Some(root) = root { - // We will look at both the current predicate and the root predicate that caused it - // to be needed. If calling something like `<(A, &B)>::default()`, then `pred` is - // `&B: Default` and `root` is `(A, &B): Default`, which is the one we are checking - // for further down, so we check both. - preds.push(root); - } - for pred in preds { - if let Some(clause) = pred.as_clause() - && let Some(clause) = clause.as_trait_clause() - && let ty = clause.self_ty().skip_binder() - && let ty::Tuple(types) = ty.kind() - { - let path = clause.skip_binder().trait_ref.print_only_trait_path(); - let def_id = clause.def_id(); - let ty = Ty::new_tup( - self.tcx, - self.tcx.mk_type_list_from_iter(types.iter().map(|ty| ty.peel_refs())), - ); - let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| { - if param.index == 0 { - ty.into() - } else { - self.infcx.var_for_def(DUMMY_SP, param) - } - }); - if self - .infcx - .type_implements_trait(def_id, args, self.param_env) - .must_apply_modulo_regions() - { - // "`Trait` is implemented for `(A, B)` but not for `(A, &B)`" - let mut msg = DiagStyledString::normal(format!("`{path}` ")); - msg.push_highlighted("is"); - msg.push_normal(" implemented for `("); - let len = types.len(); - for (i, t) in types.iter().enumerate() { - msg.push( - format!("{}", with_forced_trimmed_paths!(t.peel_refs())), - t.peel_refs() != t, - ); - if i < len - 1 { - msg.push_normal(", "); - } - } - msg.push_normal(")` but "); - msg.push_highlighted("not"); - msg.push_normal(" for `("); - for (i, t) in types.iter().enumerate() { - msg.push( - format!("{}", with_forced_trimmed_paths!(t)), - t.peel_refs() != t, - ); - if i < len - 1 { - msg.push_normal(", "); - } - } - msg.push_normal(")`"); - - // Find the span corresponding to the impl that was found to point at it. - if let Some(impl_span) = self - .tcx - .all_impls(def_id) - .filter(|&impl_def_id| { - let header = self.tcx.impl_trait_header(impl_def_id).unwrap(); - let trait_ref = header.trait_ref.instantiate( - self.tcx, - self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), - ); - - let value = ty::fold_regions(self.tcx, ty, |_, _| { - self.tcx.lifetimes.re_erased - }); - // FIXME: Don't bother dealing with non-lifetime binders here... - if value.has_escaping_bound_vars() { - return false; - } - self.infcx.can_eq(ty::ParamEnv::empty(), trait_ref.self_ty(), value) - && header.polarity == ty::ImplPolarity::Positive - }) - .map(|impl_def_id| self.tcx.def_span(impl_def_id)) - .next() - { - err.highlighted_span_note(impl_span, msg.0); - } else { - err.highlighted_note(msg.0); - } - found_tuple = true; - } - // If `pred` was already on the tuple, we don't need to look at the root - // obligation too. - break; - } - } - } - found_tuple - } - /// If an appropriate error source is not found, check method chain for possible candidates fn lookup_segments_chain_for_no_match_method( &self, diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 3565c11249ad1..7e8a41457d411 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -153,7 +153,12 @@ fn prepare_vtable_segments_inner<'tcx, T>( // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level. while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() { - let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id); + // We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a + // vptr for supertraits that have no methods, but that themselves have supertraits + // with methods, so we check if any transitive supertrait has entries here (this includes + // the trait itself). + let has_entries = ty::elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id) + .any(|def_id| has_own_existential_vtable_entries(tcx, def_id)); segment_visitor(VtblSegment::TraitOwnEntries { trait_ref: inner_most_trait_ref, diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index b310db2dac485..4643ced9ad818 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1263,6 +1263,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", ))] pub fn lock(&self) -> io::Result<()> { @@ -1275,6 +1276,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", )))] pub fn lock(&self) -> io::Result<()> { @@ -1286,6 +1288,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", ))] pub fn lock_shared(&self) -> io::Result<()> { @@ -1298,6 +1301,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", )))] pub fn lock_shared(&self) -> io::Result<()> { @@ -1309,6 +1313,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", ))] pub fn try_lock(&self) -> Result<(), TryLockError> { @@ -1329,6 +1334,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", )))] pub fn try_lock(&self) -> Result<(), TryLockError> { @@ -1343,6 +1349,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", ))] pub fn try_lock_shared(&self) -> Result<(), TryLockError> { @@ -1363,6 +1370,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", )))] pub fn try_lock_shared(&self) -> Result<(), TryLockError> { @@ -1377,6 +1385,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", ))] pub fn unlock(&self) -> io::Result<()> { @@ -1389,6 +1398,7 @@ impl File { target_os = "fuchsia", target_os = "linux", target_os = "netbsd", + target_os = "openbsd", target_vendor = "apple", )))] pub fn unlock(&self) -> io::Result<()> { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 59541bf12def0..30cbcc05c429f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1416,8 +1416,8 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect if builder.config.llvm_enzyme { cargo.env("LLVM_ENZYME", "1"); } - let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target }); - cargo.env("LLVM_CONFIG", &llvm_config); + let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target }); + cargo.env("LLVM_CONFIG", &host_llvm_config); // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by @@ -2012,14 +2012,52 @@ impl Step for Assemble { if builder.config.llvm_enabled(target_compiler.host) { trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled"); - let llvm::LlvmResult { llvm_config, .. } = - builder.ensure(llvm::Llvm { target: target_compiler.host }); + let target = target_compiler.host; + let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target }); if !builder.config.dry_run() && builder.config.llvm_tools_enabled { trace!("LLVM tools enabled"); - let llvm_bin_dir = - command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); - let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); + let host_llvm_bin_dir = command(&host_llvm_config) + .arg("--bindir") + .run_capture_stdout(builder) + .stdout() + .trim() + .to_string(); + + let llvm_bin_dir = if target == builder.host_target { + PathBuf::from(host_llvm_bin_dir) + } else { + // If we're cross-compiling, we cannot run the target llvm-config in order to + // figure out where binaries are located. We thus have to guess. + let external_llvm_config = builder + .config + .target_config + .get(&target) + .and_then(|t| t.llvm_config.clone()); + if let Some(external_llvm_config) = external_llvm_config { + // If we have an external LLVM, just hope that the bindir is the directory + // where the LLVM config is located + external_llvm_config.parent().unwrap().to_path_buf() + } else { + // If we have built LLVM locally, then take the path of the host bindir + // relative to its output build directory, and then apply it to the target + // LLVM output build directory. + let host_llvm_out = builder.llvm_out(builder.host_target); + let target_llvm_out = builder.llvm_out(target); + if let Ok(relative_path) = + Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out) + { + target_llvm_out.join(relative_path) + } else { + // This is the most desperate option, just replace the host target with + // the actual target in the directory path... + PathBuf::from( + host_llvm_bin_dir + .replace(&*builder.host_target.triple, &target.triple), + ) + } + } + }; // Since we've already built the LLVM tools, install them to the sysroot. // This is the equivalent of installing the `llvm-tools-preview` component via diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 4699813abf42a..5cfaa6a7c7707 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2176,11 +2176,12 @@ fn maybe_install_llvm( builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary); } !builder.config.dry_run() - } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) = - llvm::prebuilt_llvm_config(builder, target, true) + } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { + host_llvm_config, .. + }) = llvm::prebuilt_llvm_config(builder, target, true) { trace!("LLVM already built, installing LLVM files"); - let mut cmd = command(llvm_config); + let mut cmd = command(host_llvm_config); cmd.arg("--libfiles"); builder.verbose(|| println!("running {cmd:?}")); let files = cmd.run_capture_stdout(builder).stdout(); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index b2056f5cf3786..8191a77b5c363 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -31,7 +31,7 @@ use crate::{CLang, GitRepo, Kind, trace}; pub struct LlvmResult { /// Path to llvm-config binary. /// NB: This is always the host llvm-config! - pub llvm_config: PathBuf, + pub host_llvm_config: PathBuf, /// Path to LLVM cmake directory for the target. pub llvm_cmake_dir: PathBuf, } @@ -111,14 +111,14 @@ pub fn prebuilt_llvm_config( && let Some(ref s) = config.llvm_config { check_llvm_version(builder, s); - let llvm_config = s.to_path_buf(); - let mut llvm_cmake_dir = llvm_config.clone(); + let host_llvm_config = s.to_path_buf(); + let mut llvm_cmake_dir = host_llvm_config.clone(); llvm_cmake_dir.pop(); llvm_cmake_dir.pop(); llvm_cmake_dir.push("lib"); llvm_cmake_dir.push("cmake"); llvm_cmake_dir.push("llvm"); - return LlvmBuildStatus::AlreadyBuilt(LlvmResult { llvm_config, llvm_cmake_dir }); + return LlvmBuildStatus::AlreadyBuilt(LlvmResult { host_llvm_config, llvm_cmake_dir }); } if handle_submodule_when_needed { @@ -143,7 +143,7 @@ pub fn prebuilt_llvm_config( }; let llvm_cmake_dir = out_dir.join("lib/cmake/llvm"); - let res = LlvmResult { llvm_config: build_llvm_config, llvm_cmake_dir }; + let res = LlvmResult { host_llvm_config: build_llvm_config, llvm_cmake_dir }; static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { @@ -488,11 +488,11 @@ impl Step for Llvm { // https://llvm.org/docs/HowToCrossCompileLLVM.html if !builder.config.is_host_target(target) { - let LlvmResult { llvm_config, .. } = + let LlvmResult { host_llvm_config, .. } = builder.ensure(Llvm { target: builder.config.host_target }); if !builder.config.dry_run() { let llvm_bindir = - command(&llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); + command(&host_llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); let host_bin = Path::new(llvm_bindir.trim()); cfg.define( "LLVM_TABLEGEN", @@ -501,7 +501,7 @@ impl Step for Llvm { // LLVM_NM is required for cross compiling using MSVC cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION)); } - cfg.define("LLVM_CONFIG_PATH", llvm_config); + cfg.define("LLVM_CONFIG_PATH", host_llvm_config); if builder.config.llvm_clang { let build_bin = builder.llvm_out(builder.config.host_target).join("build").join("bin"); @@ -543,7 +543,7 @@ impl Step for Llvm { // Helper to find the name of LLVM's shared library on darwin and linux. let find_llvm_lib_name = |extension| { - let major = get_llvm_version_major(builder, &res.llvm_config); + let major = get_llvm_version_major(builder, &res.host_llvm_config); match &llvm_version_suffix { Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.{extension}"), None => format!("libLLVM-{major}.{extension}"), @@ -929,7 +929,7 @@ impl Step for Enzyme { } let target = self.target; - let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: self.target }); + let LlvmResult { host_llvm_config, .. } = builder.ensure(Llvm { target: self.target }); static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { @@ -983,7 +983,7 @@ impl Step for Enzyme { cfg.out_dir(&out_dir) .profile(profile) - .env("LLVM_CONFIG_REAL", &llvm_config) + .env("LLVM_CONFIG_REAL", &host_llvm_config) .define("LLVM_ENABLE_ASSERTIONS", "ON") .define("ENZYME_EXTERNAL_SHARED_LIB", "ON") .define("LLVM_DIR", builder.llvm_out(target)); @@ -1019,13 +1019,13 @@ impl Step for Lld { } let target = self.target; - let LlvmResult { llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target }); + let LlvmResult { host_llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target }); // The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path // we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin` // subfolder. We check if that's the case, and if LLD's binary already exists there next to // `llvm-config`: if so, we can use it instead of building LLVM/LLD from source. - let ci_llvm_bin = llvm_config.parent().unwrap(); + let ci_llvm_bin = host_llvm_config.parent().unwrap(); if ci_llvm_bin.is_dir() && ci_llvm_bin.file_name().unwrap() == "bin" { let lld_path = ci_llvm_bin.join(exe("lld", target)); if lld_path.exists() { @@ -1108,7 +1108,7 @@ impl Step for Lld { // Use the host llvm-tblgen binary. cfg.define( "LLVM_TABLEGEN_EXE", - llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION), + host_llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION), ); } @@ -1149,7 +1149,7 @@ impl Step for Sanitizers { return runtimes; } - let LlvmResult { llvm_config, .. } = + let LlvmResult { host_llvm_config, .. } = builder.ensure(Llvm { target: builder.config.host_target }); static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); @@ -1189,7 +1189,7 @@ impl Step for Sanitizers { cfg.define("COMPILER_RT_BUILD_XRAY", "OFF"); cfg.define("COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"); cfg.define("COMPILER_RT_USE_LIBCXX", "OFF"); - cfg.define("LLVM_CONFIG_PATH", &llvm_config); + cfg.define("LLVM_CONFIG_PATH", &host_llvm_config); if self.target.contains("ohos") { cfg.define("COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 119fa4237bcfe..9f0d1cc88923a 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1976,12 +1976,14 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let mut llvm_components_passed = false; let mut copts_passed = false; if builder.config.llvm_enabled(compiler.host) { - let llvm::LlvmResult { llvm_config, .. } = + let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target: builder.config.host_target }); if !builder.config.dry_run() { - let llvm_version = get_llvm_version(builder, &llvm_config); - let llvm_components = - command(&llvm_config).arg("--components").run_capture_stdout(builder).stdout(); + let llvm_version = get_llvm_version(builder, &host_llvm_config); + let llvm_components = command(&host_llvm_config) + .arg("--components") + .run_capture_stdout(builder) + .stdout(); // Remove trailing newline from llvm-config output. cmd.arg("--llvm-version") .arg(llvm_version.trim()) @@ -1999,7 +2001,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // rustc args as a workaround. if !builder.config.dry_run() && suite.ends_with("fulldeps") { let llvm_libdir = - command(&llvm_config).arg("--libdir").run_capture_stdout(builder).stdout(); + command(&host_llvm_config).arg("--libdir").run_capture_stdout(builder).stdout(); let link_llvm = if target.is_msvc() { format!("-Clink-arg=-LIBPATH:{llvm_libdir}") } else { @@ -2013,7 +2015,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // tools. Pass the path to run-make tests so they can use them. // (The coverage-run tests also need these tools to process // coverage reports.) - let llvm_bin_path = llvm_config + let llvm_bin_path = host_llvm_config .parent() .expect("Expected llvm-config to be contained in directory"); assert!(llvm_bin_path.is_dir()); diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 0caeb328811aa..9050f4069e857 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -19,6 +19,7 @@ pub const VENDOR_DIR: &str = "vendor"; pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'static str>)> { [ ("src/tools/cargo/Cargo.toml", vec!["src/tools/cargo"]), + ("src/tools/clippy/clippy_test_deps/Cargo.toml", vec![]), ("src/tools/rust-analyzer/Cargo.toml", vec![]), ("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]), ("compiler/rustc_codegen_gcc/Cargo.toml", vec![]), diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 96289a63785e2..deee041490bd2 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1613,11 +1613,15 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s /// /// Note that this returns `None` if LLVM is disabled, or if we're in a /// check build or dry-run, where there's no need to build all of LLVM. + /// + /// FIXME(@kobzol) + /// **WARNING**: This actually returns the **HOST** LLVM config, not LLVM config for the given + /// *target*. pub fn llvm_config(&self, target: TargetSelection) -> Option { if self.config.llvm_enabled(target) && self.kind != Kind::Check && !self.config.dry_run() { - let llvm::LlvmResult { llvm_config, .. } = self.ensure(llvm::Llvm { target }); - if llvm_config.is_file() { - return Some(llvm_config); + let llvm::LlvmResult { host_llvm_config, .. } = self.ensure(llvm::Llvm { target }); + if host_llvm_config.is_file() { + return Some(host_llvm_config); } } None diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f012645b7ef5c..a24128790097c 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -494,14 +494,14 @@ fn test_prebuilt_llvm_config_path_resolution() { false, ) .llvm_result() - .llvm_config + .host_llvm_config .clone(); let actual = drop_win_disk_prefix_if_present(actual); assert_eq!(expected, actual); let actual = prebuilt_llvm_config(&builder, builder.config.host_target, false) .llvm_result() - .llvm_config + .host_llvm_config .clone(); let actual = drop_win_disk_prefix_if_present(actual); assert_eq!(expected, actual); @@ -519,7 +519,7 @@ fn test_prebuilt_llvm_config_path_resolution() { let actual = prebuilt_llvm_config(&builder, builder.config.host_target, false) .llvm_result() - .llvm_config + .host_llvm_config .clone(); let expected = builder .out @@ -542,7 +542,7 @@ fn test_prebuilt_llvm_config_path_resolution() { let actual = prebuilt_llvm_config(&builder, builder.config.host_target, false) .llvm_result() - .llvm_config + .host_llvm_config .clone(); let expected = builder .out diff --git a/tests/ui/methods/missing-bound-on-tuple.rs b/tests/ui/methods/missing-bound-on-tuple.rs deleted file mode 100644 index 25deabf59267b..0000000000000 --- a/tests/ui/methods/missing-bound-on-tuple.rs +++ /dev/null @@ -1,39 +0,0 @@ -trait WorksOnDefault { - fn do_something() {} -} - -impl WorksOnDefault for T {} -//~^ NOTE the following trait bounds were not satisfied -//~| NOTE unsatisfied trait bound introduced here - -trait Foo {} - -trait WorksOnFoo { - fn do_be_do() {} -} - -impl WorksOnFoo for T {} -//~^ NOTE the following trait bounds were not satisfied -//~| NOTE unsatisfied trait bound introduced here - -impl Foo for (A, B, C) {} -//~^ NOTE `Foo` is implemented for `(i32, u32, String)` -impl Foo for i32 {} -impl Foo for &i32 {} -impl Foo for u32 {} -impl Foo for String {} - -fn main() { - let _success = <(i32, u32, String)>::do_something(); - let _failure = <(i32, &u32, String)>::do_something(); //~ ERROR E0599 - //~^ NOTE `Default` is implemented for `(i32, u32, String)` - //~| NOTE function or associated item cannot be called on - let _success = <(i32, u32, String)>::do_be_do(); - let _failure = <(i32, &u32, String)>::do_be_do(); //~ ERROR E0599 - //~^ NOTE function or associated item cannot be called on - let _success = <(i32, u32, String)>::default(); - let _failure = <(i32, &u32, String)>::default(); //~ ERROR E0599 - //~^ NOTE `Default` is implemented for `(i32, u32, String)` - //~| NOTE function or associated item cannot be called on - //~| NOTE the following trait bounds were not satisfied -} diff --git a/tests/ui/methods/missing-bound-on-tuple.stderr b/tests/ui/methods/missing-bound-on-tuple.stderr deleted file mode 100644 index f3e0897e5e645..0000000000000 --- a/tests/ui/methods/missing-bound-on-tuple.stderr +++ /dev/null @@ -1,58 +0,0 @@ -error[E0599]: the function or associated item `do_something` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied - --> $DIR/missing-bound-on-tuple.rs:28:43 - | -LL | let _failure = <(i32, &u32, String)>::do_something(); - | ^^^^^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds - | -note: the following trait bounds were not satisfied: - `&(i32, &u32, String): Default` - `&mut (i32, &u32, String): Default` - `(i32, &u32, String): Default` - --> $DIR/missing-bound-on-tuple.rs:5:9 - | -LL | impl WorksOnDefault for T {} - | ^^^^^^^ -------------- - - | | - | unsatisfied trait bound introduced here -note: `Default` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)` - --> $SRC_DIR/core/src/tuple.rs:LL:COL - = note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0599]: the function or associated item `do_be_do` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied - --> $DIR/missing-bound-on-tuple.rs:32:43 - | -LL | let _failure = <(i32, &u32, String)>::do_be_do(); - | ^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds - | -note: the following trait bounds were not satisfied: - `&(i32, &u32, String): Foo` - `&mut (i32, &u32, String): Foo` - `(i32, &u32, String): Foo` - --> $DIR/missing-bound-on-tuple.rs:15:9 - | -LL | impl WorksOnFoo for T {} - | ^^^ ---------- - - | | - | unsatisfied trait bound introduced here -note: `Foo` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)` - --> $DIR/missing-bound-on-tuple.rs:19:1 - | -LL | impl Foo for (A, B, C) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0599]: the function or associated item `default` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied - --> $DIR/missing-bound-on-tuple.rs:35:43 - | -LL | let _failure = <(i32, &u32, String)>::default(); - | ^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `&u32: Default` - which is required by `(i32, &u32, String): Default` -note: `Default` is implemented for `(i32, u32, String)` but not for `(i32, &u32, String)` - --> $SRC_DIR/core/src/tuple.rs:LL:COL - = note: this error originates in the macro `tuple_impls` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/tuple-suggestions-issue-142488.rs b/tests/ui/methods/tuple-suggestions-issue-142488.rs new file mode 100644 index 0000000000000..f6c58fce9a1a7 --- /dev/null +++ b/tests/ui/methods/tuple-suggestions-issue-142488.rs @@ -0,0 +1,48 @@ +// Regression test for issue #142488, a diagnostics ICE when trying to suggest missing methods +// present in similar tuple types. +// This is a few of the MCVEs from the issues and its many duplicates. + +// 1 +fn main() { + for a in x { + //~^ ERROR: cannot find value `x` in this scope + (a,).to_string() + //~^ ERROR: the method `to_string` exists for tuple + } +} + +// 2 +trait Trait { + fn meth(self); +} + +impl Trait for (T, U) { + fn meth(self) {} +} + +fn mcve2() { + ((), std::collections::HashMap::new()).meth() + //~^ ERROR: the method `meth` exists for tuple +} + +// 3 +trait I {} + +struct Struct; +impl I for Struct {} + +trait Tr { + fn f(self) -> (A,) + where + Self: Sized, + { + loop {} + } +} + +impl Tr for T where T: I {} + +fn mcve3() { + Struct.f().f(); + //~^ ERROR: the method `f` exists for tuple +} diff --git a/tests/ui/methods/tuple-suggestions-issue-142488.stderr b/tests/ui/methods/tuple-suggestions-issue-142488.stderr new file mode 100644 index 0000000000000..f9363bb216f43 --- /dev/null +++ b/tests/ui/methods/tuple-suggestions-issue-142488.stderr @@ -0,0 +1,61 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/tuple-suggestions-issue-142488.rs:7:14 + | +LL | for a in x { + | ^ not found in this scope + +error[E0599]: the method `to_string` exists for tuple `(_,)`, but its trait bounds were not satisfied + --> $DIR/tuple-suggestions-issue-142488.rs:9:14 + | +LL | (a,).to_string() + | ^^^^^^^^^ method cannot be called on `(_,)` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `(_,): std::fmt::Display` + which is required by `(_,): ToString` + +error[E0599]: the method `meth` exists for tuple `((), HashMap<_, _>)`, but its trait bounds were not satisfied + --> $DIR/tuple-suggestions-issue-142488.rs:24:44 + | +LL | ((), std::collections::HashMap::new()).meth() + | ^^^^ method cannot be called on `((), HashMap<_, _>)` due to unsatisfied trait bounds + | +note: trait bound `HashMap<_, _>: Trait` was not satisfied + --> $DIR/tuple-suggestions-issue-142488.rs:19:12 + | +LL | impl Trait for (T, U) { + | ^^^^^ ----- ------ + | | + | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `Trait` defines an item `meth`, perhaps you need to implement it + --> $DIR/tuple-suggestions-issue-142488.rs:15:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ + +error[E0599]: the method `f` exists for tuple `(_,)`, but its trait bounds were not satisfied + --> $DIR/tuple-suggestions-issue-142488.rs:46:16 + | +LL | Struct.f().f(); + | ^ method cannot be called on `(_,)` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&(_,): I` + `&mut (_,): I` + `(_,): I` + --> $DIR/tuple-suggestions-issue-142488.rs:43:27 + | +LL | impl Tr for T where T: I {} + | -- - ^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `Tr` defines an item `f`, perhaps you need to implement it + --> $DIR/tuple-suggestions-issue-142488.rs:34:1 + | +LL | trait Tr { + | ^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr new file mode 100644 index 0000000000000..d90a786498e16 --- /dev/null +++ b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr @@ -0,0 +1,16 @@ +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::one - shim(reify)), + Method(::two - shim(reify)), + TraitVPtr(), + TraitVPtr(), + ] + --> $DIR/empty-supertrait-with-nonempty-supersupertrait.rs:40:1 + | +LL | type T = dyn OneTwo; + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs new file mode 100644 index 0000000000000..507cda63868cd --- /dev/null +++ b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs @@ -0,0 +1,49 @@ +//@ revisions: run dump +//@[run] run-pass +//@[dump] check-fail +//! Regression test for #145752 +//! Ensure that `OneTwo` contains a vptr for `TwoAgain` +#![allow(unused)] +#![cfg_attr(dump, feature(rustc_attrs))] + +trait One { + fn one(&self) { + panic!("don't call this"); + } +} +impl One for () {} + +trait Two { + fn two(&self) { + println!("good"); + } +} +impl Two for () {} + +trait TwoAgain: Two {} +impl TwoAgain for T {} + +trait OneTwo: One + TwoAgain {} +impl OneTwo for T {} + +fn main() { + (&()).two(); + (&() as &dyn OneTwo).two(); + (&() as &dyn OneTwo as &dyn Two).two(); + + // these two used to panic because they called `one` due to #145752 + (&() as &dyn OneTwo as &dyn TwoAgain).two(); + (&() as &dyn OneTwo as &dyn TwoAgain as &dyn Two).two(); +} + +#[cfg_attr(dump, rustc_dump_vtable)] +type T = dyn OneTwo; +//[dump]~^ ERROR vtable entries: [ +//[dump]~| ERROR MetadataDropInPlace, +//[dump]~| ERROR MetadataSize, +//[dump]~| ERROR MetadataAlign, +//[dump]~| ERROR Method(::one - shim(reify)), +//[dump]~| ERROR Method(::two - shim(reify)), +//[dump]~| ERROR TraitVPtr(), +//[dump]~| ERROR TraitVPtr(), +//[dump]~| ERROR ] diff --git a/tests/ui/traits/vtable/multiple-auto.rs b/tests/ui/traits/vtable/multiple-auto.rs new file mode 100644 index 0000000000000..87ee865868bb7 --- /dev/null +++ b/tests/ui/traits/vtable/multiple-auto.rs @@ -0,0 +1,50 @@ +// Related to +// +// This test makes sure that multiple auto traits can reuse the +// same pointer for upcasting (e.g. `Send`/`Sync`) + +#![crate_type = "lib"] +#![feature(rustc_attrs, auto_traits)] + +// Markers +auto trait M0 {} +auto trait M1 {} +auto trait M2 {} + +// Just a trait with a method +trait T { + fn method(&self) {} +} + +trait A: M0 + M1 + M2 + T {} + +trait B: M0 + M1 + T + M2 {} + +trait C: M0 + T + M1 + M2 {} + +trait D: T + M0 + M1 + M2 {} + +struct S; + +impl M0 for S {} +impl M1 for S {} +impl M2 for S {} +impl T for S {} + +#[rustc_dump_vtable] +impl A for S {} +//~^ ERROR vtable entries + +#[rustc_dump_vtable] +impl B for S {} +//~^ ERROR vtable entries + +#[rustc_dump_vtable] +impl C for S {} +//~^ ERROR vtable entries + +#[rustc_dump_vtable] +impl D for S {} +//~^ ERROR vtable entries + +fn main() {} diff --git a/tests/ui/traits/vtable/multiple-auto.stderr b/tests/ui/traits/vtable/multiple-auto.stderr new file mode 100644 index 0000000000000..0a7c3ebd36da2 --- /dev/null +++ b/tests/ui/traits/vtable/multiple-auto.stderr @@ -0,0 +1,46 @@ +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::method), + ] + --> $DIR/multiple-auto.rs:35:1 + | +LL | impl A for S {} + | ^^^^^^^^^^^^ + +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::method), + ] + --> $DIR/multiple-auto.rs:39:1 + | +LL | impl B for S {} + | ^^^^^^^^^^^^ + +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::method), + ] + --> $DIR/multiple-auto.rs:43:1 + | +LL | impl C for S {} + | ^^^^^^^^^^^^ + +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::method), + ] + --> $DIR/multiple-auto.rs:47:1 + | +LL | impl D for S {} + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors +