@@ -405,7 +405,10 @@ Session::handle_option (
405
405
{
406
406
auto error = Error (Location (), std::string ());
407
407
if ((ret = validate_crate_name (arg, error)))
408
- options.set_crate_name (arg);
408
+ {
409
+ options.set_crate_name (arg);
410
+ options.crate_name_set_manually = true ;
411
+ }
409
412
else
410
413
{
411
414
rust_assert (!error.message .empty ());
@@ -553,19 +556,9 @@ Session::parse_files (int num_files, const char **files)
553
556
filename = files[0 ];
554
557
555
558
auto crate_name = infer_crate_name (filename);
556
- Error error ((Location ()), std::string ());
557
559
rust_debug (" inferred crate name: %s" , crate_name.c_str ());
558
- if (!validate_crate_name (crate_name, error))
559
- {
560
- // fake a linemapping so that we can show the filename
561
- linemap->start_file (filename, 0 );
562
- linemap->start_line (0 , 1 );
563
- error.emit_error ();
564
- rust_inform (linemap->get_location (0 ),
565
- " crate name inferred from this file" );
566
- linemap->stop ();
567
- return ;
568
- }
560
+ // set the preliminary crate name here
561
+ // we will figure out the real crate name in `handle_crate_name`
569
562
options.set_crate_name (crate_name);
570
563
}
571
564
@@ -582,6 +575,57 @@ Session::parse_files (int num_files, const char **files)
582
575
* per-file. */
583
576
}
584
577
578
+ void
579
+ Session::handle_crate_name (AST::Crate parsed_crate)
580
+ {
581
+ auto mappings = Analysis::Mappings::get ();
582
+ auto crate_name_changed = false ;
583
+ auto error = Error (Location (), std::string ());
584
+
585
+ for (const auto &attr : parsed_crate.inner_attrs )
586
+ {
587
+ if (attr.get_path () != " crate_name" )
588
+ continue ;
589
+ if (!attr.has_attr_input ())
590
+ {
591
+ rust_error_at (attr.get_locus (),
592
+ " %<crate_name%> accepts one argument" );
593
+ continue ;
594
+ }
595
+
596
+ auto &literal
597
+ = static_cast <AST::AttrInputLiteral &> (attr.get_attr_input ());
598
+ const auto &msg_str = literal.get_literal ().as_string ();
599
+ if (!validate_crate_name (msg_str, error))
600
+ {
601
+ error.locus = attr.get_locus ();
602
+ error.emit_error ();
603
+ continue ;
604
+ }
605
+
606
+ auto options = Session::get_instance ().options ;
607
+ if (options.crate_name_set_manually && (options.crate_name != msg_str))
608
+ {
609
+ rust_error_at (attr.get_locus (),
610
+ " %<-frust-crate-name%> and %<#[crate_name]%> are "
611
+ " required to match, but %qs does not match %qs" ,
612
+ options.crate_name .c_str (), msg_str.c_str ());
613
+ }
614
+ crate_name_changed = true ;
615
+ options.set_crate_name (msg_str);
616
+ mappings->set_crate_name (mappings->get_current_crate (), msg_str);
617
+ }
618
+
619
+ options.crate_name_set_manually |= crate_name_changed;
620
+ if (!options.crate_name_set_manually
621
+ && !validate_crate_name (options.crate_name , error))
622
+ {
623
+ error.emit_error ();
624
+ rust_inform (linemap->get_location (0 ),
625
+ " crate name inferred from this file" );
626
+ }
627
+ }
628
+
585
629
// Parses a single file with filename filename.
586
630
void
587
631
Session::parse_file (const char *filename)
@@ -606,6 +650,9 @@ Session::parse_file (const char *filename)
606
650
auto mappings = Analysis::Mappings::get ();
607
651
mappings->insert_ast_crate (&parsed_crate);
608
652
653
+ // handle crate name
654
+ handle_crate_name (parsed_crate);
655
+
609
656
if (options.dump_option_enabled (CompileOptions::LEXER_DUMP))
610
657
{
611
658
dump_lex (parser);
0 commit comments