Skip to content

Commit d1fa3e4

Browse files
committed
Auto merge of rust-lang#114748 - cuviper:beta-next, r=cuviper
[beta] backport * Restrict linker version script of proc-macro crates to just its two symbols rust-lang#114470 * bootstrap: config: fix version comparison bug rust-lang#114440 * lint/ctypes: only try normalize rust-lang#113921 * Avoid tls access while iterating through mpsc thread entries rust-lang#113861 * Substitute types before checking inlining compatibility. rust-lang#113802 * Revert "fix: bug etc/bash_complettion -> src/etc/... to avoid copy error" rust-lang#113579 * lint/ctypes: fix () return type checks rust-lang#113457 * Rename and allow cast_ref_to_mut lint rust-lang#113422 * Ignore flaky clippy tests. rust-lang#113621 r? cuviper
2 parents d8fd588 + 4d05014 commit d1fa3e4

29 files changed

+306
-133
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::{env, mem, str};
1313
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
1414
use rustc_metadata::find_native_static_library;
1515
use rustc_middle::middle::dependency_format::Linkage;
16+
use rustc_middle::middle::exported_symbols;
1617
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind};
1718
use rustc_middle::ty::TyCtxt;
1819
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
@@ -659,8 +660,6 @@ impl<'a> Linker for GccLinker<'a> {
659660
return;
660661
}
661662

662-
// FIXME(#99978) hide #[no_mangle] symbols for proc-macros
663-
664663
let is_windows = self.sess.target.is_like_windows;
665664
let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
666665

@@ -1679,8 +1678,15 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
16791678
return exports.iter().map(ToString::to_string).collect();
16801679
}
16811680

1682-
let mut symbols = Vec::new();
1681+
if let CrateType::ProcMacro = crate_type {
1682+
exported_symbols_for_proc_macro_crate(tcx)
1683+
} else {
1684+
exported_symbols_for_non_proc_macro(tcx, crate_type)
1685+
}
1686+
}
16831687

1688+
fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
1689+
let mut symbols = Vec::new();
16841690
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
16851691
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
16861692
if info.level.is_below_threshold(export_threshold) {
@@ -1691,6 +1697,19 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
16911697
symbols
16921698
}
16931699

1700+
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
1701+
// `exported_symbols` will be empty when !should_codegen.
1702+
if !tcx.sess.opts.output_types.should_codegen() {
1703+
return Vec::new();
1704+
}
1705+
1706+
let stable_crate_id = tcx.sess.local_stable_crate_id();
1707+
let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
1708+
let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
1709+
1710+
vec![proc_macro_decls_name, metadata_symbol_name]
1711+
}
1712+
16941713
pub(crate) fn linked_symbols(
16951714
tcx: TyCtxt<'_>,
16961715
crate_type: CrateType,

compiler/rustc_lint/messages.ftl

+2-4
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,6 @@ lint_builtin_unused_doc_comment = unused doc comment
155155
lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
156156
.suggestion = use `loop`
157157
158-
lint_cast_ref_to_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
159-
160158
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
161159
162160
lint_check_name_unknown = unknown lint: `{$lint_name}`
@@ -264,8 +262,6 @@ lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
264262
lint_improper_ctypes_char_reason = the `char` type has no C equivalent
265263
lint_improper_ctypes_dyn = trait objects have no C equivalent
266264
267-
lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
268-
269265
lint_improper_ctypes_enum_repr_help =
270266
consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
271267
@@ -319,6 +315,8 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir
319315
320316
lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable
321317
318+
lint_invalid_reference_casting = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
319+
322320
lint_lintpass_by_hand = implementing `LintPass` by hand
323321
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
324322

compiler/rustc_lint/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ extern crate tracing;
5050

5151
mod array_into_iter;
5252
pub mod builtin;
53-
mod cast_ref_to_mut;
5453
mod context;
5554
mod deref_into_dyn_supertrait;
5655
mod drop_forget_useless;
@@ -77,6 +76,7 @@ mod opaque_hidden_inferred_bound;
7776
mod pass_by_value;
7877
mod passes;
7978
mod redundant_semicolon;
79+
mod reference_casting;
8080
mod traits;
8181
mod types;
8282
mod unused;
@@ -98,7 +98,6 @@ use rustc_span::Span;
9898

9999
use array_into_iter::ArrayIntoIter;
100100
use builtin::*;
101-
use cast_ref_to_mut::*;
102101
use deref_into_dyn_supertrait::*;
103102
use drop_forget_useless::*;
104103
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
@@ -117,6 +116,7 @@ use noop_method_call::*;
117116
use opaque_hidden_inferred_bound::*;
118117
use pass_by_value::*;
119118
use redundant_semicolon::*;
119+
use reference_casting::*;
120120
use traits::*;
121121
use types::*;
122122
use unused::*;
@@ -216,7 +216,7 @@ late_lint_methods!(
216216
BoxPointers: BoxPointers,
217217
PathStatements: PathStatements,
218218
LetUnderscore: LetUnderscore,
219-
CastRefToMut: CastRefToMut,
219+
InvalidReferenceCasting: InvalidReferenceCasting,
220220
// Depends on referenced function signatures in expressions
221221
UnusedResults: UnusedResults,
222222
NonUpperCaseGlobals: NonUpperCaseGlobals,

compiler/rustc_lint/src/lints.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -737,10 +737,10 @@ pub enum InvalidFromUtf8Diag {
737737
},
738738
}
739739

740-
// cast_ref_to_mut.rs
740+
// reference_casting.rs
741741
#[derive(LintDiagnostic)]
742-
#[diag(lint_cast_ref_to_mut)]
743-
pub struct CastRefToMutDiag;
742+
#[diag(lint_invalid_reference_casting)]
743+
pub struct InvalidReferenceCastingDiag;
744744

745745
// hidden_unicode_codepoints.rs
746746
#[derive(LintDiagnostic)]

compiler/rustc_lint/src/cast_ref_to_mut.rs compiler/rustc_lint/src/reference_casting.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ use rustc_hir::{Expr, ExprKind, MutTy, TyKind, UnOp};
33
use rustc_middle::ty;
44
use rustc_span::sym;
55

6-
use crate::{lints::CastRefToMutDiag, LateContext, LateLintPass, LintContext};
6+
use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext};
77

88
declare_lint! {
9-
/// The `cast_ref_to_mut` lint checks for casts of `&T` to `&mut T`
9+
/// The `invalid_reference_casting` lint checks for casts of `&T` to `&mut T`
1010
/// without using interior mutability.
1111
///
1212
/// ### Example
1313
///
1414
/// ```rust,compile_fail
15+
/// # #![deny(invalid_reference_casting)]
1516
/// fn x(r: &i32) {
1617
/// unsafe {
1718
/// *(r as *const i32 as *mut i32) += 1;
@@ -28,14 +29,14 @@ declare_lint! {
2829
///
2930
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
3031
/// mutable.
31-
CAST_REF_TO_MUT,
32-
Deny,
32+
INVALID_REFERENCE_CASTING,
33+
Allow,
3334
"casts of `&T` to `&mut T` without interior mutability"
3435
}
3536

36-
declare_lint_pass!(CastRefToMut => [CAST_REF_TO_MUT]);
37+
declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);
3738

38-
impl<'tcx> LateLintPass<'tcx> for CastRefToMut {
39+
impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
3940
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
4041
let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else { return; };
4142

@@ -66,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for CastRefToMut {
6667

6768
let e = e.peel_blocks();
6869
if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind() {
69-
cx.emit_spanned_lint(CAST_REF_TO_MUT, expr.span, CastRefToMutDiag);
70+
cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag);
7071
}
7172
}
7273
}

compiler/rustc_lint/src/types.rs

+48-56
Original file line numberDiff line numberDiff line change
@@ -963,12 +963,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
963963
substs: SubstsRef<'tcx>,
964964
) -> FfiResult<'tcx> {
965965
let field_ty = field.ty(self.cx.tcx, substs);
966-
if field_ty.has_opaque_types() {
967-
self.check_type_for_ffi(cache, field_ty)
968-
} else {
969-
let field_ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, field_ty);
970-
self.check_type_for_ffi(cache, field_ty)
971-
}
966+
let field_ty = self
967+
.cx
968+
.tcx
969+
.try_normalize_erasing_regions(self.cx.param_env, field_ty)
970+
.unwrap_or(field_ty);
971+
self.check_type_for_ffi(cache, field_ty)
972972
}
973973

974974
/// Checks if the given `VariantDef`'s field types are "ffi-safe".
@@ -982,39 +982,43 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
982982
) -> FfiResult<'tcx> {
983983
use FfiResult::*;
984984

985-
let transparent_safety = def.repr().transparent().then(|| {
986-
// Can assume that at most one field is not a ZST, so only check
987-
// that field's type for FFI-safety.
985+
let transparent_with_all_zst_fields = if def.repr().transparent() {
988986
if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
989-
return self.check_field_type_for_ffi(cache, field, substs);
987+
// Transparent newtypes have at most one non-ZST field which needs to be checked..
988+
match self.check_field_type_for_ffi(cache, field, substs) {
989+
FfiUnsafe { ty, .. } if ty.is_unit() => (),
990+
r => return r,
991+
}
992+
993+
false
990994
} else {
991-
// All fields are ZSTs; this means that the type should behave
992-
// like (), which is FFI-unsafe... except if all fields are PhantomData,
993-
// which is tested for below
994-
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None }
995+
// ..or have only ZST fields, which is FFI-unsafe (unless those fields are all
996+
// `PhantomData`).
997+
true
995998
}
996-
});
997-
// We can't completely trust repr(C) markings; make sure the fields are
998-
// actually safe.
999+
} else {
1000+
false
1001+
};
1002+
1003+
// We can't completely trust `repr(C)` markings, so make sure the fields are actually safe.
9991004
let mut all_phantom = !variant.fields.is_empty();
10001005
for field in &variant.fields {
1001-
match self.check_field_type_for_ffi(cache, &field, substs) {
1002-
FfiSafe => {
1003-
all_phantom = false;
1004-
}
1005-
FfiPhantom(..) if !def.repr().transparent() && def.is_enum() => {
1006-
return FfiUnsafe {
1007-
ty,
1008-
reason: fluent::lint_improper_ctypes_enum_phantomdata,
1009-
help: None,
1010-
};
1011-
}
1012-
FfiPhantom(..) => {}
1013-
r => return transparent_safety.unwrap_or(r),
1006+
all_phantom &= match self.check_field_type_for_ffi(cache, &field, substs) {
1007+
FfiSafe => false,
1008+
// `()` fields are FFI-safe!
1009+
FfiUnsafe { ty, .. } if ty.is_unit() => false,
1010+
FfiPhantom(..) => true,
1011+
r @ FfiUnsafe { .. } => return r,
10141012
}
10151013
}
10161014

1017-
if all_phantom { FfiPhantom(ty) } else { transparent_safety.unwrap_or(FfiSafe) }
1015+
if all_phantom {
1016+
FfiPhantom(ty)
1017+
} else if transparent_with_all_zst_fields {
1018+
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None }
1019+
} else {
1020+
FfiSafe
1021+
}
10181022
}
10191023

10201024
/// Checks if the given type is "ffi-safe" (has a stable, well-defined
@@ -1217,25 +1221,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12171221
}
12181222

12191223
let sig = tcx.erase_late_bound_regions(sig);
1220-
if !sig.output().is_unit() {
1221-
let r = self.check_type_for_ffi(cache, sig.output());
1222-
match r {
1223-
FfiSafe => {}
1224-
_ => {
1225-
return r;
1226-
}
1227-
}
1228-
}
12291224
for arg in sig.inputs() {
1230-
let r = self.check_type_for_ffi(cache, *arg);
1231-
match r {
1225+
match self.check_type_for_ffi(cache, *arg) {
12321226
FfiSafe => {}
1233-
_ => {
1234-
return r;
1235-
}
1227+
r => return r,
12361228
}
12371229
}
1238-
FfiSafe
1230+
1231+
let ret_ty = sig.output();
1232+
if ret_ty.is_unit() {
1233+
return FfiSafe;
1234+
}
1235+
1236+
self.check_type_for_ffi(cache, ret_ty)
12391237
}
12401238

12411239
ty::Foreign(..) => FfiSafe,
@@ -1317,7 +1315,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13171315
if let Some(ty) = self
13181316
.cx
13191317
.tcx
1320-
.normalize_erasing_regions(self.cx.param_env, ty)
1318+
.try_normalize_erasing_regions(self.cx.param_env, ty)
1319+
.unwrap_or(ty)
13211320
.visit_with(&mut ProhibitOpaqueTypes)
13221321
.break_value()
13231322
{
@@ -1335,16 +1334,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13351334
is_static: bool,
13361335
is_return_type: bool,
13371336
) {
1338-
// We have to check for opaque types before `normalize_erasing_regions`,
1339-
// which will replace opaque types with their underlying concrete type.
13401337
if self.check_for_opaque_ty(sp, ty) {
13411338
// We've already emitted an error due to an opaque type.
13421339
return;
13431340
}
13441341

1345-
// it is only OK to use this function because extern fns cannot have
1346-
// any generic types right now:
1347-
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
1342+
let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty);
13481343

13491344
// C doesn't really support passing arrays by value - the only way to pass an array by value
13501345
// is through a struct. So, first test that the top level isn't an array, and then
@@ -1354,7 +1349,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13541349
}
13551350

13561351
// Don't report FFI errors for unit return types. This check exists here, and not in
1357-
// `check_foreign_fn` (where it would make more sense) so that normalization has definitely
1352+
// the caller (where it would make more sense) so that normalization has definitely
13581353
// happened.
13591354
if is_return_type && ty.is_unit() {
13601355
return;
@@ -1370,9 +1365,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13701365
None,
13711366
);
13721367
}
1373-
// If `ty` is a `repr(transparent)` newtype, and the non-zero-sized type is a generic
1374-
// argument, which after substitution, is `()`, then this branch can be hit.
1375-
FfiResult::FfiUnsafe { ty, .. } if is_return_type && ty.is_unit() => {}
13761368
FfiResult::FfiUnsafe { ty, reason, help } => {
13771369
self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
13781370
}

compiler/rustc_mir_transform/src/inline.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ impl<'tcx> Inliner<'tcx> {
440440
validation: Ok(()),
441441
};
442442

443+
for var_debug_info in callee_body.var_debug_info.iter() {
444+
checker.visit_var_debug_info(var_debug_info);
445+
}
446+
443447
// Traverse the MIR manually so we can account for the effects of inlining on the CFG.
444448
let mut work_list = vec![START_BLOCK];
445449
let mut visited = BitSet::new_empty(callee_body.basic_blocks.len());
@@ -847,7 +851,16 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
847851
if let ProjectionElem::Field(f, ty) = elem {
848852
let parent_ty = place_ref.ty(&self.callee_body.local_decls, self.tcx);
849853
let check_equal = |this: &mut Self, f_ty| {
850-
if !util::is_equal_up_to_subtyping(this.tcx, this.param_env, ty, f_ty) {
854+
// Fast path if there is nothing to substitute.
855+
if ty == f_ty {
856+
return;
857+
}
858+
let ty = this.instance.subst_mir(this.tcx, ty::EarlyBinder::bind(&ty));
859+
let f_ty = this.instance.subst_mir(this.tcx, ty::EarlyBinder::bind(&f_ty));
860+
if ty == f_ty {
861+
return;
862+
}
863+
if !util::is_subtype(this.tcx, this.param_env, ty, f_ty) {
851864
trace!(?ty, ?f_ty);
852865
this.validation = Err("failed to normalize projection type");
853866
return;

0 commit comments

Comments
 (0)