Skip to content
14 changes: 13 additions & 1 deletion compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -62,6 +62,18 @@ pub trait CodegenBackend {
}
}

fn supported_crate_types(&self, _sess: &Session) -> Vec<CrateType> {
vec![
CrateType::Executable,
CrateType::Dylib,
CrateType::Rlib,
CrateType::Staticlib,
CrateType::Cdylib,
CrateType::ProcMacro,
CrateType::Sdylib,
]
}

fn print_passes(&self) {}

fn print_version(&self) {}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
20 changes: 7 additions & 13 deletions compiler/rustc_incremental/src/persist/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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");

Expand Down Expand Up @@ -595,17 +597,9 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
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)
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_incremental/src/persist/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -208,9 +208,14 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache> {

/// 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));

Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,11 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> 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),
Expand All @@ -937,7 +941,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> 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 _);
Expand Down
18 changes: 15 additions & 3 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,14 @@ impl CodegenBackend for DummyCodegenBackend {
"dummy"
}

fn supported_crate_types(&self, _sess: &Session) -> Vec<CrateType> {
// 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<dyn Any> {
Box::new(CodegenResults {
modules: vec![],
Expand All @@ -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"
));
}

Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_session/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,11 @@ pub fn categorize_crate_type(s: Symbol) -> Option<CrateType> {
Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1)
}

pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<CrateType> {
pub fn collect_crate_types(
session: &Session,
backend_crate_types: &[CrateType],
attrs: &[ast::Attribute],
) -> Vec<CrateType> {
// If we're generating a test executable, then ignore all other output
// styles at all other locations
if session.opts.test {
Expand Down Expand Up @@ -219,7 +223,12 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
}

base.retain(|crate_type| {
if invalid_output_for_target(session, *crate_type) {
if invalid_output_for_target(session, *crate_type)
|| !backend_crate_types.contains(crate_type)
{
// FIXME provide a better warning for the case where the codegen
// backend doesn't support it once cargo doesn't hard code this
// warning message.
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: *crate_type,
target_triple: &session.opts.target_triple,
Expand Down
2 changes: 0 additions & 2 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ pub(crate) enum ModuleSorting {

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum EmitType {
Unversioned,
Toolchain,
InvocationSpecific,
DepInfo(Option<OutFileName>),
Expand All @@ -322,7 +321,6 @@ impl FromStr for EmitType {

fn from_str(s: &str) -> Result<Self, Self::Err> {
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)),
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ fn opts() -> Vec<RustcOptGroup> {
"",
"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(
Expand Down
2 changes: 1 addition & 1 deletion tests/run-make/emit-shared-files/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
50 changes: 50 additions & 0 deletions tests/ui/traits/next-solver/opaques/stranded_opaque.rs
Original file line number Diff line number Diff line change
@@ -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<Output = impl Send> {
//~^ 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<Assoc = 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<impl Trait> {
//~^ 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<Output = impl Send>;
//~^ 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<Assoc = 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<impl Trait>;
//~^ ERROR unconstrained opaque type
//~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied

fn main() {}
Loading
Loading