Auto merge of #140592 - cuviper:beta-next, r=cuviper · rust-lang/rust@973ec11 (original) (raw)

`@@ -301,8 +301,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn

`

301

301

``

302

302

`let filename = FileName::anon_source_code(&wrapped_source);

`

303

303

``

304

``

`-

// Any errors in parsing should also appear when the doctest is compiled for real, so just

`

305

``

`` -

// send all the errors that librustc_ast emits directly into a Sink instead of stderr.

``

306

304

`let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));

`

307

305

`let fallback_bundle = rustc_errors::fallback_fluent_bundle(

`

308

306

` rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),

`

`@@ -311,7 +309,8 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn

`

311

309

` info.supports_color =

`

312

310

`HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone())

`

313

311

`.supports_color();

`

314

``

-

``

312

`+

// Any errors in parsing should also appear when the doctest is compiled for real, so just

`

``

313

`` +

// send all the errors that the parser emits directly into a Sink instead of stderr.

``

315

314

`let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);

`

316

315

``

317

316

`` // FIXME(misdreavus): pass -Z treat-err-as-bug to the doctest parser

``

`@@ -339,9 +338,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn

`

339

338

`*prev_span_hi = hi;

`

340

339

`}

`

341

340

``

342

``

`-

// Recurse through functions body. It is necessary because the doctest source code is

`

343

``

`-

// wrapped in a function to limit the number of AST errors. If we don't recurse into

`

344

``

`-

// functions, we would thing all top-level items (so basically nothing).

`

345

341

`fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool {

`

346

342

`let mut is_extern_crate = false;

`

347

343

`if !info.has_global_allocator

`

`@@ -351,8 +347,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn

`

351

347

`}

`

352

348

`match item.kind {

`

353

349

` ast::ItemKind::Fn(_) if !info.has_main_fn => {

`

354

``

`-

// We only push if it's the top item because otherwise, we would duplicate

`

355

``

`-

// its content since the top-level item was already added.

`

356

350

`if item.ident.name == sym::main {

`

357

351

` info.has_main_fn = true;

`

358

352

`}

`

`@@ -411,37 +405,46 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn

`

411

405

`push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);

`

412

406

`}

`

413

407

`}

`

``

408

`+

let mut has_non_items = false;

`

414

409

`for stmt in &body.stmts {

`

415

410

`let mut is_extern_crate = false;

`

416

411

`match stmt.kind {

`

417

412

`StmtKind::Item(ref item) => {

`

418

``

`-

is_extern_crate = check_item(&item, &mut info, crate_name);

`

419

``

`-

}

`

420

``

`-

StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => {

`

421

``

`-

reset_error_count(&psess);

`

422

``

`-

return Err(());

`

``

413

`+

is_extern_crate = check_item(item, &mut info, crate_name);

`

423

414

`}

`

424

``

`-

StmtKind::MacCall(ref mac_call) if !info.has_main_fn => {

`

425

``

`-

let mut iter = mac_call.mac.args.tokens.iter();

`

426

``

-

427

``

`-

while let Some(token) = iter.next() {

`

428

``

`-

if let TokenTree::Token(token, _) = token

`

429

``

`-

&& let TokenKind::Ident(name, _) = token.kind

`

430

``

`-

&& name == kw::Fn

`

431

``

`-

&& let Some(TokenTree::Token(fn_token, _)) = iter.peek()

`

432

``

`-

&& let TokenKind::Ident(fn_name, _) = fn_token.kind

`

433

``

`-

&& fn_name == sym::main

`

434

``

`-

&& let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = {

`

435

``

`-

iter.next();

`

436

``

`-

iter.peek()

`

``

415

`+

// We assume that the macro calls will expand to item(s) even though they could

`

``

416

`+

// expand to statements and expressions.

`

``

417

`+

StmtKind::MacCall(ref mac_call) => {

`

``

418

`+

if !info.has_main_fn {

`

``

419

`` +

// For backward compatibility, we look for the token sequence fn main(…)

``

``

420

`+

// in the macro input (!) to crudely detect main functions "masked by a

`

``

421

`+

// wrapper macro". For the record, this is a horrible heuristic!

`

``

422

`+

// See https://github.com/rust-lang/rust/issues/56898.

`

``

423

`+

let mut iter = mac_call.mac.args.tokens.iter();

`

``

424

`+

while let Some(token) = iter.next() {

`

``

425

`+

if let TokenTree::Token(token, _) = token

`

``

426

`+

&& let TokenKind::Ident(kw::Fn, _) = token.kind

`

``

427

`+

&& let Some(TokenTree::Token(ident, _)) = iter.peek()

`

``

428

`+

&& let TokenKind::Ident(sym::main, _) = ident.kind

`

``

429

`+

&& let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, _)) = {

`

``

430

`+

iter.next();

`

``

431

`+

iter.peek()

`

``

432

`+

}

`

``

433

`+

{

`

``

434

`+

info.has_main_fn = true;

`

``

435

`+

break;

`

437

436

`}

`

438

``

`-

{

`

439

``

`-

info.has_main_fn = true;

`

440

``

`-

break;

`

441

437

`}

`

442

438

`}

`

443

439

`}

`

444

``

`-

_ => {}

`

``

440

`+

StmtKind::Expr(ref expr) => {

`

``

441

`+

if matches!(expr.kind, ast::ExprKind::Err(_)) {

`

``

442

`+

reset_error_count(&psess);

`

``

443

`+

return Err(());

`

``

444

`+

}

`

``

445

`+

has_non_items = true;

`

``

446

`+

}

`

``

447

`+

StmtKind::Let() | StmtKind::Semi() | StmtKind::Empty => has_non_items = true,

`

445

448

`}

`

446

449

``

447

450

`` // Weirdly enough, the Stmt span doesn't include its attributes, so we need to

``

`@@ -466,6 +469,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn

`

466

469

`push_to_s(&mut info.crates, source, span, &mut prev_span_hi);

`

467

470

`}

`

468

471

`}

`

``

472

`+

if has_non_items {

`

``

473

`` +

// FIXME: if info.has_main_fn is true, emit a warning here to mention that

``

``

474

`+

// this code will not be called.

`

``

475

`+

info.has_main_fn = false;

`

``

476

`+

}

`

469

477

`Ok(info)

`

470

478

`}

`

471

479

`Err(e) => {

`