Skip to content

Commit b2f8864

Browse files
authored
Unrolled build for rust-lang#134586
Rollup merge of rust-lang#134586 - Urgau:fn-ptr-lint-option, r=compiler-errors Also lint on option of function pointer comparisons This PR is the first part of rust-lang#134536, ie. the linting on `Option<{fn ptr}>` in the `unpredictable_function_pointer_comparisons` lint, which isn't part of the lang nomination that the second part is going trough, and so should be able to be approved independently. Related to rust-lang#134527 r? `@compiler-errors`
2 parents 5f23ef7 + 9965ad7 commit b2f8864

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

compiler/rustc_lint/src/types.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
44
use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange};
55
use rustc_data_structures::fx::FxHashSet;
66
use rustc_errors::DiagMessage;
7-
use rustc_hir::{Expr, ExprKind};
7+
use rustc_hir::{Expr, ExprKind, LangItem};
88
use rustc_middle::bug;
99
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
1010
use rustc_middle::ty::{
@@ -444,7 +444,25 @@ fn lint_fn_pointer<'tcx>(
444444
let (l_ty, l_ty_refs) = peel_refs(l_ty);
445445
let (r_ty, r_ty_refs) = peel_refs(r_ty);
446446

447-
if !l_ty.is_fn() || !r_ty.is_fn() {
447+
if l_ty.is_fn() && r_ty.is_fn() {
448+
// both operands are function pointers, fallthrough
449+
} else if let ty::Adt(l_def, l_args) = l_ty.kind()
450+
&& let ty::Adt(r_def, r_args) = r_ty.kind()
451+
&& cx.tcx.is_lang_item(l_def.did(), LangItem::Option)
452+
&& cx.tcx.is_lang_item(r_def.did(), LangItem::Option)
453+
&& let Some(l_some_arg) = l_args.get(0)
454+
&& let Some(r_some_arg) = r_args.get(0)
455+
&& l_some_arg.expect_ty().is_fn()
456+
&& r_some_arg.expect_ty().is_fn()
457+
{
458+
// both operands are `Option<{function ptr}>`
459+
return cx.emit_span_lint(
460+
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
461+
e.span,
462+
UnpredictableFunctionPointerComparisons::Warn,
463+
);
464+
} else {
465+
// types are not function pointers, nothing to do
448466
return;
449467
}
450468

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This test checks that we lint on Option of fn ptr.
2+
//
3+
// https://github.com/rust-lang/rust/issues/134527.
4+
//
5+
//@ check-pass
6+
7+
unsafe extern "C" fn func() {}
8+
9+
type FnPtr = unsafe extern "C" fn();
10+
11+
fn main() {
12+
let _ = Some::<FnPtr>(func) == Some(func as unsafe extern "C" fn());
13+
//~^ WARN function pointer comparisons
14+
15+
// Undecided as of https://github.com/rust-lang/rust/pull/134536
16+
assert_eq!(Some::<FnPtr>(func), Some(func as unsafe extern "C" fn()));
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
2+
--> $DIR/fn-ptr-comparisons-some.rs:12:13
3+
|
4+
LL | let _ = Some::<FnPtr>(func) == Some(func as unsafe extern "C" fn());
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: the address of the same function can vary between different codegen units
8+
= note: furthermore, different functions could have the same address after being merged together
9+
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
10+
= note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default
11+
12+
warning: 1 warning emitted
13+

0 commit comments

Comments
 (0)