Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #99157

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f165843
Move EarlyBinder calls in rustc_typeck::outlives a bit further up
jackh726 Jul 2, 2022
9935796
Add bound_const_param_default
jackh726 Jul 8, 2022
ad9e1e3
Use map_bound
jackh726 Jul 8, 2022
b361638
Use constant eval to do strict validity checks
5225225 Jul 7, 2022
c84cfa4
All init checks go through rustc_const_eval, cleanup
5225225 Jul 9, 2022
ab4a80e
Adjust docs on old might_permit_raw_init, cleanup
5225225 Jul 9, 2022
b398fa5
Cleanup, move might_permit_raw_init to own file
5225225 Jul 9, 2022
fc26ca1
check non_exhaustive attr and private fields for transparent types
fee1-dead Jul 7, 2022
5fb6784
add more tests
fee1-dead Jul 10, 2022
3ac69d7
Fix sized check ICE in intrisicck
compiler-errors Jul 10, 2022
6c44357
fix(doctest): treat fatal parse errors as incomplete attributes
notriddle Jul 11, 2022
b7c1868
Cleanup not needed arguments
5225225 Jul 11, 2022
236c7c0
Add test for uninit value with validity invariant in array
5225225 Jul 11, 2022
988e754
placeholders -> inference vars in comment
jackh726 Jul 11, 2022
a93152d
Rollup merge of #99020 - fee1-dead-contrib:repr_transparent_non_exhau…
Dylan-DPC Jul 11, 2022
3f66c4e
Rollup merge of #99033 - 5225225:interpreter-validity-checks, r=oli-obk
Dylan-DPC Jul 11, 2022
542d036
Rollup merge of #99038 - jackh726:earlybinder-cleanup, r=lcnr
Dylan-DPC Jul 11, 2022
db4e980
Rollup merge of #99124 - compiler-errors:issue-99122, r=oli-obk
Dylan-DPC Jul 11, 2022
18a2fa7
Rollup merge of #99142 - notriddle:notriddle/doctest-multiline-crate-…
Dylan-DPC Jul 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3664,6 +3664,7 @@ dependencies = [
"rustc_arena",
"rustc_ast",
"rustc_attr",
"rustc_const_eval",
"rustc_data_structures",
"rustc_errors",
"rustc_fs_util",
Expand Down
11 changes: 3 additions & 8 deletions compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
pub(crate) use llvm::codegen_llvm_intrinsic_call;

use rustc_const_eval::might_permit_raw_init::might_permit_raw_init;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::symbol::{kw, sym, Symbol};
Expand Down Expand Up @@ -673,10 +674,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
}

if intrinsic == sym::assert_zero_valid
&& !layout.might_permit_raw_init(
fx,
InitKind::Zero,
fx.tcx.sess.opts.debugging_opts.strict_init_checks) {
&& !might_permit_raw_init(fx.tcx, layout, InitKind::Zero) {

with_no_trimmed_paths!({
crate::base::codegen_panic(
Expand All @@ -689,10 +687,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
}

if intrinsic == sym::assert_uninit_valid
&& !layout.might_permit_raw_init(
fx,
InitKind::Uninit,
fx.tcx.sess.opts.debugging_opts.strict_init_checks) {
&& !might_permit_raw_init(fx.tcx, layout, InitKind::Uninit) {

with_no_trimmed_paths!({
crate::base::codegen_panic(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
extern crate rustc_middle;
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ rustc_metadata = { path = "../rustc_metadata" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
rustc_const_eval = { path = "../rustc_const_eval" }

[dependencies.object]
version = "0.29.0"
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
source_info: mir::SourceInfo,
target: Option<mir::BasicBlock>,
cleanup: Option<mir::BasicBlock>,
strict_validity: bool,
) -> bool {
// Emit a panic or a no-op for `assert_*` intrinsics.
// These are intrinsics that compile to panics so that we can get a message
Expand All @@ -546,13 +545,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
_ => None,
});
if let Some(intrinsic) = panic_intrinsic {
use rustc_const_eval::might_permit_raw_init::might_permit_raw_init;
use AssertIntrinsic::*;

let ty = instance.unwrap().substs.type_at(0);
let layout = bx.layout_of(ty);
let do_panic = match intrinsic {
Inhabited => layout.abi.is_uninhabited(),
ZeroValid => !layout.might_permit_raw_init(bx, InitKind::Zero, strict_validity),
UninitValid => !layout.might_permit_raw_init(bx, InitKind::Uninit, strict_validity),
ZeroValid => !might_permit_raw_init(bx.tcx(), layout, InitKind::Zero),
UninitValid => !might_permit_raw_init(bx.tcx(), layout, InitKind::Uninit),
};
if do_panic {
let msg_str = with_no_visible_paths!({
Expand Down Expand Up @@ -687,7 +688,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
source_info,
target,
cleanup,
self.cx.tcx().sess.opts.debugging_opts.strict_init_checks,
) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
}

impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
pub(super) fn new(const_eval_limit: Limit, can_access_statics: bool) -> Self {
pub(crate) fn new(const_eval_limit: Limit, can_access_statics: bool) -> Self {
CompileTimeInterpreter {
steps_remaining: const_eval_limit.0,
stack: Vec::new(),
Expand Down
56 changes: 28 additions & 28 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use super::{
Pointer,
};

use crate::might_permit_raw_init::might_permit_raw_init;

mod caller_location;
mod type_name;

Expand Down Expand Up @@ -413,35 +415,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
),
)?;
}
if intrinsic_name == sym::assert_zero_valid
&& !layout.might_permit_raw_init(
self,
InitKind::Zero,
self.tcx.sess.opts.debugging_opts.strict_init_checks,
)
{
M::abort(
self,
format!(
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
ty
),
)?;

if intrinsic_name == sym::assert_zero_valid {
let should_panic = !might_permit_raw_init(*self.tcx, layout, InitKind::Zero);

if should_panic {
M::abort(
self,
format!(
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
ty
),
)?;
}
}
if intrinsic_name == sym::assert_uninit_valid
&& !layout.might_permit_raw_init(
self,
InitKind::Uninit,
self.tcx.sess.opts.debugging_opts.strict_init_checks,
)
{
M::abort(
self,
format!(
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
ty
),
)?;

if intrinsic_name == sym::assert_uninit_valid {
let should_panic = !might_permit_raw_init(*self.tcx, layout, InitKind::Uninit);

if should_panic {
M::abort(
self,
format!(
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
ty
),
)?;
}
}
}
sym::simd_insert => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern crate rustc_middle;
pub mod const_eval;
mod errors;
pub mod interpret;
pub mod might_permit_raw_init;
pub mod transform;
pub mod util;

Expand Down
44 changes: 44 additions & 0 deletions compiler/rustc_const_eval/src/might_permit_raw_init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::const_eval::CompileTimeInterpreter;
use crate::interpret::{InterpCx, MemoryKind, OpTy};
use rustc_middle::ty::layout::LayoutCx;
use rustc_middle::ty::{layout::TyAndLayout, ParamEnv, TyCtxt};
use rustc_session::Limit;
use rustc_target::abi::InitKind;

pub fn might_permit_raw_init<'tcx>(
tcx: TyCtxt<'tcx>,
ty: TyAndLayout<'tcx>,
kind: InitKind,
) -> bool {
let strict = tcx.sess.opts.debugging_opts.strict_init_checks;

if strict {
let machine = CompileTimeInterpreter::new(Limit::new(0), false);

let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);

// We could panic here... Or we could just return "yeah it's valid whatever". Or let
// codegen_panic_intrinsic return an error that halts compilation.
// I'm not exactly sure *when* this can fail. OOM?
let allocated = cx
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
.expect("failed to allocate for uninit check");

if kind == InitKind::Zero {
// Again, unclear what to do here if it fails.
cx.write_bytes_ptr(
allocated.ptr,
std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
)
.expect("failed to write bytes for zero valid check");
}

let ot: OpTy<'_, _> = allocated.into();

// Assume that if it failed, it's a validation failure.
cx.validate_operand(&ot).is_ok()
} else {
let layout_cx = LayoutCx { tcx, param_env: ParamEnv::reveal_all() };
ty.might_permit_raw_init(&layout_cx, kind)
}
}
51 changes: 51 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3132,6 +3132,56 @@ declare_lint! {
"detects unexpected names and values in `#[cfg]` conditions",
}

declare_lint! {
/// The `repr_transparent_external_private_fields` lint
/// detects types marked #[repr(trasparent)] that (transitively)
/// contain an external ZST type marked #[non_exhaustive]
///
/// ### Example
///
/// ```rust,ignore (needs external crate)
/// #![deny(repr_transparent_external_private_fields)]
/// use foo::NonExhaustiveZst;
///
/// #[repr(transparent)]
/// struct Bar(u32, ([u32; 0], NonExhaustiveZst));
/// ```
///
/// This will produce:
///
/// ```text
/// error: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
/// --> src/main.rs:3:1
/// |
/// 3 | #[macro_use]
/// | ^^^^^^^^^^^^
/// |
/// note: the lint level is defined here
/// --> src/main.rs:1:9
/// |
/// 1 | #![deny(repr_transparent_external_private_fields)]
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/// ```
///
/// ### Explanation
///
/// Previous, Rust accepted fields that contain external private zero-sized types,
/// even though it should not be a breaking change to add a non-zero-sized field to
/// that private type.
///
/// This is a [future-incompatible] lint to transition this
/// to a hard error in the future. See [issue #78586] for more details.
///
/// [issue #78586]: https://github.com/rust-lang/rust/issues/78586
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
Warn,
"tranparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #78586 <https://github.com/rust-lang/rust/issues/78586>",
};
}

declare_lint_pass! {
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
Expand Down Expand Up @@ -3237,6 +3287,7 @@ declare_lint_pass! {
DEPRECATED_WHERE_CLAUSE_LOCATION,
TEST_UNSTABLE_LINT,
FFI_UNWIND_CALLS,
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
]
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ impl GenericParamDef {
) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
match self.kind {
GenericParamDefKind::Type { has_default, .. } if has_default => {
Some(EarlyBinder(tcx.type_of(self.def_id).into()))
Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into()))
}
GenericParamDefKind::Const { has_default } if has_default => {
Some(EarlyBinder(tcx.const_param_default(self.def_id).into()))
Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into()))
}
_ => None,
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,10 @@ impl<T> EarlyBinder<T> {
let value = f(self.0)?;
Ok(EarlyBinder(value))
}

pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
EarlyBinder(value)
}
}

impl<T> EarlyBinder<Option<T>> {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,10 @@ impl<'tcx> TyCtxt<'tcx> {
) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
ty::EarlyBinder(self.item_bounds(def_id))
}

pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
ty::EarlyBinder(self.const_param_default(def_id))
}
}

struct OpaqueTypeExpander<'tcx> {
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,13 +537,12 @@ fn build_call_shim<'tcx>(
};

let def_id = instance.def_id();
let sig = tcx.fn_sig(def_id);
let mut sig = tcx.erase_late_bound_regions(sig);
let sig = tcx.bound_fn_sig(def_id);
let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig));

assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
if let Some(sig_substs) = sig_substs {
sig = EarlyBinder(sig).subst(tcx, sig_substs);
}
let mut sig =
if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 };

if let CallKind::Indirect(fnty) = call_kind {
// `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
Expand Down
Loading