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;
|
||||
};
|
||||
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);
|
||||
for &style in &crate_types {
|
||||
let fname =
|
||||
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
|
||||
let fname = rustc_session::output::filename_for_input(
|
||||
sess, style, crate_name, &t_outputs,
|
||||
);
|
||||
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
|
||||
return Compilation::Continue;
|
||||
};
|
||||
let id = rustc_session::output::find_crate_name(sess, attrs);
|
||||
println_info!("{id}");
|
||||
println_info!("{}", passes::get_crate_name(sess, attrs));
|
||||
}
|
||||
Cfg => {
|
||||
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 Some(path_sym) = first_path.value_str() else {
|
||||
// This check is here mainly to catch attempting to use a macro,
|
||||
// such as #[path = concat!(...)]. This isn't currently supported
|
||||
// because otherwise the InvocationCollector would need to defer
|
||||
// loading a module until the #[path] attribute was expanded, and
|
||||
// it doesn't support that (and would likely add a bit of
|
||||
// complexity). Usually bad forms are checked in AstValidator (via
|
||||
// `check_builtin_attribute`), but by the time that runs the macro
|
||||
// such as `#[path = concat!(...)]`. This isn't supported because
|
||||
// otherwise the `InvocationCollector` would need to defer loading
|
||||
// a module until the `#[path]` attribute was expanded, and it
|
||||
// doesn't support that (and would likely add a bit of complexity).
|
||||
// Usually bad forms are checked 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, 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_middle::bug;
|
||||
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_span::Symbol;
|
||||
use tracing::debug;
|
||||
|
||||
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.
|
||||
///
|
||||
/// [`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() {
|
||||
return;
|
||||
}
|
||||
|
@ -221,7 +222,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) {
|
|||
debug!("prepare_session_directory");
|
||||
|
||||
// {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());
|
||||
create_dir(sess, &crate_dir, "crate");
|
||||
|
||||
|
@ -594,10 +595,9 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
|
|||
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 crate_name = find_crate_name(sess, &[]);
|
||||
let crate_types = collect_crate_types(sess, &[]);
|
||||
let stable_crate_id = StableCrateId::new(
|
||||
crate_name,
|
||||
|
|
|
@ -11,6 +11,7 @@ use rustc_serialize::Decodable;
|
|||
use rustc_serialize::opaque::MemDecoder;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::IncrementalStateAssertion;
|
||||
use rustc_span::Symbol;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
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
|
||||
/// 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`.
|
||||
prepare_session_directory(sess);
|
||||
prepare_session_directory(sess, crate_name);
|
||||
|
||||
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 =
|
||||
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 =
|
||||
identifiers cannot contain emoji: `{$ident}`
|
||||
|
||||
|
|
|
@ -4,6 +4,21 @@ use std::path::Path;
|
|||
use rustc_macros::Diagnostic;
|
||||
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)]
|
||||
#[diag(interface_ferris_identifier)]
|
||||
pub struct FerrisIdentifier {
|
||||
|
|
|
@ -28,10 +28,12 @@ use rustc_passes::{abi_test, input_stats, layout_test};
|
|||
use rustc_resolve::Resolver;
|
||||
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||
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::{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_trait_selection::traits;
|
||||
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);
|
||||
|
||||
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
||||
let crate_name = find_crate_name(sess, &pre_configured_attrs);
|
||||
let crate_name = get_crate_name(sess, &pre_configured_attrs);
|
||||
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
|
||||
let stable_crate_id = StableCrateId::new(
|
||||
crate_name,
|
||||
|
@ -735,7 +736,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
|||
sess.cfg_version,
|
||||
);
|
||||
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 =
|
||||
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
|
||||
|
@ -1080,23 +1081,85 @@ pub(crate) fn start_codegen<'tcx>(
|
|||
codegen
|
||||
}
|
||||
|
||||
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
|
||||
if let Some(attr) = krate_attrs
|
||||
.iter()
|
||||
.find(|attr| attr.has_name(sym::recursion_limit) && attr.value_str().is_none())
|
||||
{
|
||||
// This is here mainly to check for using a macro, such as
|
||||
// #![recursion_limit = foo!()]. That is not supported since that
|
||||
// would require expanding this while in the middle of expansion,
|
||||
// which needs to know the limit before expanding. Otherwise,
|
||||
// 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,
|
||||
);
|
||||
/// Compute and validate the crate name.
|
||||
pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol {
|
||||
// We validate *all* occurrences of `#![crate_name]`, pick the first find and
|
||||
// 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
|
||||
{
|
||||
sess.dcx().emit_err(errors::CrateNameDoesNotMatch {
|
||||
span,
|
||||
crate_name,
|
||||
attr_crate_name,
|
||||
});
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
// 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
|
||||
// before expansion. Otherwise, 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
|
||||
// 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,
|
||||
|
|
|
@ -8,12 +8,8 @@ session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible
|
|||
session_cli_feature_diagnostic_help =
|
||||
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_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_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,
|
||||
}
|
||||
|
||||
#[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)]
|
||||
#[diag(session_crate_name_empty)]
|
||||
pub(crate) struct CrateNameEmpty {
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
|
||||
use std::path::Path;
|
||||
|
||||
use rustc_ast::{self as ast, attr};
|
||||
use rustc_ast as ast;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::Session;
|
||||
use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||
use crate::errors::{
|
||||
self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
|
||||
InvalidCharacterInCrateName,
|
||||
};
|
||||
use crate::config::{self, CrateType, OutFileName, OutputFilenames, OutputType};
|
||||
use crate::errors::{self, CrateNameEmpty, FileIsNotWriteable, InvalidCharacterInCrateName};
|
||||
|
||||
pub fn out_filename(
|
||||
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.
|
||||
///
|
||||
/// 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