thir-unsafeck: print list of missing target features when calling a f… · rust-lang/rust@6b066a9 (original) (raw)

``

1

`+

use std::borrow::Cow;

`

``

2

+

1

3

`use crate::build::ExprCategory;

`

2

4

`use crate::errors::*;

`

3

5

`use rustc_middle::thir::visit::{self, Visitor};

`

4

6

``

``

7

`+

use rustc_errors::DiagnosticArgValue;

`

5

8

`use rustc_hir as hir;

`

6

9

`use rustc_middle::mir::BorrowKind;

`

7

10

`use rustc_middle::thir::*;

`

`@@ -392,15 +395,29 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {

`

392

395

`` // the call requires unsafe. Don't check this on wasm

``

393

396

`// targets, though. For more information on wasm see the

`

394

397

`// is_like_wasm check in hir_analysis/src/collect.rs

`

``

398

`+

let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;

`

395

399

`if !self.tcx.sess.target.options.is_like_wasm

`

396

``

`-

&& !self

`

397

``

`-

.tcx

`

398

``

`-

.codegen_fn_attrs(func_did)

`

399

``

`-

.target_features

`

``

400

`+

&& !callee_features

`

400

401

`.iter()

`

401

402

`.all(|feature| self.body_target_features.contains(feature))

`

402

403

`{

`

403

``

`-

self.requires_unsafe(expr.span, CallToFunctionWith(func_did));

`

``

404

`+

let missing: Vec<_> = callee_features

`

``

405

`+

.iter()

`

``

406

`+

.copied()

`

``

407

`+

.filter(|feature| !self.body_target_features.contains(feature))

`

``

408

`+

.collect();

`

``

409

`+

let build_enabled = self

`

``

410

`+

.tcx

`

``

411

`+

.sess

`

``

412

`+

.target_features

`

``

413

`+

.iter()

`

``

414

`+

.copied()

`

``

415

`+

.filter(|feature| missing.contains(feature))

`

``

416

`+

.collect();

`

``

417

`+

self.requires_unsafe(

`

``

418

`+

expr.span,

`

``

419

`+

CallToFunctionWith { function: func_did, missing, build_enabled },

`

``

420

`+

);

`

404

421

`}

`

405

422

`}

`

406

423

`}

`

`@@ -526,7 +543,7 @@ struct UnusedUnsafeWarning {

`

526

543

`enclosing_unsafe: Option,

`

527

544

`}

`

528

545

``

529

``

`-

#[derive(Clone, Copy, PartialEq)]

`

``

546

`+

#[derive(Clone, PartialEq)]

`

530

547

`enum UnsafeOpKind {

`

531

548

`CallToUnsafeFunction(Option),

`

532

549

`UseOfInlineAssembly,

`

`@@ -537,7 +554,15 @@ enum UnsafeOpKind {

`

537

554

`AccessToUnionField,

`

538

555

`MutationOfLayoutConstrainedField,

`

539

556

`BorrowOfLayoutConstrainedField,

`

540

``

`-

CallToFunctionWith(DefId),

`

``

557

`+

CallToFunctionWith {

`

``

558

`+

function: DefId,

`

``

559

`` +

/// Target features enabled in callee's #[target_feature] but missing in

``

``

560

`` +

/// caller's #[target_feature].

``

``

561

`+

missing: Vec,

`

``

562

`` +

/// Target features in missing that are enabled at compile time

``

``

563

`` +

/// (e.g., with -C target-feature).

``

``

564

`+

build_enabled: Vec,

`

``

565

`+

},

`

541

566

`}

`

542

567

``

543

568

`use UnsafeOpKind::*;

`

`@@ -658,13 +683,22 @@ impl UnsafeOpKind {

`

658

683

` unsafe_not_inherited_note,

`

659

684

`},

`

660

685

`),

`

661

``

`-

CallToFunctionWith(did) => tcx.emit_spanned_lint(

`

``

686

`+

CallToFunctionWith { function, missing, build_enabled } => tcx.emit_spanned_lint(

`

662

687

`UNSAFE_OP_IN_UNSAFE_FN,

`

663

688

` hir_id,

`

664

689

` span,

`

665

690

`UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {

`

666

691

` span,

`

667

``

`-

function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),

`

``

692

`+

function: &with_no_trimmed_paths!(tcx.def_path_str(*function)),

`

``

693

`+

missing_target_features: DiagnosticArgValue::StrListSepByAnd(

`

``

694

`+

missing.iter().map(|feature| Cow::from(feature.as_str())).collect(),

`

``

695

`+

),

`

``

696

`+

missing_target_features_count: missing.len(),

`

``

697

`+

note: if build_enabled.is_empty() { None } else { Some(()) },

`

``

698

`+

build_target_features: DiagnosticArgValue::StrListSepByAnd(

`

``

699

`+

build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(),

`

``

700

`+

),

`

``

701

`+

build_target_features_count: build_enabled.len(),

`

668

702

` unsafe_not_inherited_note,

`

669

703

`},

`

670

704

`),

`

`@@ -821,18 +855,38 @@ impl UnsafeOpKind {

`

821

855

` unsafe_not_inherited_note,

`

822

856

`});

`

823

857

`}

`

824

``

`-

CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => {

`

``

858

`+

CallToFunctionWith { function, missing, build_enabled }

`

``

859

`+

if unsafe_op_in_unsafe_fn_allowed =>

`

``

860

`+

{

`

825

861

` tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {

`

826

862

` span,

`

``

863

`+

missing_target_features: DiagnosticArgValue::StrListSepByAnd(

`

``

864

`+

missing.iter().map(|feature| Cow::from(feature.as_str())).collect(),

`

``

865

`+

),

`

``

866

`+

missing_target_features_count: missing.len(),

`

``

867

`+

note: if build_enabled.is_empty() { None } else { Some(()) },

`

``

868

`+

build_target_features: DiagnosticArgValue::StrListSepByAnd(

`

``

869

`+

build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(),

`

``

870

`+

),

`

``

871

`+

build_target_features_count: build_enabled.len(),

`

827

872

` unsafe_not_inherited_note,

`

828

``

`-

function: &tcx.def_path_str(*did),

`

``

873

`+

function: &tcx.def_path_str(*function),

`

829

874

`});

`

830

875

`}

`

831

``

`-

CallToFunctionWith(did) => {

`

``

876

`+

CallToFunctionWith { function, missing, build_enabled } => {

`

832

877

` tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe {

`

833

878

` span,

`

``

879

`+

missing_target_features: DiagnosticArgValue::StrListSepByAnd(

`

``

880

`+

missing.iter().map(|feature| Cow::from(feature.as_str())).collect(),

`

``

881

`+

),

`

``

882

`+

missing_target_features_count: missing.len(),

`

``

883

`+

note: if build_enabled.is_empty() { None } else { Some(()) },

`

``

884

`+

build_target_features: DiagnosticArgValue::StrListSepByAnd(

`

``

885

`+

build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(),

`

``

886

`+

),

`

``

887

`+

build_target_features_count: build_enabled.len(),

`

834

888

` unsafe_not_inherited_note,

`

835

``

`-

function: &tcx.def_path_str(*did),

`

``

889

`+

function: &tcx.def_path_str(*function),

`

836

890

`});

`

837

891

`}

`

838

892

`}

`