Reject macro calls inside of #![crate_name]
This commit is contained in:
parent
46d53a68aa
commit
9b6fd35738
21 changed files with 196 additions and 115 deletions
|
@ -667,11 +667,12 @@ fn print_crate_info(
|
||||||
return Compilation::Continue;
|
return Compilation::Continue;
|
||||||
};
|
};
|
||||||
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
|
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
|
||||||
let id = rustc_session::output::find_crate_name(sess, attrs);
|
let crate_name = passes::get_crate_name(sess, attrs);
|
||||||
let crate_types = collect_crate_types(sess, attrs);
|
let crate_types = collect_crate_types(sess, attrs);
|
||||||
for &style in &crate_types {
|
for &style in &crate_types {
|
||||||
let fname =
|
let fname = rustc_session::output::filename_for_input(
|
||||||
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
|
sess, style, crate_name, &t_outputs,
|
||||||
|
);
|
||||||
println_info!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
|
println_info!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -680,8 +681,7 @@ fn print_crate_info(
|
||||||
// no crate attributes, print out an error and exit
|
// no crate attributes, print out an error and exit
|
||||||
return Compilation::Continue;
|
return Compilation::Continue;
|
||||||
};
|
};
|
||||||
let id = rustc_session::output::find_crate_name(sess, attrs);
|
println_info!("{}", passes::get_crate_name(sess, attrs));
|
||||||
println_info!("{id}");
|
|
||||||
}
|
}
|
||||||
Cfg => {
|
Cfg => {
|
||||||
let mut cfgs = sess
|
let mut cfgs = sess
|
||||||
|
|
|
@ -183,12 +183,12 @@ pub(crate) fn mod_file_path_from_attr(
|
||||||
let first_path = attrs.iter().find(|at| at.has_name(sym::path))?;
|
let first_path = attrs.iter().find(|at| at.has_name(sym::path))?;
|
||||||
let Some(path_sym) = first_path.value_str() else {
|
let Some(path_sym) = first_path.value_str() else {
|
||||||
// This check is here mainly to catch attempting to use a macro,
|
// This check is here mainly to catch attempting to use a macro,
|
||||||
// such as #[path = concat!(...)]. This isn't currently supported
|
// such as `#[path = concat!(...)]`. This isn't supported because
|
||||||
// because otherwise the InvocationCollector would need to defer
|
// otherwise the `InvocationCollector` would need to defer loading
|
||||||
// loading a module until the #[path] attribute was expanded, and
|
// a module until the `#[path]` attribute was expanded, and it
|
||||||
// it doesn't support that (and would likely add a bit of
|
// doesn't support that (and would likely add a bit of complexity).
|
||||||
// complexity). Usually bad forms are checked in AstValidator (via
|
// Usually bad forms are checked during semantic analysis via
|
||||||
// `check_builtin_attribute`), but by the time that runs the macro
|
// `TyCtxt::check_mod_attrs`), but by the time that runs the macro
|
||||||
// is expanded, and it doesn't give an error.
|
// is expanded, and it doesn't give an error.
|
||||||
validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path);
|
validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path);
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,8 +117,9 @@ use rustc_data_structures::{base_n, flock};
|
||||||
use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize};
|
use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
use rustc_session::output::{collect_crate_types, find_crate_name};
|
use rustc_session::output::collect_crate_types;
|
||||||
use rustc_session::{Session, StableCrateId};
|
use rustc_session::{Session, StableCrateId};
|
||||||
|
use rustc_span::Symbol;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
|
@ -211,7 +212,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
|
||||||
/// The garbage collection will take care of it.
|
/// The garbage collection will take care of it.
|
||||||
///
|
///
|
||||||
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
|
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
|
||||||
pub(crate) fn prepare_session_directory(sess: &Session) {
|
pub(crate) fn prepare_session_directory(sess: &Session, crate_name: Symbol) {
|
||||||
if sess.opts.incremental.is_none() {
|
if sess.opts.incremental.is_none() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +222,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) {
|
||||||
debug!("prepare_session_directory");
|
debug!("prepare_session_directory");
|
||||||
|
|
||||||
// {incr-comp-dir}/{crate-name-and-disambiguator}
|
// {incr-comp-dir}/{crate-name-and-disambiguator}
|
||||||
let crate_dir = crate_path(sess);
|
let crate_dir = crate_path(sess, crate_name);
|
||||||
debug!("crate-dir: {}", crate_dir.display());
|
debug!("crate-dir: {}", crate_dir.display());
|
||||||
create_dir(sess, &crate_dir, "crate");
|
create_dir(sess, &crate_dir, "crate");
|
||||||
|
|
||||||
|
@ -594,10 +595,9 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
|
||||||
Ok(UNIX_EPOCH + duration)
|
Ok(UNIX_EPOCH + duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crate_path(sess: &Session) -> PathBuf {
|
fn crate_path(sess: &Session, crate_name: Symbol) -> PathBuf {
|
||||||
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
|
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
|
||||||
|
|
||||||
let crate_name = find_crate_name(sess, &[]);
|
|
||||||
let crate_types = collect_crate_types(sess, &[]);
|
let crate_types = collect_crate_types(sess, &[]);
|
||||||
let stable_crate_id = StableCrateId::new(
|
let stable_crate_id = StableCrateId::new(
|
||||||
crate_name,
|
crate_name,
|
||||||
|
|
|
@ -11,6 +11,7 @@ use rustc_serialize::Decodable;
|
||||||
use rustc_serialize::opaque::MemDecoder;
|
use rustc_serialize::opaque::MemDecoder;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_session::config::IncrementalStateAssertion;
|
use rustc_session::config::IncrementalStateAssertion;
|
||||||
|
use rustc_span::Symbol;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
|
|
||||||
use super::data::*;
|
use super::data::*;
|
||||||
|
@ -203,9 +204,9 @@ 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
|
/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
|
||||||
/// new graph to an incremental session directory.
|
/// new graph to an incremental session directory.
|
||||||
pub fn setup_dep_graph(sess: &Session) -> DepGraph {
|
pub fn setup_dep_graph(sess: &Session, crate_name: Symbol) -> DepGraph {
|
||||||
// `load_dep_graph` can only be called after `prepare_session_directory`.
|
// `load_dep_graph` can only be called after `prepare_session_directory`.
|
||||||
prepare_session_directory(sess);
|
prepare_session_directory(sess, crate_name);
|
||||||
|
|
||||||
let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));
|
let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@ interface_abi_required_feature_issue = for more information, see issue #116344 <
|
||||||
interface_cant_emit_mir =
|
interface_cant_emit_mir =
|
||||||
could not emit MIR: {$error}
|
could not emit MIR: {$error}
|
||||||
|
|
||||||
|
interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`
|
||||||
|
|
||||||
|
interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen
|
||||||
|
|
||||||
interface_emoji_identifier =
|
interface_emoji_identifier =
|
||||||
identifiers cannot contain emoji: `{$ident}`
|
identifiers cannot contain emoji: `{$ident}`
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,21 @@ use std::path::Path;
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(interface_crate_name_does_not_match)]
|
||||||
|
pub(crate) struct CrateNameDoesNotMatch {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) span: Span,
|
||||||
|
pub(crate) crate_name: Symbol,
|
||||||
|
pub(crate) attr_crate_name: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(interface_crate_name_invalid)]
|
||||||
|
pub(crate) struct CrateNameInvalid<'a> {
|
||||||
|
pub(crate) crate_name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(interface_ferris_identifier)]
|
#[diag(interface_ferris_identifier)]
|
||||||
pub struct FerrisIdentifier {
|
pub struct FerrisIdentifier {
|
||||||
|
|
|
@ -28,10 +28,12 @@ use rustc_passes::{abi_test, input_stats, layout_test};
|
||||||
use rustc_resolve::Resolver;
|
use rustc_resolve::Resolver;
|
||||||
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||||
use rustc_session::cstore::Untracked;
|
use rustc_session::cstore::Untracked;
|
||||||
use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name};
|
use rustc_session::output::{collect_crate_types, filename_for_input};
|
||||||
use rustc_session::search_paths::PathKind;
|
use rustc_session::search_paths::PathKind;
|
||||||
use rustc_session::{Limit, Session};
|
use rustc_session::{Limit, Session};
|
||||||
use rustc_span::{ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Symbol, sym};
|
use rustc_span::{
|
||||||
|
ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym,
|
||||||
|
};
|
||||||
use rustc_target::spec::PanicStrategy;
|
use rustc_target::spec::PanicStrategy;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
use tracing::{info, instrument};
|
use tracing::{info, instrument};
|
||||||
|
@ -725,8 +727,7 @@ 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 pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
|
||||||
|
|
||||||
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
let crate_name = get_crate_name(sess, &pre_configured_attrs);
|
||||||
let crate_name = find_crate_name(sess, &pre_configured_attrs);
|
|
||||||
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
|
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
|
||||||
let stable_crate_id = StableCrateId::new(
|
let stable_crate_id = StableCrateId::new(
|
||||||
crate_name,
|
crate_name,
|
||||||
|
@ -735,7 +736,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
||||||
sess.cfg_version,
|
sess.cfg_version,
|
||||||
);
|
);
|
||||||
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
|
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
|
||||||
let dep_graph = setup_dep_graph(sess);
|
let dep_graph = setup_dep_graph(sess, crate_name);
|
||||||
|
|
||||||
let cstore =
|
let cstore =
|
||||||
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
|
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
|
||||||
|
@ -1080,23 +1081,85 @@ pub(crate) fn start_codegen<'tcx>(
|
||||||
codegen
|
codegen
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
|
/// Compute and validate the crate name.
|
||||||
if let Some(attr) = krate_attrs
|
pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol {
|
||||||
.iter()
|
// We validate *all* occurrences of `#![crate_name]`, pick the first find and
|
||||||
.find(|attr| attr.has_name(sym::recursion_limit) && attr.value_str().is_none())
|
// if a crate name was passed on the command line via `--crate-name` we enforce
|
||||||
|
// that they match.
|
||||||
|
// We perform the validation step here instead of later to ensure it gets run
|
||||||
|
// in all code paths that require the crate name very early on, namely before
|
||||||
|
// macro expansion.
|
||||||
|
|
||||||
|
let attr_crate_name =
|
||||||
|
validate_and_find_value_str_builtin_attr(sym::crate_name, sess, krate_attrs);
|
||||||
|
|
||||||
|
let validate = |name, span| {
|
||||||
|
rustc_session::output::validate_crate_name(sess, name, span);
|
||||||
|
name
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(crate_name) = &sess.opts.crate_name {
|
||||||
|
let crate_name = Symbol::intern(crate_name);
|
||||||
|
if let Some((attr_crate_name, span)) = attr_crate_name
|
||||||
|
&& attr_crate_name != crate_name
|
||||||
{
|
{
|
||||||
// This is here mainly to check for using a macro, such as
|
sess.dcx().emit_err(errors::CrateNameDoesNotMatch {
|
||||||
// #![recursion_limit = foo!()]. That is not supported since that
|
span,
|
||||||
// would require expanding this while in the middle of expansion,
|
crate_name,
|
||||||
// which needs to know the limit before expanding. Otherwise,
|
attr_crate_name,
|
||||||
// validation would normally be caught in AstValidator (via
|
});
|
||||||
// `check_builtin_attribute`), 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,
|
|
||||||
attr,
|
|
||||||
sym::recursion_limit,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return validate(crate_name, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((crate_name, span)) = attr_crate_name {
|
||||||
|
return validate(crate_name, Some(span));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Input::File(ref path) = sess.io.input
|
||||||
|
&& let Some(file_stem) = path.file_stem().and_then(|s| s.to_str())
|
||||||
|
{
|
||||||
|
if file_stem.starts_with('-') {
|
||||||
|
sess.dcx().emit_err(errors::CrateNameInvalid { crate_name: file_stem });
|
||||||
|
} else {
|
||||||
|
return validate(Symbol::intern(&file_stem.replace('-', "_")), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sym::rust_out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
|
||||||
|
// We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
|
||||||
|
// because that would require expanding this while in the middle of expansion, which needs to
|
||||||
|
// know the limit before expanding.
|
||||||
|
let _ = validate_and_find_value_str_builtin_attr(sym::recursion_limit, sess, krate_attrs);
|
||||||
rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
|
rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find.
|
||||||
|
///
|
||||||
|
/// This validator is intended for built-in attributes whose value needs to be known very early
|
||||||
|
/// during compilation (namely, before macro expansion) and it mainly exists to reject macro calls
|
||||||
|
/// inside of the attributes, such as in `#![name = expand!()]`. Normal attribute validation happens
|
||||||
|
/// during semantic analysis via [`TyCtxt::check_mod_attrs`] which happens *after* macro expansion
|
||||||
|
/// when such macro calls (here: `expand`) have already been expanded and we can no longer check for
|
||||||
|
/// their presence.
|
||||||
|
///
|
||||||
|
/// [value-str]: ast::Attribute::value_str
|
||||||
|
fn validate_and_find_value_str_builtin_attr(
|
||||||
|
name: Symbol,
|
||||||
|
sess: &Session,
|
||||||
|
krate_attrs: &[ast::Attribute],
|
||||||
|
) -> Option<(Symbol, Span)> {
|
||||||
|
let mut result = None;
|
||||||
|
// Validate *all* relevant attributes, not just the first occurrence.
|
||||||
|
for attr in ast::attr::filter_by_name(krate_attrs, name) {
|
||||||
|
let Some(value) = attr.value_str() else {
|
||||||
|
validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, attr, name)
|
||||||
|
};
|
||||||
|
// Choose the first occurrence as our result.
|
||||||
|
result.get_or_insert((value, attr.span));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
|
@ -433,11 +433,11 @@ pub(crate) fn check_attr_crate_type(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is here mainly to check for using a macro, such as
|
// This is here mainly to check for using a macro, such as
|
||||||
// #![crate_type = foo!()]. That is not supported since the
|
// `#![crate_type = foo!()]`. That is not supported since the
|
||||||
// crate type needs to be known very early in compilation long
|
// crate type needs to be known very early in compilation long
|
||||||
// before expansion. Otherwise, validation would normally be
|
// before expansion. Otherwise, validation would normally be
|
||||||
// caught in AstValidator (via `check_builtin_attribute`), but
|
// caught during semantic analysis via `TyCtxt::check_mod_attrs`,
|
||||||
// by the time that runs the macro is expanded, and it doesn't
|
// but by the time that runs the macro is expanded, and it doesn't
|
||||||
// give an error.
|
// give an error.
|
||||||
validate_attr::emit_fatal_malformed_builtin_attribute(
|
validate_attr::emit_fatal_malformed_builtin_attribute(
|
||||||
&sess.psess,
|
&sess.psess,
|
||||||
|
|
|
@ -8,12 +8,8 @@ session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible
|
||||||
session_cli_feature_diagnostic_help =
|
session_cli_feature_diagnostic_help =
|
||||||
add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable
|
add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable
|
||||||
|
|
||||||
session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`
|
|
||||||
|
|
||||||
session_crate_name_empty = crate name must not be empty
|
session_crate_name_empty = crate name must not be empty
|
||||||
|
|
||||||
session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
|
|
||||||
|
|
||||||
session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version}
|
session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version}
|
||||||
|
|
||||||
session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled
|
session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled
|
||||||
|
|
|
@ -212,21 +212,6 @@ pub(crate) struct FileWriteFail<'a> {
|
||||||
pub(crate) err: String,
|
pub(crate) err: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(session_crate_name_does_not_match)]
|
|
||||||
pub(crate) struct CrateNameDoesNotMatch {
|
|
||||||
#[primary_span]
|
|
||||||
pub(crate) span: Span,
|
|
||||||
pub(crate) crate_name: Symbol,
|
|
||||||
pub(crate) attr_crate_name: Symbol,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(session_crate_name_invalid)]
|
|
||||||
pub(crate) struct CrateNameInvalid<'a> {
|
|
||||||
pub(crate) s: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(session_crate_name_empty)]
|
#[diag(session_crate_name_empty)]
|
||||||
pub(crate) struct CrateNameEmpty {
|
pub(crate) struct CrateNameEmpty {
|
||||||
|
|
|
@ -2,15 +2,12 @@
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rustc_ast::{self as ast, attr};
|
use rustc_ast as ast;
|
||||||
use rustc_span::{Span, Symbol, sym};
|
use rustc_span::{Span, Symbol, sym};
|
||||||
|
|
||||||
use crate::Session;
|
use crate::Session;
|
||||||
use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
use crate::config::{self, CrateType, OutFileName, OutputFilenames, OutputType};
|
||||||
use crate::errors::{
|
use crate::errors::{self, CrateNameEmpty, FileIsNotWriteable, InvalidCharacterInCrateName};
|
||||||
self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
|
|
||||||
InvalidCharacterInCrateName,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn out_filename(
|
pub fn out_filename(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
|
@ -49,53 +46,6 @@ fn is_writeable(p: &Path) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find and [validate] the crate name.
|
|
||||||
///
|
|
||||||
/// [validate]: validate_crate_name
|
|
||||||
pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol {
|
|
||||||
let validate = |name, span| {
|
|
||||||
validate_crate_name(sess, name, span);
|
|
||||||
name
|
|
||||||
};
|
|
||||||
|
|
||||||
// Look in attributes 100% of the time to make sure the attribute is marked
|
|
||||||
// as used. After doing this, however, we still prioritize a crate name from
|
|
||||||
// the command line over one found in the #[crate_name] attribute. If we
|
|
||||||
// find both we ensure that they're the same later on as well.
|
|
||||||
let attr_crate_name =
|
|
||||||
attr::find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
|
|
||||||
|
|
||||||
if let Some(crate_name) = &sess.opts.crate_name {
|
|
||||||
let crate_name = Symbol::intern(crate_name);
|
|
||||||
if let Some((attr, attr_crate_name)) = attr_crate_name
|
|
||||||
&& attr_crate_name != crate_name
|
|
||||||
{
|
|
||||||
sess.dcx().emit_err(CrateNameDoesNotMatch {
|
|
||||||
span: attr.span,
|
|
||||||
crate_name,
|
|
||||||
attr_crate_name,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return validate(crate_name, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((attr, crate_name)) = attr_crate_name {
|
|
||||||
return validate(crate_name, Some(attr.span));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Input::File(ref path) = sess.io.input
|
|
||||||
&& let Some(s) = path.file_stem().and_then(|s| s.to_str())
|
|
||||||
{
|
|
||||||
if s.starts_with('-') {
|
|
||||||
sess.dcx().emit_err(CrateNameInvalid { s });
|
|
||||||
} else {
|
|
||||||
return validate(Symbol::intern(&s.replace('-', "_")), None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sym::rust_out
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validate the given crate name.
|
/// Validate the given crate name.
|
||||||
///
|
///
|
||||||
/// Note that this validation is more permissive than identifier parsing. It considers
|
/// Note that this validation is more permissive than identifier parsing. It considers
|
||||||
|
|
6
tests/ui/attributes/crate-name-macro-call.rs
Normal file
6
tests/ui/attributes/crate-name-macro-call.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// issue: rust-lang/rust#122001
|
||||||
|
// Ensure we reject macro calls inside `#![crate_name]` as their result wouldn't get honored anyway.
|
||||||
|
|
||||||
|
#![crate_name = concat!("my", "crate")] //~ ERROR malformed `crate_name` attribute input
|
||||||
|
|
||||||
|
fn main() {}
|
8
tests/ui/attributes/crate-name-macro-call.stderr
Normal file
8
tests/ui/attributes/crate-name-macro-call.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: malformed `crate_name` attribute input
|
||||||
|
--> $DIR/crate-name-macro-call.rs:4:1
|
||||||
|
|
|
||||||
|
LL | #![crate_name = concat!("my", "crate")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Ensure we validate `#![crate_name]` on print requests and reject macro calls inside of it.
|
||||||
|
// See also <https://github.com/rust-lang/rust/issues/122001>.
|
||||||
|
|
||||||
|
//@ compile-flags: --print=crate-name
|
||||||
|
#![crate_name = concat!("wrapped")] //~ ERROR malformed `crate_name` attribute input
|
|
@ -0,0 +1,8 @@
|
||||||
|
error: malformed `crate_name` attribute input
|
||||||
|
--> $DIR/print-crate-name-request-malformed-crate-name.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #![crate_name = concat!("wrapped")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Ensure we validate `#![crate_name]` on print requests.
|
||||||
|
|
||||||
|
//@ compile-flags: --print=file-names
|
||||||
|
#![crate_name] //~ ERROR malformed `crate_name` attribute input
|
|
@ -0,0 +1,8 @@
|
||||||
|
error: malformed `crate_name` attribute input
|
||||||
|
--> $DIR/print-file-names-request-malformed-crate-name-1.rs:4:1
|
||||||
|
|
|
||||||
|
LL | #![crate_name]
|
||||||
|
| ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Ensure that we validate *all* `#![crate_name]`s on print requests, not just the first,
|
||||||
|
// and that we reject macro calls inside of them.
|
||||||
|
// See also <https://github.com/rust-lang/rust/issues/122001>.
|
||||||
|
|
||||||
|
//@ compile-flags: --print=file-names
|
||||||
|
#![crate_name = "this_one_is_okay"]
|
||||||
|
#![crate_name = concat!("this_one_is_not")] //~ ERROR malformed `crate_name` attribute input
|
|
@ -0,0 +1,8 @@
|
||||||
|
error: malformed `crate_name` attribute input
|
||||||
|
--> $DIR/print-file-names-request-malformed-crate-name-2.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #![crate_name = concat!("this_one_is_not")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Ensure we validate `#![crate_name]` on print requests and reject macro calls inside of it.
|
||||||
|
// See also <https://github.com/rust-lang/rust/issues/122001>.
|
||||||
|
|
||||||
|
//@ compile-flags: --print=file-names
|
||||||
|
#![crate_name = concat!("wrapped")] //~ ERROR malformed `crate_name` attribute input
|
|
@ -0,0 +1,8 @@
|
||||||
|
error: malformed `crate_name` attribute input
|
||||||
|
--> $DIR/print-file-names-request-malformed-crate-name.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #![crate_name = concat!("wrapped")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue