diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index ec53d9f53eb83..85bff45408140 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -10,7 +10,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; -use rustc_session::config::{self, OutputFilenames, PrintRequest}; +use rustc_session::config::{self, CrateType, OutputFilenames, PrintRequest}; use rustc_span::Symbol; use super::CodegenObject; @@ -62,6 +62,18 @@ pub trait CodegenBackend { } } + fn supported_crate_types(&self, _sess: &Session) -> Vec { + vec![ + CrateType::Executable, + CrateType::Dylib, + CrateType::Rlib, + CrateType::Staticlib, + CrateType::Cdylib, + CrateType::ProcMacro, + CrateType::Sdylib, + ] + } + fn print_passes(&self) {} fn print_version(&self) {} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 9529ef2b99ad3..c926a7c742a0a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -686,7 +686,8 @@ fn print_crate_info( }; let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess); let crate_name = passes::get_crate_name(sess, attrs); - let crate_types = collect_crate_types(sess, attrs); + let crate_types = + collect_crate_types(sess, &codegen_backend.supported_crate_types(sess), attrs); for &style in &crate_types { let fname = rustc_session::output::filename_for_input( sess, style, crate_name, &t_outputs, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index a02990fe4abaf..870a7b6563860 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -242,6 +242,16 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( owner_def_id: LocalDefId, opaque_types_from: DefiningScopeKind, ) -> Ty<'tcx> { + // When an opaque type is stranded, its hidden type cannot be inferred + // so we should not continue. + if !tcx.opaque_types_defined_by(owner_def_id).contains(&def_id) { + let opaque_type_span = tcx.def_span(def_id); + let guar = tcx + .dcx() + .span_delayed_bug(opaque_type_span, "cannot infer type for stranded opaque type"); + return Ty::new_error(tcx, guar); + } + match opaque_types_from { DefiningScopeKind::HirTypeck => { let tables = tcx.typeck(owner_def_id); diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 975bf1d18622a..f73cc4d43e8c5 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -116,8 +116,6 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize}; use rustc_middle::bug; -use rustc_session::config::CrateType; -use rustc_session::output::collect_crate_types; use rustc_session::{Session, StableCrateId}; use rustc_span::Symbol; use tracing::debug; @@ -212,7 +210,11 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu /// The garbage collection will take care of it. /// /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph -pub(crate) fn prepare_session_directory(sess: &Session, crate_name: Symbol) { +pub(crate) fn prepare_session_directory( + sess: &Session, + crate_name: Symbol, + stable_crate_id: StableCrateId, +) { if sess.opts.incremental.is_none() { return; } @@ -222,7 +224,7 @@ pub(crate) fn prepare_session_directory(sess: &Session, crate_name: Symbol) { debug!("prepare_session_directory"); // {incr-comp-dir}/{crate-name-and-disambiguator} - let crate_dir = crate_path(sess, crate_name); + let crate_dir = crate_path(sess, crate_name, stable_crate_id); debug!("crate-dir: {}", crate_dir.display()); create_dir(sess, &crate_dir, "crate"); @@ -595,17 +597,9 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path(sess: &Session, crate_name: Symbol) -> PathBuf { +fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); - let crate_types = collect_crate_types(sess, &[]); - let stable_crate_id = StableCrateId::new( - crate_name, - crate_types.contains(&CrateType::Executable), - sess.opts.cg.metadata.clone(), - sess.cfg_version, - ); - let crate_name = format!("{crate_name}-{}", stable_crate_id.as_u64().to_base_fixed_len(CASE_INSENSITIVE)); incr_dir.join(crate_name) diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 0e646b136c452..1b2a283a1a0d1 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -10,8 +10,8 @@ use rustc_middle::dep_graph::{DepGraph, DepsType, SerializedDepGraph, WorkProduc use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::Decodable; use rustc_serialize::opaque::MemDecoder; -use rustc_session::Session; use rustc_session::config::IncrementalStateAssertion; +use rustc_session::{Session, StableCrateId}; use rustc_span::Symbol; use tracing::{debug, warn}; @@ -208,9 +208,14 @@ pub fn load_query_result_cache(sess: &Session) -> Option { /// Setups the dependency graph by loading an existing graph from disk and set up streaming of a /// new graph to an incremental session directory. -pub fn setup_dep_graph(sess: &Session, crate_name: Symbol, deps: &DepsType) -> DepGraph { +pub fn setup_dep_graph( + sess: &Session, + crate_name: Symbol, + stable_crate_id: StableCrateId, + deps: &DepsType, +) -> DepGraph { // `load_dep_graph` can only be called after `prepare_session_directory`. - prepare_session_directory(sess, crate_name); + prepare_session_directory(sess, crate_name, stable_crate_id); let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess, deps)); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d9b4492441eb0..58ed71a970776 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -926,7 +926,11 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs); let crate_name = get_crate_name(sess, &pre_configured_attrs); - let crate_types = collect_crate_types(sess, &pre_configured_attrs); + let crate_types = collect_crate_types( + sess, + &compiler.codegen_backend.supported_crate_types(sess), + &pre_configured_attrs, + ); let stable_crate_id = StableCrateId::new( crate_name, crate_types.contains(&CrateType::Executable), @@ -937,7 +941,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( let outputs = util::build_output_filenames(&pre_configured_attrs, sess); let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() }; - let dep_graph = setup_dep_graph(sess, crate_name, &dep_type); + let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id, &dep_type); let cstore = FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index be2fd0787b98a..5e9cb42365049 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -354,6 +354,14 @@ impl CodegenBackend for DummyCodegenBackend { "dummy" } + fn supported_crate_types(&self, _sess: &Session) -> Vec { + // This includes bin despite failing on the link step to ensure that you + // can still get the frontend handling for binaries. For all library + // like crate types cargo will fallback to rlib unless you specifically + // say that only a different crate type must be used. + vec![CrateType::Rlib, CrateType::Executable] + } + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { Box::new(CodegenResults { modules: vec![], @@ -380,12 +388,16 @@ impl CodegenBackend for DummyCodegenBackend { ) { // JUSTIFICATION: TyCtxt no longer available here #[allow(rustc::bad_opt_access)] - if sess.opts.crate_types.iter().any(|&crate_type| crate_type != CrateType::Rlib) { + if let Some(&crate_type) = codegen_results + .crate_info + .crate_types + .iter() + .find(|&&crate_type| crate_type != CrateType::Rlib) + { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal(format!( - "crate type {} not supported by the dummy codegen backend", - sess.opts.crate_types[0], + "crate type {crate_type} not supported by the dummy codegen backend" )); } diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index cba70b5bd5d17..a48a4f649da1d 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -174,7 +174,11 @@ pub fn categorize_crate_type(s: Symbol) -> Option { Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) } -pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { +pub fn collect_crate_types( + session: &Session, + backend_crate_types: &[CrateType], + attrs: &[ast::Attribute], +) -> Vec { // If we're generating a test executable, then ignore all other output // styles at all other locations if session.opts.test { @@ -219,7 +223,12 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec), @@ -322,7 +321,6 @@ impl FromStr for EmitType { fn from_str(s: &str) -> Result { match s { - "unversioned-shared-resources" => Ok(Self::Unversioned), "toolchain-shared-resources" => Ok(Self::Toolchain), "invocation-specific" => Ok(Self::InvocationSpecific), "dep-info" => Ok(Self::DepInfo(None)), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 820b2392e07ce..dd6378b25def7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -567,7 +567,7 @@ fn opts() -> Vec { "", "emit", "Comma separated list of types of output for rustdoc to emit", - "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info]", + "[toolchain-shared-resources,invocation-specific,dep-info]", ), opt(Unstable, FlagMulti, "", "no-run", "Compile doctests without running them", ""), opt( diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs index 911ceb3adca4b..bd868d4fd19e2 100644 --- a/tests/run-make/emit-shared-files/rmake.rs +++ b/tests/run-make/emit-shared-files/rmake.rs @@ -68,7 +68,7 @@ fn main() { rustdoc() .arg("-Zunstable-options") - .arg("--emit=toolchain-shared-resources,unversioned-shared-resources") + .arg("--emit=toolchain-shared-resources") .out_dir("all-shared") .arg("--resource-suffix=-xxx") .args(&["--extend-css", "z.css"]) diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index badbc0b6d15b7..3afe0ca3ca8f5 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -150,7 +150,7 @@ Options: --generate-redirect-map Generate JSON file at the top level instead of generating HTML redirection files - --emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info] + --emit [toolchain-shared-resources,invocation-specific,dep-info] Comma separated list of types of output for rustdoc to emit --no-run Compile doctests without running them diff --git a/tests/ui/traits/next-solver/opaques/stranded_opaque.rs b/tests/ui/traits/next-solver/opaques/stranded_opaque.rs new file mode 100644 index 0000000000000..f600a1496b99c --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/stranded_opaque.rs @@ -0,0 +1,50 @@ +//@ compile-flags: -Znext-solver +#![feature(type_alias_impl_trait)] +use std::future::Future; + +// Test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/235 + +// These are cases where an opaque types become "stranded" due to +// some errors. Make sure we don't ICE in either case. + +// Case 1: `impl Send` is stranded +fn foo() -> impl ?Future { + //~^ ERROR bound modifier `?` can only be applied to `Sized` + //~| ERROR bound modifier `?` can only be applied to `Sized` + () +} + +// Case 2: `Assoc = impl Trait` is stranded +trait Trait {} +impl Trait for i32 {} + +fn produce() -> impl Trait { + //~^ ERROR associated type `Assoc` not found for `Trait` + //~| ERROR associated type `Assoc` not found for `Trait` + 16 +} + +// Case 3: `impl Trait` is stranded +fn ill_formed_string() -> String { + //~^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied + String::from("a string") +} + +// Case 4: TAIT variant of Case 1 to 3 +type Foo = impl ?Future; +//~^ ERROR unconstrained opaque type +//~| ERROR unconstrained opaque type +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` + +type Produce = impl Trait; +//~^ ERROR unconstrained opaque type +//~| ERROR unconstrained opaque type +//~| ERROR associated type `Assoc` not found for `Trait` +//~| ERROR associated type `Assoc` not found for `Trait` + +type IllFormedString = String; +//~^ ERROR unconstrained opaque type +//~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/stranded_opaque.stderr b/tests/ui/traits/next-solver/opaques/stranded_opaque.stderr new file mode 100644 index 0000000000000..bcb357eb69531 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/stranded_opaque.stderr @@ -0,0 +1,116 @@ +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/stranded_opaque.rs:11:18 + | +LL | fn foo() -> impl ?Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/stranded_opaque.rs:21:28 + | +LL | fn produce() -> impl Trait { + | ^^^^^ associated type `Assoc` not found + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/stranded_opaque.rs:28:27 + | +LL | fn ill_formed_string() -> String { + | ^^^^^^------------ help: remove the unnecessary generics + | | + | expected 0 generic arguments + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/stranded_opaque.rs:46:25 + | +LL | type IllFormedString = String; + | ^^^^^^------------ help: remove the unnecessary generics + | | + | expected 0 generic arguments + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/stranded_opaque.rs:11:18 + | +LL | fn foo() -> impl ?Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/stranded_opaque.rs:21:28 + | +LL | fn produce() -> impl Trait { + | ^^^^^ associated type `Assoc` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: unconstrained opaque type + --> $DIR/stranded_opaque.rs:34:12 + | +LL | type Foo = impl ?Future; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same crate + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/stranded_opaque.rs:34:17 + | +LL | type Foo = impl ?Future; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/stranded_opaque.rs:34:17 + | +LL | type Foo = impl ?Future; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: unconstrained opaque type + --> $DIR/stranded_opaque.rs:34:34 + | +LL | type Foo = impl ?Future; + | ^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same crate + +error: unconstrained opaque type + --> $DIR/stranded_opaque.rs:40:17 + | +LL | type Produce = impl Trait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Produce` must be used in combination with a concrete type within the same crate + +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/stranded_opaque.rs:40:28 + | +LL | type Produce = impl Trait; + | ^^^^^ associated type `Assoc` not found + +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/stranded_opaque.rs:40:28 + | +LL | type Produce = impl Trait; + | ^^^^^ associated type `Assoc` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: unconstrained opaque type + --> $DIR/stranded_opaque.rs:40:36 + | +LL | type Produce = impl Trait; + | ^^^^^^^^^^ + | + = note: `Produce` must be used in combination with a concrete type within the same crate + +error: unconstrained opaque type + --> $DIR/stranded_opaque.rs:46:32 + | +LL | type IllFormedString = String; + | ^^^^^^^^^^ + | + = note: `IllFormedString` must be used in combination with a concrete type within the same crate + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0107, E0220. +For more information about an error, try `rustc --explain E0107`.