Skip to content

Commit

Permalink
Auto merge of rust-lang#114748 - cuviper:beta-next, r=cuviper
Browse files Browse the repository at this point in the history
[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
  • Loading branch information
bors committed Aug 12, 2023
2 parents d8fd588 + 4d05014 commit d1fa3e4
Show file tree
Hide file tree
Showing 29 changed files with 306 additions and 133 deletions.
25 changes: 22 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::{env, mem, str};
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_metadata::find_native_static_library;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
Expand Down Expand Up @@ -659,8 +660,6 @@ impl<'a> Linker for GccLinker<'a> {
return;
}

// FIXME(#99978) hide #[no_mangle] symbols for proc-macros

let is_windows = self.sess.target.is_like_windows;
let path = tmpdir.join(if is_windows { "list.def" } else { "list" });

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

let mut symbols = Vec::new();
if let CrateType::ProcMacro = crate_type {
exported_symbols_for_proc_macro_crate(tcx)
} else {
exported_symbols_for_non_proc_macro(tcx, crate_type)
}
}

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

fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
// `exported_symbols` will be empty when !should_codegen.
if !tcx.sess.opts.output_types.should_codegen() {
return Vec::new();
}

let stable_crate_id = tcx.sess.local_stable_crate_id();
let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);

vec![proc_macro_decls_name, metadata_symbol_name]
}

pub(crate) fn linked_symbols(
tcx: TyCtxt<'_>,
crate_type: CrateType,
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ lint_builtin_unused_doc_comment = unused doc comment
lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
.suggestion = use `loop`
lint_cast_ref_to_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
lint_check_name_unknown = unknown lint: `{$lint_name}`
Expand Down Expand Up @@ -264,8 +262,6 @@ lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
lint_improper_ctypes_char_reason = the `char` type has no C equivalent
lint_improper_ctypes_dyn = trait objects have no C equivalent
lint_improper_ctypes_enum_phantomdata = this enum contains a PhantomData field
lint_improper_ctypes_enum_repr_help =
consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
Expand Down Expand Up @@ -319,6 +315,8 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir
lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable
lint_invalid_reference_casting = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
lint_lintpass_by_hand = implementing `LintPass` by hand
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ extern crate tracing;

mod array_into_iter;
pub mod builtin;
mod cast_ref_to_mut;
mod context;
mod deref_into_dyn_supertrait;
mod drop_forget_useless;
Expand All @@ -77,6 +76,7 @@ mod opaque_hidden_inferred_bound;
mod pass_by_value;
mod passes;
mod redundant_semicolon;
mod reference_casting;
mod traits;
mod types;
mod unused;
Expand All @@ -98,7 +98,6 @@ use rustc_span::Span;

use array_into_iter::ArrayIntoIter;
use builtin::*;
use cast_ref_to_mut::*;
use deref_into_dyn_supertrait::*;
use drop_forget_useless::*;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
Expand All @@ -117,6 +116,7 @@ use noop_method_call::*;
use opaque_hidden_inferred_bound::*;
use pass_by_value::*;
use redundant_semicolon::*;
use reference_casting::*;
use traits::*;
use types::*;
use unused::*;
Expand Down Expand Up @@ -216,7 +216,7 @@ late_lint_methods!(
BoxPointers: BoxPointers,
PathStatements: PathStatements,
LetUnderscore: LetUnderscore,
CastRefToMut: CastRefToMut,
InvalidReferenceCasting: InvalidReferenceCasting,
// Depends on referenced function signatures in expressions
UnusedResults: UnusedResults,
NonUpperCaseGlobals: NonUpperCaseGlobals,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,10 +737,10 @@ pub enum InvalidFromUtf8Diag {
},
}

// cast_ref_to_mut.rs
// reference_casting.rs
#[derive(LintDiagnostic)]
#[diag(lint_cast_ref_to_mut)]
pub struct CastRefToMutDiag;
#[diag(lint_invalid_reference_casting)]
pub struct InvalidReferenceCastingDiag;

// hidden_unicode_codepoints.rs
#[derive(LintDiagnostic)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ use rustc_hir::{Expr, ExprKind, MutTy, TyKind, UnOp};
use rustc_middle::ty;
use rustc_span::sym;

use crate::{lints::CastRefToMutDiag, LateContext, LateLintPass, LintContext};
use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext};

declare_lint! {
/// The `cast_ref_to_mut` lint checks for casts of `&T` to `&mut T`
/// The `invalid_reference_casting` lint checks for casts of `&T` to `&mut T`
/// without using interior mutability.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![deny(invalid_reference_casting)]
/// fn x(r: &i32) {
/// unsafe {
/// *(r as *const i32 as *mut i32) += 1;
Expand All @@ -28,14 +29,14 @@ declare_lint! {
///
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
/// mutable.
CAST_REF_TO_MUT,
Deny,
INVALID_REFERENCE_CASTING,
Allow,
"casts of `&T` to `&mut T` without interior mutability"
}

declare_lint_pass!(CastRefToMut => [CAST_REF_TO_MUT]);
declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);

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

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

let e = e.peel_blocks();
if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind() {
cx.emit_spanned_lint(CAST_REF_TO_MUT, expr.span, CastRefToMutDiag);
cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag);
}
}
}
104 changes: 48 additions & 56 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -963,12 +963,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
substs: SubstsRef<'tcx>,
) -> FfiResult<'tcx> {
let field_ty = field.ty(self.cx.tcx, substs);
if field_ty.has_opaque_types() {
self.check_type_for_ffi(cache, field_ty)
} else {
let field_ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, field_ty);
self.check_type_for_ffi(cache, field_ty)
}
let field_ty = self
.cx
.tcx
.try_normalize_erasing_regions(self.cx.param_env, field_ty)
.unwrap_or(field_ty);
self.check_type_for_ffi(cache, field_ty)
}

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

let transparent_safety = def.repr().transparent().then(|| {
// Can assume that at most one field is not a ZST, so only check
// that field's type for FFI-safety.
let transparent_with_all_zst_fields = if def.repr().transparent() {
if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
return self.check_field_type_for_ffi(cache, field, substs);
// Transparent newtypes have at most one non-ZST field which needs to be checked..
match self.check_field_type_for_ffi(cache, field, substs) {
FfiUnsafe { ty, .. } if ty.is_unit() => (),
r => return r,
}

false
} else {
// All fields are ZSTs; this means that the type should behave
// like (), which is FFI-unsafe... except if all fields are PhantomData,
// which is tested for below
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None }
// ..or have only ZST fields, which is FFI-unsafe (unless those fields are all
// `PhantomData`).
true
}
});
// We can't completely trust repr(C) markings; make sure the fields are
// actually safe.
} else {
false
};

// We can't completely trust `repr(C)` markings, so make sure the fields are actually safe.
let mut all_phantom = !variant.fields.is_empty();
for field in &variant.fields {
match self.check_field_type_for_ffi(cache, &field, substs) {
FfiSafe => {
all_phantom = false;
}
FfiPhantom(..) if !def.repr().transparent() && def.is_enum() => {
return FfiUnsafe {
ty,
reason: fluent::lint_improper_ctypes_enum_phantomdata,
help: None,
};
}
FfiPhantom(..) => {}
r => return transparent_safety.unwrap_or(r),
all_phantom &= match self.check_field_type_for_ffi(cache, &field, substs) {
FfiSafe => false,
// `()` fields are FFI-safe!
FfiUnsafe { ty, .. } if ty.is_unit() => false,
FfiPhantom(..) => true,
r @ FfiUnsafe { .. } => return r,
}
}

if all_phantom { FfiPhantom(ty) } else { transparent_safety.unwrap_or(FfiSafe) }
if all_phantom {
FfiPhantom(ty)
} else if transparent_with_all_zst_fields {
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None }
} else {
FfiSafe
}
}

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

let sig = tcx.erase_late_bound_regions(sig);
if !sig.output().is_unit() {
let r = self.check_type_for_ffi(cache, sig.output());
match r {
FfiSafe => {}
_ => {
return r;
}
}
}
for arg in sig.inputs() {
let r = self.check_type_for_ffi(cache, *arg);
match r {
match self.check_type_for_ffi(cache, *arg) {
FfiSafe => {}
_ => {
return r;
}
r => return r,
}
}
FfiSafe

let ret_ty = sig.output();
if ret_ty.is_unit() {
return FfiSafe;
}

self.check_type_for_ffi(cache, ret_ty)
}

ty::Foreign(..) => FfiSafe,
Expand Down Expand Up @@ -1317,7 +1315,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if let Some(ty) = self
.cx
.tcx
.normalize_erasing_regions(self.cx.param_env, ty)
.try_normalize_erasing_regions(self.cx.param_env, ty)
.unwrap_or(ty)
.visit_with(&mut ProhibitOpaqueTypes)
.break_value()
{
Expand All @@ -1335,16 +1334,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
is_static: bool,
is_return_type: bool,
) {
// We have to check for opaque types before `normalize_erasing_regions`,
// which will replace opaque types with their underlying concrete type.
if self.check_for_opaque_ty(sp, ty) {
// We've already emitted an error due to an opaque type.
return;
}

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

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

// Don't report FFI errors for unit return types. This check exists here, and not in
// `check_foreign_fn` (where it would make more sense) so that normalization has definitely
// the caller (where it would make more sense) so that normalization has definitely
// happened.
if is_return_type && ty.is_unit() {
return;
Expand All @@ -1370,9 +1365,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
None,
);
}
// If `ty` is a `repr(transparent)` newtype, and the non-zero-sized type is a generic
// argument, which after substitution, is `()`, then this branch can be hit.
FfiResult::FfiUnsafe { ty, .. } if is_return_type && ty.is_unit() => {}
FfiResult::FfiUnsafe { ty, reason, help } => {
self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
}
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,10 @@ impl<'tcx> Inliner<'tcx> {
validation: Ok(()),
};

for var_debug_info in callee_body.var_debug_info.iter() {
checker.visit_var_debug_info(var_debug_info);
}

// Traverse the MIR manually so we can account for the effects of inlining on the CFG.
let mut work_list = vec![START_BLOCK];
let mut visited = BitSet::new_empty(callee_body.basic_blocks.len());
Expand Down Expand Up @@ -847,7 +851,16 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
if let ProjectionElem::Field(f, ty) = elem {
let parent_ty = place_ref.ty(&self.callee_body.local_decls, self.tcx);
let check_equal = |this: &mut Self, f_ty| {
if !util::is_equal_up_to_subtyping(this.tcx, this.param_env, ty, f_ty) {
// Fast path if there is nothing to substitute.
if ty == f_ty {
return;
}
let ty = this.instance.subst_mir(this.tcx, ty::EarlyBinder::bind(&ty));
let f_ty = this.instance.subst_mir(this.tcx, ty::EarlyBinder::bind(&f_ty));
if ty == f_ty {
return;
}
if !util::is_subtype(this.tcx, this.param_env, ty, f_ty) {
trace!(?ty, ?f_ty);
this.validation = Err("failed to normalize projection type");
return;
Expand Down
Loading

0 comments on commit d1fa3e4

Please sign in to comment.