Rollup merge of #151442 - clubby789:crate-type-port, r=JonathanBrouwer

Port `#![crate_type]` to the attribute parser

Tracking issue: https://github.com/rust-lang/rust/issues/131229

~~Note that the actual parsing that is used in the compiler session is unchanged, as it must happen very early on; this just ports the validation logic.~~

Also added `// tidy-alphabetical-start` to `check_attr.rs` to make it a bit less conflict-prone
This commit is contained in:
Jacob Pratt 2026-01-22 00:37:43 -05:00 committed by GitHub
commit 512cc8d785
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 636 additions and 475 deletions

View file

@ -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::*;
@ -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 {

View file

@ -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;
@ -193,6 +193,7 @@ attribute_parsers!(
// tidy-alphabetical-start
Combine<AllowConstFnUnstableParser>,
Combine<AllowInternalUnstableParser>,
Combine<CrateTypeParser>,
Combine<DebuggerViualizerParser>,
Combine<ForceTargetFeatureParser>,
Combine<LinkParser>,

View file

@ -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.

View file

@ -136,7 +136,7 @@ pub fn link_binary(
)
.build(&out_filename);
}
CrateType::Staticlib => {
CrateType::StaticLib => {
link_staticlib(
sess,
archive_builder_builder,
@ -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);
@ -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![];
@ -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;
}

View file

@ -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();
}

View file

@ -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,

View file

@ -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,

View file

@ -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
@ -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

View file

@ -67,7 +67,7 @@ pub trait CodegenBackend {
CrateType::Executable,
CrateType::Dylib,
CrateType::Rlib,
CrateType::Staticlib,
CrateType::StaticLib,
CrateType::Cdylib,
CrateType::ProcMacro,
CrateType::Sdylib,

View file

@ -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;
@ -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;
@ -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(
@ -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)

View file

@ -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
@ -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),

View file

@ -40,6 +40,7 @@ impl AttributeKind {
Coroutine(..) => No,
Coverage(..) => No,
CrateName { .. } => No,
CrateType(_) => No,
CustomMir(_, _, _) => Yes,
DebuggerVisualizer(..) => No,
DenyExplicitImpl(..) => No,

View file

@ -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
@ -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}`

View file

@ -1,8 +1,10 @@
use std::io;
use std::path::Path;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_hir::attrs::CrateType;
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::TargetTuple;
#[derive(Diagnostic)]
#[diag(interface_crate_name_does_not_match)]
@ -109,17 +111,16 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
pub enabled: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(interface_invalid_crate_type_value)]
pub(crate) struct UnknownCrateTypes {
#[subdiagnostic]
pub sugg: Option<UnknownCrateTypesSub>,
#[derive(Diagnostic)]
#[diag(interface_unsupported_crate_type_for_codegen_backend)]
pub(crate) struct UnsupportedCrateTypeForCodegenBackend {
pub(crate) crate_type: CrateType,
pub(crate) codegen_backend: &'static str,
}
#[derive(Subdiagnostic)]
#[suggestion(interface_suggestion, code = r#""{snippet}""#, applicability = "maybe-incorrect")]
pub(crate) struct UnknownCrateTypesSub {
#[primary_span]
pub span: Span,
pub snippet: Symbol,
#[derive(Diagnostic)]
#[diag(interface_unsupported_crate_type_for_target)]
pub(crate) struct UnsupportedCrateTypeForTarget<'a> {
pub(crate) crate_type: CrateType,
pub(crate) target_triple: &'a TargetTuple,
}

View file

@ -5,8 +5,8 @@ use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, OnceLock};
use std::{env, fs, iter};
use rustc_ast as ast;
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
use rustc_ast::{self as ast, CRATE_NODE_ID};
use rustc_attr_parsing::{AttributeParser, Early, ShouldEmit};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenResults, CrateInfo};
use rustc_data_structures::jobserver::Proxy;
@ -17,6 +17,7 @@ use rustc_errors::timings::TimingSection;
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_feature::Features;
use rustc_fs_util::try_canonicalize;
use rustc_hir::Attribute;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
use rustc_hir::definitions::Definitions;
@ -35,7 +36,7 @@ use rustc_resolve::{Resolver, ResolverOutputs};
use rustc_session::Session;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::{collect_crate_types, filename_for_input};
use rustc_session::output::{filename_for_input, invalid_output_for_target};
use rustc_session::parse::feature_err;
use rustc_session::search_paths::PathKind;
use rustc_span::{
@ -159,8 +160,6 @@ fn configure_and_expand(
)
});
util::check_attr_crate_type(sess, pre_configured_attrs, resolver.lint_buffer());
// Expand all macros
krate = sess.time("macro_expand_crate", || {
// Windows dlls do not have rpaths, so they don't know how to find their
@ -929,6 +928,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
&compiler.codegen_backend.supported_crate_types(sess),
compiler.codegen_backend.name(),
&pre_configured_attrs,
krate.spans.inner_span,
);
let stable_crate_id = StableCrateId::new(
crate_name,
@ -1347,6 +1347,94 @@ pub(crate) fn parse_crate_name(
Some((name, name_span))
}
pub fn collect_crate_types(
session: &Session,
backend_crate_types: &[CrateType],
codegen_backend_name: &'static str,
attrs: &[ast::Attribute],
crate_span: Span,
) -> Vec<CrateType> {
// If we're generating a test executable, then ignore all other output
// styles at all other locations
if session.opts.test {
if !session.target.executables {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: CrateType::Executable,
target_triple: &session.opts.target_triple,
});
return Vec::new();
}
return vec![CrateType::Executable];
}
// Shadow `sdylib` crate type in interface build.
if session.opts.unstable_opts.build_sdylib_interface {
return vec![CrateType::Rlib];
}
// Only check command line flags if present. If no types are specified by
// command line, then reuse the empty `base` Vec to hold the types that
// will be found in crate attributes.
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
let mut base = session.opts.crate_types.clone();
if base.is_empty() {
if let Some(Attribute::Parsed(AttributeKind::CrateType(crate_type))) =
AttributeParser::<Early>::parse_limited_should_emit(
session,
attrs,
sym::crate_type,
crate_span,
CRATE_NODE_ID,
None,
ShouldEmit::EarlyFatal { also_emit_lints: false },
)
{
base.extend(crate_type);
}
if base.is_empty() {
base.push(default_output_for_target(session));
} else {
base.sort();
base.dedup();
}
}
base.retain(|crate_type| {
if invalid_output_for_target(session, *crate_type) {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: *crate_type,
target_triple: &session.opts.target_triple,
});
false
} else if !backend_crate_types.contains(crate_type) {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForCodegenBackend {
crate_type: *crate_type,
codegen_backend: codegen_backend_name,
});
false
} else {
true
}
});
base
}
/// Returns default crate type for target
///
/// Default crate type is used when crate type isn't provided neither
/// through cmd line arguments nor through crate attributes
///
/// It is CrateType::Executable for all platforms but iOS as there is no
/// way to run iOS binaries anyway without jailbreaking and
/// interaction with Rust code through static library is the only
/// option for now
fn default_output_for_target(sess: &Session) -> CrateType {
if !sess.target.executables { CrateType::StaticLib } else { CrateType::Executable }
}
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
let attr = AttributeParser::parse_limited_should_emit(
sess,

View file

@ -6,7 +6,7 @@ use std::sync::{Arc, OnceLock};
use std::{env, thread};
use rustc_ast as ast;
use rustc_attr_parsing::{ShouldEmit, validate_attr};
use rustc_attr_parsing::ShouldEmit;
use rustc_codegen_ssa::back::archive::{ArArchiveBuilderBuilder, ArchiveBuilderBuilder};
use rustc_codegen_ssa::back::link::link_binary;
use rustc_codegen_ssa::target_features::cfg_target_feature;
@ -15,16 +15,13 @@ use rustc_codegen_ssa::{CodegenResults, CrateInfo, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::jobserver::Proxy;
use rustc_data_structures::sync;
use rustc_errors::LintBuffer;
use rustc_metadata::{DylibError, EncodedMetadata, load_symbol_from_dylib};
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::{CurrentGcx, TyCtxt};
use rustc_session::config::{
Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple,
};
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
use rustc_session::{EarlyDiagCtxt, Session, filesearch, lint};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_session::{EarlyDiagCtxt, Session, filesearch};
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMapInputs;
use rustc_span::{SessionGlobals, Symbol, sym};
@ -575,54 +572,6 @@ fn get_codegen_sysroot(
}
}
pub(crate) fn check_attr_crate_type(
sess: &Session,
attrs: &[ast::Attribute],
lint_buffer: &mut LintBuffer,
) {
// Unconditionally collect crate types from attributes to make them used
for a in attrs.iter() {
if a.has_name(sym::crate_type) {
if let Some(n) = a.value_str() {
if categorize_crate_type(n).is_some() {
return;
}
if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() {
let span = spanned.span;
let candidate = find_best_match_for_name(
&CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(),
n,
None,
);
lint_buffer.buffer_lint(
lint::builtin::UNKNOWN_CRATE_TYPES,
ast::CRATE_NODE_ID,
span,
errors::UnknownCrateTypes {
sugg: candidate
.map(|cand| errors::UnknownCrateTypesSub { span, snippet: cand }),
},
);
}
} else {
// This is here mainly to check for using a macro, such as
// `#![crate_type = foo!()]`. That is not supported since the
// crate type needs to be known very early in compilation long
// before expansion. Otherwise, validation would normally be
// caught during semantic analysis via `TyCtxt::check_mod_attrs`,
// but by the time that runs the macro is expanded, and it doesn't
// give an error.
validate_attr::emit_fatal_malformed_builtin_attribute(
&sess.psess,
a,
sym::crate_type,
);
}
}
}
}
fn multiple_output_types_to_stdout(
output_types: &OutputTypes,
single_output_file_is_stdout: bool,

View file

@ -503,6 +503,9 @@ lint_invalid_asm_label_named = avoid using named labels in inline assembly
.note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro
lint_invalid_crate_type_value = invalid `crate_type` value
.suggestion = did you mean
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes

View file

@ -423,5 +423,10 @@ pub fn decorate_attribute_lint(
&AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
lints::DoNotRecommendDoesNotExpectArgs.decorate_lint(diag)
}
&AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes {
sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
}
.decorate_lint(diag),
}
}

View file

@ -3310,3 +3310,18 @@ pub(crate) struct AttrCrateLevelOnly;
#[derive(LintDiagnostic)]
#[diag(lint_incorrect_do_not_recommend_args)]
pub(crate) struct DoNotRecommendDoesNotExpectArgs;
#[derive(LintDiagnostic)]
#[diag(lint_invalid_crate_type_value)]
pub(crate) struct UnknownCrateTypes {
#[subdiagnostic]
pub sugg: Option<UnknownCrateTypesSuggestion>,
}
#[derive(Subdiagnostic)]
#[suggestion(lint_suggestion, code = r#""{snippet}""#, applicability = "maybe-incorrect")]
pub(crate) struct UnknownCrateTypesSuggestion {
#[primary_span]
pub span: Span,
pub snippet: Symbol,
}

View file

@ -822,6 +822,10 @@ pub enum AttributeLintKind {
DocTestLiteral,
AttrCrateLevelOnly,
DoNotRecommendDoesNotExpectArgs,
CrateTypeUnknown {
span: Span,
suggested: Option<Symbol>,
},
}
pub type RegisteredTools = FxIndexSet<Ident>;

View file

@ -104,7 +104,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
CrateType::Dylib | CrateType::Cdylib | CrateType::Sdylib => {
if sess.opts.cg.prefer_dynamic { Linkage::Dynamic } else { Linkage::Static }
}
CrateType::Staticlib => {
CrateType::StaticLib => {
if sess.opts.unstable_opts.staticlib_prefer_dynamic {
Linkage::Dynamic
} else {
@ -141,7 +141,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
// Static executables must have all static dependencies.
// If any are not found, generate some nice pretty errors.
if (ty == CrateType::Staticlib && !sess.opts.unstable_opts.staticlib_allow_rdylib_deps)
if (ty == CrateType::StaticLib && !sess.opts.unstable_opts.staticlib_allow_rdylib_deps)
|| (ty == CrateType::Executable
&& sess.crt_static(Some(ty))
&& !sess.target.crt_static_allows_dylibs)

View file

@ -162,7 +162,7 @@ fn find_bundled_library(
) -> Option<Symbol> {
let sess = tcx.sess;
if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind
&& tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
&& tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib))
&& (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
{
let verbatim = verbatim.unwrap_or(false);

View file

@ -1980,7 +1980,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn needs_metadata(self) -> bool {
self.crate_types().iter().any(|ty| match *ty {
CrateType::Executable
| CrateType::Staticlib
| CrateType::StaticLib
| CrateType::Cdylib
| CrateType::Sdylib => false,
CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
@ -2279,7 +2279,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.crate_types().iter().any(|crate_type| {
match crate_type {
CrateType::Executable
| CrateType::Staticlib
| CrateType::StaticLib
| CrateType::ProcMacro
| CrateType::Cdylib
| CrateType::Sdylib => false,

View file

@ -225,112 +225,116 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
},
Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)},
Attribute::Parsed(
AttributeKind::EiiDeclaration { .. }
| AttributeKind::EiiForeignItem
| AttributeKind::BodyStability { .. }
| AttributeKind::ConstStabilityIndirect
| AttributeKind::MacroTransparency(_)
| AttributeKind::CollapseDebugInfo(..)
| AttributeKind::CfgTrace(..)
| AttributeKind::Pointee(..)
| AttributeKind::Dummy
| AttributeKind::RustcBuiltinMacro { .. }
| AttributeKind::Ignore { .. }
| AttributeKind::InstructionSet(..)
| AttributeKind::Path(..)
| AttributeKind::NoImplicitPrelude(..)
// tidy-alphabetical-start
AttributeKind::AllowIncoherentImpl(..)
| AttributeKind::AsPtr(..)
| AttributeKind::AutomaticallyDerived(..)
| AttributeKind::Marker(..)
| AttributeKind::SkipDuringMethodDispatch { .. }
| AttributeKind::BodyStability { .. }
| AttributeKind::CfgAttrTrace
| AttributeKind::CfgTrace(..)
| AttributeKind::CfiEncoding { .. }
| AttributeKind::Coinductive(..)
| AttributeKind::DenyExplicitImpl(..)
| AttributeKind::DynIncompatibleTrait(..)
| AttributeKind::SpecializationTrait(..)
| AttributeKind::UnsafeSpecializationMarker(..)
| AttributeKind::ParenSugar(..)
| AttributeKind::AllowIncoherentImpl(..)
| AttributeKind::Cold(..)
| AttributeKind::CollapseDebugInfo(..)
| AttributeKind::CompilerBuiltins
| AttributeKind::Confusables { .. }
| AttributeKind::TypeConst{..}
| AttributeKind::ConstStabilityIndirect
| AttributeKind::Coroutine(..)
| AttributeKind::Coverage (..)
| AttributeKind::CrateName { .. }
| AttributeKind::CrateType(..)
| AttributeKind::DebuggerVisualizer(..)
| AttributeKind::DenyExplicitImpl(..)
// `#[doc]` is actually a lot more than just doc comments, so is checked below
| AttributeKind::DocComment {..}
| AttributeKind::Dummy
| AttributeKind::DynIncompatibleTrait(..)
| AttributeKind::EiiDeclaration { .. }
| AttributeKind::EiiForeignItem
| AttributeKind::ExportName { .. }
| AttributeKind::ExportStable
| AttributeKind::FfiConst(..)
| AttributeKind::Fundamental
| AttributeKind::Ignore { .. }
| AttributeKind::InstructionSet(..)
| AttributeKind::LinkName { .. }
| AttributeKind::LinkOrdinal { .. }
| AttributeKind::LinkSection { .. }
| AttributeKind::Linkage(..)
| AttributeKind::MacroEscape( .. )
| AttributeKind::MacroTransparency(_)
| AttributeKind::MacroUse { .. }
| AttributeKind::Marker(..)
| AttributeKind::MoveSizeLimit { .. }
| AttributeKind::MustNotSupend { .. }
| AttributeKind::MustUse { .. }
| AttributeKind::NeedsAllocator
| AttributeKind::NeedsPanicRuntime
| AttributeKind::NoBuiltins
| AttributeKind::NoCore { .. }
| AttributeKind::NoImplicitPrelude(..)
| AttributeKind::NoLink
| AttributeKind::NoMain
| AttributeKind::NoMangle(..)
| AttributeKind::NoStd { .. }
| AttributeKind::ObjcClass { .. }
| AttributeKind::ObjcSelector { .. }
| AttributeKind::Optimize(..)
| AttributeKind::PanicRuntime
| AttributeKind::ParenSugar(..)
| AttributeKind::PassByValue (..)
| AttributeKind::PatchableFunctionEntry { .. }
| AttributeKind::Path(..)
| AttributeKind::PatternComplexityLimit { .. }
| AttributeKind::PinV2(..)
| AttributeKind::Pointee(..)
| AttributeKind::ProfilerRuntime
| AttributeKind::RecursionLimit { .. }
// handled below this loop and elsewhere
| AttributeKind::Repr { .. }
| AttributeKind::Cold(..)
| AttributeKind::ExportName { .. }
| AttributeKind::Fundamental
| AttributeKind::Optimize(..)
| AttributeKind::LinkSection { .. }
| AttributeKind::MacroUse { .. }
| AttributeKind::MacroEscape( .. )
| AttributeKind::NoLink
| AttributeKind::RustcNoImplicitAutorefs
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
| AttributeKind::RustcAllocator
| AttributeKind::RustcAllocatorZeroed
| AttributeKind::RustcAllocatorZeroedVariant { .. }
| AttributeKind::RustcBuiltinMacro { .. }
| AttributeKind::RustcCoherenceIsCore(..)
| AttributeKind::RustcDeallocator
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpItemBounds
| AttributeKind::RustcDumpPredicates
| AttributeKind::RustcDumpUserArgs
| AttributeKind::RustcDumpVtable(..)
| AttributeKind::RustcHasIncoherentInherentImpls
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
| AttributeKind::RustcLintOptDenyFieldAccess { .. }
| AttributeKind::RustcLintOptTy
| AttributeKind::RustcLintQueryInstability
| AttributeKind::RustcLintUntrackedQueryInformation
| AttributeKind::RustcNeverReturnsNullPointer
| AttributeKind::RustcScalableVector { .. }
| AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
| AttributeKind::RustcShouldNotBeCalledOnConstItems(..)
| AttributeKind::RustcVariance
| AttributeKind::RustcVarianceOfOpaques
| AttributeKind::ExportStable
| AttributeKind::FfiConst(..)
| AttributeKind::UnstableFeatureBound(..)
| AttributeKind::AsPtr(..)
| AttributeKind::LinkName { .. }
| AttributeKind::LinkOrdinal { .. }
| AttributeKind::NoMangle(..)
| AttributeKind::Used { .. }
| AttributeKind::PassByValue (..)
| AttributeKind::StdInternalSymbol (..)
| AttributeKind::Coverage (..)
| AttributeKind::ShouldPanic { .. }
| AttributeKind::Coroutine(..)
| AttributeKind::Linkage(..)
| AttributeKind::MustUse { .. }
| AttributeKind::CrateName { .. }
| AttributeKind::RecursionLimit { .. }
| AttributeKind::MoveSizeLimit { .. }
| AttributeKind::TypeLengthLimit { .. }
| AttributeKind::PatternComplexityLimit { .. }
| AttributeKind::NoCore { .. }
| AttributeKind::NoStd { .. }
| AttributeKind::NoMain
| AttributeKind::CompilerBuiltins
| AttributeKind::PanicRuntime
| AttributeKind::NeedsPanicRuntime
| AttributeKind::ProfilerRuntime
| AttributeKind::NoBuiltins
| AttributeKind::ObjcClass { .. }
| AttributeKind::ObjcSelector { .. }
| AttributeKind::RustcCoherenceIsCore(..)
| AttributeKind::DebuggerVisualizer(..)
| AttributeKind::RustcMain
| AttributeKind::RustcPassIndirectlyInNonRusticAbis(..)
| AttributeKind::PinV2(..)
| AttributeKind::WindowsSubsystem(..)
| AttributeKind::CfgAttrTrace
| AttributeKind::ThreadLocal
| AttributeKind::CfiEncoding { .. }
| AttributeKind::RustcHasIncoherentInherentImpls
| AttributeKind::MustNotSupend { .. }
| AttributeKind::RustcDumpUserArgs
| AttributeKind::RustcDumpItemBounds
| AttributeKind::RustcDumpPredicates
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpVtable(..)
| AttributeKind::NeedsAllocator
| AttributeKind::RustcAllocator
| AttributeKind::RustcAllocatorZeroed
| AttributeKind::RustcAllocatorZeroedVariant { .. }
| AttributeKind::RustcDeallocator
| AttributeKind::RustcReallocator
| AttributeKind::RustcNeverReturnsNullPointer
| AttributeKind::RustcNoImplicitAutorefs
| AttributeKind::RustcNounwind
| AttributeKind::RustcOffloadKernel
| AttributeKind::PatchableFunctionEntry { .. }
| AttributeKind::RustcPassIndirectlyInNonRusticAbis(..)
| AttributeKind::RustcReallocator
| AttributeKind::RustcScalableVector { .. }
| AttributeKind::RustcShouldNotBeCalledOnConstItems(..)
| AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
| AttributeKind::RustcVariance
| AttributeKind::RustcVarianceOfOpaques
| AttributeKind::ShouldPanic { .. }
| AttributeKind::SkipDuringMethodDispatch { .. }
| AttributeKind::SpecializationTrait(..)
| AttributeKind::StdInternalSymbol (..)
| AttributeKind::ThreadLocal
| AttributeKind::TypeConst{..}
| AttributeKind::TypeLengthLimit { .. }
| AttributeKind::UnsafeSpecializationMarker(..)
| AttributeKind::UnstableFeatureBound(..)
| AttributeKind::Used { .. }
| AttributeKind::WindowsSubsystem(..)
// tidy-alphabetical-end
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@ -402,7 +406,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::rustc_no_implicit_bounds
| sym::test_runner
| sym::reexport_test_harness_main
| sym::crate_type
| sym::rustc_preserve_ub_checks,
..
] => {}
@ -1612,7 +1615,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
.tcx
.crate_types()
.iter()
.all(|kind| matches!(kind, CrateType::Rlib | CrateType::Staticlib));
.all(|kind| matches!(kind, CrateType::Rlib | CrateType::StaticLib));
if never_needs_link {
errors::UnusedNote::LinkerMessagesBinaryCrateOnly
} else {

View file

@ -68,7 +68,7 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
| CrateType::ProcMacro
| CrateType::Cdylib
| CrateType::Executable
| CrateType::Staticlib
| CrateType::StaticLib
| CrateType::Sdylib => true,
CrateType::Rlib => false,
});

View file

@ -141,12 +141,6 @@ session_unleashed_feature_help_unnamed = skipping check that does not even have
session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
session_unsupported_crate_type_for_codegen_backend =
dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}`
session_unsupported_crate_type_for_target =
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is not supported
session_unsupported_dwarf_version_help = supported DWARF versions are 2, 3, 4 and 5

View file

@ -10,13 +10,13 @@ use std::hash::Hash;
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
use std::sync::LazyLock;
use std::{cmp, fmt, fs, iter};
use std::{cmp, fs, iter};
use externs::{ExternOpt, split_extern_opt};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg};
use rustc_errors::{ColorConfig, DiagCtxtFlags};
use rustc_feature::UnstableFeatures;
use rustc_hashes::Hash64;
use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
@ -1529,29 +1529,7 @@ pub enum EntryFnType {
},
}
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, BlobDecodable)]
#[derive(HashStable_Generic)]
pub enum CrateType {
Executable,
Dylib,
Rlib,
Staticlib,
Cdylib,
ProcMacro,
Sdylib,
}
impl CrateType {
pub fn has_metadata(self) -> bool {
match self {
CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
CrateType::Executable
| CrateType::Cdylib
| CrateType::Staticlib
| CrateType::Sdylib => false,
}
}
}
pub use rustc_hir::attrs::CrateType;
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
pub enum Passes {
@ -1595,10 +1573,6 @@ pub struct BranchProtection {
pub gcs: bool,
}
pub(crate) const fn default_lib_output() -> CrateType {
CrateType::Rlib
}
pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
// First disallow some configuration given on the command line
cfg::disallow_cfgs(sess, &user_cfg);
@ -2873,9 +2847,9 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
for unparsed_crate_type in &list_list {
for part in unparsed_crate_type.split(',') {
let new_part = match part {
"lib" => default_lib_output(),
"lib" => CrateType::default(),
"rlib" => CrateType::Rlib,
"staticlib" => CrateType::Staticlib,
"staticlib" => CrateType::StaticLib,
"dylib" => CrateType::Dylib,
"cdylib" => CrateType::Cdylib,
"bin" => CrateType::Executable,
@ -2969,26 +2943,6 @@ pub mod nightly_options {
}
}
impl fmt::Display for CrateType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> 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)
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
/// `-Zunpretty=normal`

View file

@ -11,7 +11,6 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple};
use crate::config::CrateType;
use crate::parse::ParseSess;
#[derive(Diagnostic)]
@ -376,20 +375,6 @@ struct BinaryFloatLiteralNotSupported {
span: Span,
}
#[derive(Diagnostic)]
#[diag(session_unsupported_crate_type_for_codegen_backend)]
pub(crate) struct UnsupportedCrateTypeForCodegenBackend {
pub(crate) crate_type: CrateType,
pub(crate) codegen_backend: &'static str,
}
#[derive(Diagnostic)]
#[diag(session_unsupported_crate_type_for_target)]
pub(crate) struct UnsupportedCrateTypeForTarget<'a> {
pub(crate) crate_type: CrateType,
pub(crate) target_triple: &'a TargetTuple,
}
pub fn report_lit_error(
psess: &ParseSess,
err: LitError,

View file

@ -2,12 +2,11 @@
use std::path::Path;
use rustc_ast as ast;
use rustc_span::{Span, Symbol, sym};
use rustc_span::{Span, Symbol};
use crate::Session;
use crate::config::{self, CrateType, OutFileName, OutputFilenames, OutputType};
use crate::errors::{self, CrateNameEmpty, FileIsNotWriteable, InvalidCharacterInCrateName};
use crate::config::{CrateType, OutFileName, OutputFilenames, OutputType};
use crate::errors::{CrateNameEmpty, FileIsNotWriteable, InvalidCharacterInCrateName};
pub fn out_filename(
sess: &Session,
@ -101,7 +100,7 @@ pub fn filename_for_input(
let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix);
OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")))
}
CrateType::Staticlib => {
CrateType::StaticLib => {
let (prefix, suffix) = sess.staticlib_components(false);
OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")))
}
@ -121,19 +120,6 @@ pub fn filename_for_input(
}
}
/// Returns default crate type for target
///
/// Default crate type is used when crate type isn't provided neither
/// through cmd line arguments nor through crate attributes
///
/// It is CrateType::Executable for all platforms but iOS as there is no
/// way to run iOS binaries anyway without jailbreaking and
/// interaction with Rust code through static library is the only
/// option for now
pub fn default_output_for_target(sess: &Session) -> CrateType {
if !sess.target.executables { CrateType::Staticlib } else { CrateType::Executable }
}
/// Checks if target supports crate_type as output
pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool {
if let CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro = crate_type {
@ -157,88 +143,3 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool
false
}
pub const CRATE_TYPES: &[(Symbol, CrateType)] = &[
(sym::rlib, CrateType::Rlib),
(sym::dylib, CrateType::Dylib),
(sym::cdylib, CrateType::Cdylib),
(sym::lib, config::default_lib_output()),
(sym::staticlib, CrateType::Staticlib),
(sym::proc_dash_macro, CrateType::ProcMacro),
(sym::bin, CrateType::Executable),
(sym::sdylib, CrateType::Sdylib),
];
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,
backend_crate_types: &[CrateType],
codegen_backend_name: &'static str,
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 {
if !session.target.executables {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: CrateType::Executable,
target_triple: &session.opts.target_triple,
});
return Vec::new();
}
return vec![CrateType::Executable];
}
// Shadow `sdylib` crate type in interface build.
if session.opts.unstable_opts.build_sdylib_interface {
return vec![CrateType::Rlib];
}
// Only check command line flags if present. If no types are specified by
// command line, then reuse the empty `base` Vec to hold the types that
// will be found in crate attributes.
// JUSTIFICATION: before wrapper fn is available
#[allow(rustc::bad_opt_access)]
let mut base = session.opts.crate_types.clone();
if base.is_empty() {
let attr_types = attrs.iter().filter_map(|a| {
if a.has_name(sym::crate_type)
&& let Some(s) = a.value_str()
{
categorize_crate_type(s)
} else {
None
}
});
base.extend(attr_types);
if base.is_empty() {
base.push(default_output_for_target(session));
} else {
base.sort();
base.dedup();
}
}
base.retain(|crate_type| {
if invalid_output_for_target(session, *crate_type) {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
crate_type: *crate_type,
target_triple: &session.opts.target_triple,
});
false
} else if !backend_crate_types.contains(crate_type) {
session.dcx().emit_warn(errors::UnsupportedCrateTypeForCodegenBackend {
crate_type: *crate_type,
codegen_backend: codegen_backend_name,
});
false
} else {
true
}
});
base
}

View file

@ -1,10 +1,11 @@
error: malformed `crate_type` attribute input
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-delimited.rs:2:1
|
LL | #![crate_type(lib)]
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0539`.

View file

@ -1,10 +1,11 @@
error: malformed `crate_type` attribute input
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-empty.rs:2:1
|
LL | #![crate_type]
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0539`.

View file

@ -1,4 +1,5 @@
#![crate_type = foo!()] //~ ERROR malformed `crate_type` attribute
#![crate_type = foo!()]
//~^ ERROR attribute value must be a literal
macro_rules! foo {
() => {"rlib"};

View file

@ -1,10 +1,8 @@
error: malformed `crate_type` attribute input
--> $DIR/crate-type-macro-call.rs:1:1
error: attribute value must be a literal
--> $DIR/crate-type-macro-call.rs:1:17
|
LL | #![crate_type = foo!()]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
| ^^^^^^
error: aborting due to 1 previous error

View file

@ -1,7 +1,7 @@
// Tests for the issue in #137589
#[crate_type = foo!()]
//~^ ERROR cannot find macro `foo` in this scope
//~| WARN crate-level attribute should be an inner attribute
//~| ERROR attribute value must be a literal
macro_rules! foo {} //~ ERROR macros must contain at least one rule

View file

@ -16,17 +16,11 @@ note: a macro with the same name exists, but it appears later
LL | macro_rules! foo {}
| ^^^
warning: crate-level attribute should be an inner attribute
--> $DIR/crate-type-macro-empty.rs:2:1
error: attribute value must be a literal
--> $DIR/crate-type-macro-empty.rs:2:16
|
LL | #[crate_type = foo!()]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: requested on the command line with `-W unused-attributes`
help: add a `!`
|
LL | #![crate_type = foo!()]
| +
| ^^^^^^
error: aborting due to 2 previous errors; 1 warning emitted
error: aborting due to 3 previous errors

View file

@ -1,6 +1,7 @@
// Tests for the issue in #137589
#[crate_type = foo!()] //~ ERROR cannot find macro `foo` in this scope
//~| WARN crate-level attribute should be an inner attribute
#[crate_type = foo!()]
//~^ ERROR cannot find macro `foo` in this scope
//~| ERROR attribute value must be a literal
macro_rules! foo {
($x:expr) => {"rlib"}

View file

@ -5,22 +5,16 @@ LL | #[crate_type = foo!()]
| ^^^ consider moving the definition of `foo` before this call
|
note: a macro with the same name exists, but it appears later
--> $DIR/crate-type-macro-not-found.rs:5:14
--> $DIR/crate-type-macro-not-found.rs:6:14
|
LL | macro_rules! foo {
| ^^^
warning: crate-level attribute should be an inner attribute
--> $DIR/crate-type-macro-not-found.rs:2:1
error: attribute value must be a literal
--> $DIR/crate-type-macro-not-found.rs:2:16
|
LL | #[crate_type = foo!()]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: requested on the command line with `-W unused-attributes`
help: add a `!`
|
LL | #![crate_type = foo!()]
| +
| ^^^^^^
error: aborting due to 1 previous error; 1 warning emitted
error: aborting due to 2 previous errors

View file

@ -0,0 +1,19 @@
//! Test the behavior of various malformed `crate_type` attributes applied to a non-crate target.
#![allow(unused_attributes)]
// No arguments
#[crate_type] //~ ERROR malformed `crate_type` attribute input
// List/NameValue with/without strings
#[crate_type(lib)] //~ ERROR malformed `crate_type` attribute input
#[crate_type("lib")] //~ ERROR malformed `crate_type` attribute input
#[crate_type = lib] //~ ERROR attribute value must be a literal
#[crate_type = "lib"] // OK
// Same as above but with invalid names
#[crate_type(foo)] //~ ERROR malformed `crate_type` attribute input
#[crate_type("foo")] //~ ERROR malformed `crate_type` attribute input
#[crate_type = foo] //~ ERROR attribute value must be a literal
#[crate_type = "foo"] // OK - we don't report errors on invalid crate types here
// Non-string literals
#[crate_type(1)] //~ ERROR malformed `crate_type` attribute input
#[crate_type = 1] //~ ERROR malformed `crate_type` attribute input
fn main() {}

View file

@ -0,0 +1,74 @@
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:5:1
|
LL | #[crate_type]
| ^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:7:1
|
LL | #[crate_type(lib)]
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:8:1
|
LL | #[crate_type("lib")]
| ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error: attribute value must be a literal
--> $DIR/crate-type-non-crate.rs:9:16
|
LL | #[crate_type = lib]
| ^^^
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:12:1
|
LL | #[crate_type(foo)]
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:13:1
|
LL | #[crate_type("foo")]
| ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error: attribute value must be a literal
--> $DIR/crate-type-non-crate.rs:14:16
|
LL | #[crate_type = foo]
| ^^^
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:17:1
|
LL | #[crate_type(1)]
| ^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error[E0539]: malformed `crate_type` attribute input
--> $DIR/crate-type-non-crate.rs:18:1
|
LL | #[crate_type = 1]
| ^^^^^^^^^^^^^^^-^
| | |
| | expected a string literal here
| help: must be of the form: `#[crate_type = "crate type"]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0539`.

View file

@ -835,26 +835,26 @@ mod crate_name {
#[crate_type = "0800"]
//~^ WARN crate-level attribute should be an inner attribute
//~| HELP add a `!`
mod crate_type {
//~^ NOTE this attribute does not have an `!`, which means it is applied to this module
mod inner { #![crate_type="0800"] }
//~^ WARN crate-level attribute should be in the root module
//~^ WARN the `#![crate_type]` attribute can only be used at the crate root
#[crate_type = "0800"] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
//~| HELP add a `!`
//~| NOTE this attribute does not have an `!`, which means it is applied to this function
#[crate_type = "0800"] struct S;
//~^ WARN crate-level attribute should be an inner attribute
//~| HELP add a `!`
//~| NOTE this attribute does not have an `!`, which means it is applied to this struct
#[crate_type = "0800"] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
//~| HELP add a `!`
//~| NOTE this attribute does not have an `!`, which means it is applied to this type alias
#[crate_type = "0800"] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
//~| HELP add a `!`
//~| NOTE this attribute does not have an `!`, which means it is applied to this implementation block
}
#[feature(x0600)]

View file

@ -218,17 +218,6 @@ LL | | }
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:1
|
LL | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: add a `!`
|
LL | #![crate_type = "0800"]
| +
warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:1
|
@ -354,56 +343,6 @@ LL | #[link(name = "x")] extern "Rust" {}
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: crate-level attribute should be in the root module
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:17
|
LL | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
|
LL | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: add a `!`
|
LL | #![crate_type = "0800"] fn f() { }
| +
warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
|
LL | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: add a `!`
|
LL | #![crate_type = "0800"] struct S;
| +
warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:851:5
|
LL | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: add a `!`
|
LL | #![crate_type = "0800"] type T = S;
| +
warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:5
|
LL | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: add a `!`
|
LL | #![crate_type = "0800"] impl S { }
| +
warning: crate-level attribute should be in the root module
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:864:17
|
@ -1285,6 +1224,76 @@ note: this attribute does not have an `!`, which means it is applied to this imp
LL | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:1
|
LL | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: this attribute does not have an `!`, which means it is applied to this module
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:1
|
LL | / mod crate_type {
LL | |
LL | | mod inner { #![crate_type="0800"] }
... |
LL | | }
| |_^
warning: the `#![crate_type]` attribute can only be used at the crate root
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:17
|
LL | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
|
LL | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: this attribute does not have an `!`, which means it is applied to this function
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:28
|
LL | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
|
LL | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: this attribute does not have an `!`, which means it is applied to this struct
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:28
|
LL | #[crate_type = "0800"] struct S;
| ^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:851:5
|
LL | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: this attribute does not have an `!`, which means it is applied to this type alias
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:851:28
|
LL | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:5
|
LL | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
|
note: this attribute does not have an `!`, which means it is applied to this implementation block
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:28
|
LL | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_main]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:885:1
|

View file

@ -26,7 +26,7 @@
#![crate_type="dlib"]
//~^ ERROR invalid `crate_type` value
//~| HELP did you mean
//~| SUGGESTION rlib
//~| SUGGESTION lib
#![crate_type="lob"]
//~^ ERROR invalid `crate_type` value

View file

@ -34,7 +34,7 @@ error: invalid `crate_type` value
--> $DIR/invalid-crate-type.rs:26:15
|
LL | #![crate_type="dlib"]
| ^^^^^^ help: did you mean: `"rlib"`
| ^^^^^^ help: did you mean: `"lib"`
error: invalid `crate_type` value
--> $DIR/invalid-crate-type.rs:31:15

View file

@ -4,7 +4,7 @@
#![deny(unused_attributes)]
mod a {
#![crate_type = "bin"] //~ ERROR should be in the root module
#![crate_type = "bin"] //~ ERROR the `#![crate_type]` attribute can only be used at the crate root
}
#[crate_type = "bin"] fn main() {} //~ ERROR should be an inner

View file

@ -1,4 +1,4 @@
error: crate-level attribute should be in the root module
error: the `#![crate_type]` attribute can only be used at the crate root
--> $DIR/lint-misplaced-attr.rs:7:5
|
LL | #![crate_type = "bin"]
@ -10,16 +10,17 @@ note: the lint level is defined here
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: crate-level attribute should be an inner attribute
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]`
--> $DIR/lint-misplaced-attr.rs:10:1
|
LL | #[crate_type = "bin"] fn main() {}
| ^^^^^^^^^^^^^^^^^^^^^
|
help: add a `!`
note: this attribute does not have an `!`, which means it is applied to this function
--> $DIR/lint-misplaced-attr.rs:10:23
|
LL | #![crate_type = "bin"] fn main() {}
| +
LL | #[crate_type = "bin"] fn main() {}
| ^^^^^^^^^^^^
error: aborting due to 2 previous errors