Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use rustc_hir::attrs::WindowsSubsystemKind;
use rustc_hir::attrs::{CrateType, WindowsSubsystemKind};
use rustc_hir::lints::AttributeLintKind;
use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES;
use rustc_span::Symbol;
use rustc_span::edit_distance::find_best_match_for_name;

use super::prelude::*;

Expand Down Expand Up @@ -26,6 +30,56 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
}
}

pub(crate) struct CrateTypeParser;

impl<S: Stage> CombineAttributeParser<S> for CrateTypeParser {
const PATH: &[Symbol] = &[sym::crate_type];
type Item = CrateType;
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::CrateType(items);

const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);

const TEMPLATE: AttributeTemplate =
template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html");

fn extend(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let ArgParser::NameValue(n) = args else {
cx.expected_name_value(cx.attr_span, None);
return None;
};

let Some(crate_type) = n.value_as_str() else {
cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
return None;
};

let Ok(crate_type) = crate_type.try_into() else {
// We don't error on invalid `#![crate_type]` when not applied to a crate
if cx.shared.target == Target::Crate {
let candidate = find_best_match_for_name(
&CrateType::all_stable().iter().map(|(name, _)| *name).collect::<Vec<_>>(),
crate_type,
None,
);
cx.emit_lint(
UNKNOWN_CRATE_TYPES,
AttributeLintKind::CrateTypeUnknown {
span: n.value_span,
suggested: candidate,
},
n.value_span,
);
}
return None;
};

Some(crate_type)
}
}

pub(crate) struct RecursionLimitParser;

impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ use crate::attributes::codegen_attrs::{
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::crate_level::{
CrateNameParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoBuiltinsParser, NoCoreParser,
NoMainParser, NoStdParser, PanicRuntimeParser, PatternComplexityLimitParser,
ProfilerRuntimeParser, RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
WindowsSubsystemParser,
CrateNameParser, CrateTypeParser, MoveSizeLimitParser, NeedsPanicRuntimeParser,
NoBuiltinsParser, NoCoreParser, NoMainParser, NoStdParser, PanicRuntimeParser,
PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser,
RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser,
};
use crate::attributes::debugger::DebuggerViualizerParser;
use crate::attributes::deprecation::DeprecationParser;
Expand Down Expand Up @@ -193,6 +193,7 @@ attribute_parsers!(
// tidy-alphabetical-start
Combine<AllowConstFnUnstableParser>,
Combine<AllowInternalUnstableParser>,
Combine<CrateTypeParser>,
Combine<DebuggerViualizerParser>,
Combine<ForceTargetFeatureParser>,
Combine<LinkParser>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
CrateType::Executable
| CrateType::Dylib
| CrateType::Cdylib
| CrateType::Staticlib
| CrateType::StaticLib
| CrateType::Sdylib => {
// These are crate types for which we will embed pretty printers since they
// are treated as leaf crates.
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub fn link_binary(
)
.build(&out_filename);
}
CrateType::Staticlib => {
CrateType::StaticLib => {
link_staticlib(
sess,
archive_builder_builder,
Expand Down Expand Up @@ -474,7 +474,7 @@ fn link_staticlib(

let res = each_linked_rlib(
&codegen_results.crate_info,
Some(CrateType::Staticlib),
Some(CrateType::StaticLib),
&mut |cnum, path| {
let lto = are_upstream_rust_objects_already_included(sess)
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
Expand Down Expand Up @@ -532,7 +532,7 @@ fn link_staticlib(
let fmts = codegen_results
.crate_info
.dependency_formats
.get(&CrateType::Staticlib)
.get(&CrateType::StaticLib)
.expect("no dependency formats for staticlib");

let mut all_rust_dylibs = vec![];
Expand Down Expand Up @@ -1210,7 +1210,7 @@ fn add_sanitizer_libraries(
return;
}

if matches!(crate_type, CrateType::Rlib | CrateType::Staticlib) {
if matches!(crate_type, CrateType::Rlib | CrateType::StaticLib) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1857,7 +1857,7 @@ pub(crate) fn linked_symbols(
| CrateType::Cdylib
| CrateType::Dylib
| CrateType::Sdylib => (),
CrateType::Staticlib | CrateType::Rlib => {
CrateType::StaticLib | CrateType::Rlib => {
// These are not linked, so no need to generate symbols.o for them.
return Vec::new();
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool {
match crate_type {
CrateType::Executable
| CrateType::Dylib
| CrateType::Staticlib
| CrateType::StaticLib
| CrateType::Cdylib
| CrateType::ProcMacro
| CrateType::Sdylib => true,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {

fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
match crate_type {
CrateType::Executable | CrateType::Staticlib | CrateType::ProcMacro | CrateType::Cdylib => {
CrateType::Executable | CrateType::StaticLib | CrateType::ProcMacro | CrateType::Cdylib => {
SymbolExportLevel::C
}
CrateType::Rlib | CrateType::Dylib | CrateType::Sdylib => SymbolExportLevel::Rust,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ impl CrateInfo {
info.linked_symbols
.iter_mut()
.filter(|(crate_type, _)| {
!matches!(crate_type, CrateType::Rlib | CrateType::Staticlib)
!matches!(crate_type, CrateType::Rlib | CrateType::StaticLib)
})
.for_each(|(_, linked_symbols)| {
let mut symbols = missing_weak_lang_items
Expand Down Expand Up @@ -1041,7 +1041,7 @@ impl CrateInfo {
// this is a rare use case and we don't want to slow down the common case.
false
}
CrateType::Staticlib | CrateType::Rlib => {
CrateType::StaticLib | CrateType::Rlib => {
// We don't invoke the linker for these, so we don't need to collect the NatVis for
// them.
false
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub trait CodegenBackend {
CrateType::Executable,
CrateType::Dylib,
CrateType::Rlib,
CrateType::Staticlib,
CrateType::StaticLib,
CrateType::Cdylib,
CrateType::ProcMacro,
CrateType::Sdylib,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use rustc_feature::find_gated_cfg;
// `rust_index` isn't used in this crate's code, but it must be named in the
// `Cargo.toml` for the `rustc_randomized_layouts` feature.
use rustc_index as _;
use rustc_interface::passes::collect_crate_types;
use rustc_interface::util::{self, get_codegen_backend};
use rustc_interface::{Linker, create_and_enter_global_ctxt, interface, passes};
use rustc_lint::unerased_lint_store;
Expand All @@ -56,10 +57,10 @@ use rustc_session::config::{
};
use rustc_session::getopts::{self, Matches};
use rustc_session::lint::{Lint, LintId};
use rustc_session::output::{CRATE_TYPES, collect_crate_types, invalid_output_for_target};
use rustc_session::output::invalid_output_for_target;
use rustc_session::{EarlyDiagCtxt, Session, config};
use rustc_span::FileName;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::{DUMMY_SP, FileName};
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTuple};
use tracing::trace;
Expand Down Expand Up @@ -698,6 +699,7 @@ fn print_crate_info(
&codegen_backend.supported_crate_types(sess),
codegen_backend.name(),
attrs,
DUMMY_SP,
);
for &style in &crate_types {
let fname = rustc_session::output::filename_for_input(
Expand Down Expand Up @@ -849,7 +851,7 @@ fn print_crate_info(
}
}
SupportedCrateTypes => {
let supported_crate_types = CRATE_TYPES
let supported_crate_types = CrateType::all()
.iter()
.filter(|(_, crate_type)| !invalid_output_for_target(sess, *crate_type))
.filter(|(_, crate_type)| *crate_type != CrateType::Sdylib)
Expand Down
105 changes: 105 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,108 @@ pub enum CollapseMacroDebuginfo {
Yes = 3,
}

/// Crate type, as specified by `#![crate_type]`
#[derive(Copy, Clone, Debug, Hash, PartialEq, Default, PartialOrd, Eq, Ord)]
#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub enum CrateType {
/// `#![crate_type = "bin"]`
Executable,
/// `#![crate_type = "dylib"]`
Dylib,
/// `#![crate_type = "rlib"]` or `#![crate_type = "lib"]`
#[default]
Rlib,
/// `#![crate_type = "staticlib"]`
StaticLib,
/// `#![crate_type = "cdylib"]`
Cdylib,
/// `#![crate_type = "proc-macro"]`
ProcMacro,
/// `#![crate_type = "sdylib"]`
// Unstable; feature(export_stable)
Sdylib,
}

impl CrateType {
/// Pairs of each `#[crate_type] = "..."` value and the crate type it resolves to
pub fn all() -> &'static [(Symbol, Self)] {
debug_assert_eq!(CrateType::default(), CrateType::Rlib);
&[
(rustc_span::sym::lib, CrateType::Rlib),
(rustc_span::sym::rlib, CrateType::Rlib),
(rustc_span::sym::dylib, CrateType::Dylib),
(rustc_span::sym::cdylib, CrateType::Cdylib),
(rustc_span::sym::staticlib, CrateType::StaticLib),
(rustc_span::sym::proc_dash_macro, CrateType::ProcMacro),
(rustc_span::sym::bin, CrateType::Executable),
(rustc_span::sym::sdylib, CrateType::Sdylib),
]
}

/// Same as [`CrateType::all`], but does not include unstable options.
/// Used for diagnostics.
pub fn all_stable() -> &'static [(Symbol, Self)] {
debug_assert_eq!(CrateType::default(), CrateType::Rlib);
&[
(rustc_span::sym::lib, CrateType::Rlib),
(rustc_span::sym::rlib, CrateType::Rlib),
(rustc_span::sym::dylib, CrateType::Dylib),
(rustc_span::sym::cdylib, CrateType::Cdylib),
(rustc_span::sym::staticlib, CrateType::StaticLib),
(rustc_span::sym::proc_dash_macro, CrateType::ProcMacro),
(rustc_span::sym::bin, CrateType::Executable),
]
}

pub fn has_metadata(self) -> bool {
match self {
CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
CrateType::Executable
| CrateType::Cdylib
| CrateType::StaticLib
| CrateType::Sdylib => false,
}
}
}

impl TryFrom<Symbol> for CrateType {
type Error = ();

fn try_from(value: Symbol) -> Result<Self, Self::Error> {
Ok(match value {
rustc_span::sym::bin => CrateType::Executable,
rustc_span::sym::dylib => CrateType::Dylib,
rustc_span::sym::staticlib => CrateType::StaticLib,
rustc_span::sym::cdylib => CrateType::Cdylib,
rustc_span::sym::rlib => CrateType::Rlib,
rustc_span::sym::lib => CrateType::default(),
rustc_span::sym::proc_dash_macro => CrateType::ProcMacro,
rustc_span::sym::sdylib => CrateType::Sdylib,
_ => return Err(()),
})
}
}

impl std::fmt::Display for CrateType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
CrateType::Executable => "bin".fmt(f),
CrateType::Dylib => "dylib".fmt(f),
CrateType::Rlib => "rlib".fmt(f),
CrateType::StaticLib => "staticlib".fmt(f),
CrateType::Cdylib => "cdylib".fmt(f),
CrateType::ProcMacro => "proc-macro".fmt(f),
CrateType::Sdylib => "sdylib".fmt(f),
}
}
}

impl IntoDiagArg for CrateType {
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg(&mut None)
}
}

/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
Expand Down Expand Up @@ -719,6 +821,9 @@ pub enum AttributeKind {
/// Represents `#[crate_name = ...]`
CrateName { name: Symbol, name_span: Span, attr_span: Span },

/// Represents `#![crate_type = ...]`
CrateType(ThinVec<CrateType>),

/// Represents `#[custom_mir]`.
CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ impl AttributeKind {
Coroutine(..) => No,
Coverage(..) => No,
CrateName { .. } => No,
CrateType(_) => No,
CustomMir(_, _, _) => Yes,
DebuggerVisualizer(..) => No,
DenyExplicitImpl(..) => No,
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_interface/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
interface_input_file_would_be_overwritten =
the input file "{$path}" would be overwritten by the generated executable

interface_invalid_crate_type_value = invalid `crate_type` value
.suggestion = did you mean

interface_mixed_bin_crate =
cannot mix `bin` crate type with others

Expand All @@ -51,3 +48,9 @@ interface_proc_macro_crate_panic_abort =

interface_temps_dir_error =
failed to find or create the directory specified by `--temps-dir`

interface_unsupported_crate_type_for_codegen_backend =
dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}`

interface_unsupported_crate_type_for_target =
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
Loading
Loading