Skip to content

Commit

Permalink
Auto merge of #118607 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
[stable] 1.74.1 release

This includes backports of:

*  Dispose llvm::TargetMachines prior to llvm::Context being disposed #118464
*  clarify fn discriminant guarantees: only free lifetimes may get erased #118006
*  Move subtyper below reveal_all and change reveal_all #116415
   *  Make subtyping explicit in MIR #115025 (needed for above)

As well as infrastructure fix:

*  Don't ask for a specific branch in cargotest #118597

r? `@Mark-Simulacrum`
  • Loading branch information
bors committed Dec 4, 2023
2 parents 79e9716 + de148ec commit a28077b
Show file tree
Hide file tree
Showing 44 changed files with 360 additions and 34 deletions.
7 changes: 7 additions & 0 deletions RELEASES.md
@@ -1,3 +1,10 @@
Version 1.74.1 (2023-12-07)
===========================

- [Resolved spurious STATUS_ACCESS_VIOLATIONs in LLVM](https://github.com/rust-lang/rust/pull/118464)
- [Clarify guarantees for std::mem::discriminant](https://github.com/rust-lang/rust/pull/118006)
- [Fix some subtyping-related regressions](https://github.com/rust-lang/rust/pull/116415)

Version 1.74.0 (2023-11-16)
==========================

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Expand Up @@ -2827,6 +2827,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Subtype(_)
| ProjectionElem::Index(_) => kind,
},
place_ty.projection_ty(tcx, elem),
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Expand Up @@ -242,6 +242,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ProjectionElem::Downcast(..) if opt.including_downcast => return None,
ProjectionElem::Downcast(..) => (),
ProjectionElem::OpaqueCast(..) => (),
ProjectionElem::Subtype(..) => (),
ProjectionElem::Field(field, _ty) => {
// FIXME(project-rfc_2229#36): print capture precisely here.
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
Expand Down Expand Up @@ -322,7 +323,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
}
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
ProjectionElem::Subtype(ty) | ProjectionElem::OpaqueCast(ty) => {
PlaceTy::from_ty(*ty)
}
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
},
};
Expand Down
Expand Up @@ -159,6 +159,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
[
..,
ProjectionElem::Index(_)
| ProjectionElem::Subtype(_)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. }
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Expand Up @@ -1803,6 +1803,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
for (place_base, elem) in place.iter_projections().rev() {
match elem {
ProjectionElem::Index(_/*operand*/) |
ProjectionElem::Subtype(_) |
ProjectionElem::OpaqueCast(_) |
ProjectionElem::ConstantIndex { .. } |
// assigning to P[i] requires P to be valid.
Expand Down Expand Up @@ -2191,6 +2192,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Subtype(..)
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Downcast(..) => {
let upvar_field_projection = self.is_upvar_field_projection(place);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/places_conflict.rs
Expand Up @@ -249,6 +249,7 @@ fn place_components_conflict<'tcx>(
| (ProjectionElem::ConstantIndex { .. }, _, _)
| (ProjectionElem::Subslice { .. }, _, _)
| (ProjectionElem::OpaqueCast { .. }, _, _)
| (ProjectionElem::Subtype(_), _, _)
| (ProjectionElem::Downcast { .. }, _, _) => {
// Recursive case. This can still be disjoint on a
// further iteration if this a shallow access and
Expand Down Expand Up @@ -508,6 +509,7 @@ fn place_projection_conflict<'tcx>(
| ProjectionElem::Field(..)
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subtype(_)
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_borrowck/src/prefixes.rs
Expand Up @@ -89,6 +89,9 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
cursor = cursor_base;
continue 'cursor;
}
ProjectionElem::Subtype(..) => {
panic!("Subtype projection is not allowed before borrow check")
}
ProjectionElem::Deref => {
// (handled below)
}
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Expand Up @@ -716,6 +716,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
PlaceTy::from_ty(fty)
}
ProjectionElem::Subtype(_) => {
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
}
ProjectionElem::OpaqueCast(ty) => {
let ty = self.sanitize_type(place, ty);
let ty = self.cx.normalize(ty, location);
Expand Down Expand Up @@ -2563,6 +2566,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| ProjectionElem::Subslice { .. } => {
// other field access
}
ProjectionElem::Subtype(_) => {
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/base.rs
Expand Up @@ -876,6 +876,7 @@ pub(crate) fn codegen_place<'tcx>(
cplace = cplace.place_deref(fx);
}
PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)),
PlaceElem::Field(field, _ty) => {
cplace = cplace.place_field(fx, field);
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_codegen_cranelift/src/value_and_place.rs
Expand Up @@ -674,6 +674,16 @@ impl<'tcx> CPlace<'tcx> {
}
}

/// Used for `ProjectionElem::Subtype`, `ty` has to be monomorphized before
/// passed on.
pub(crate) fn place_transmute_type(
self,
fx: &mut FunctionCx<'_, '_, 'tcx>,
ty: Ty<'tcx>,
) -> CPlace<'tcx> {
CPlace { inner: self.inner, layout: fx.layout_of(ty) }
}

pub(crate) fn place_field(
self,
fx: &mut FunctionCx<'_, '_, 'tcx>,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/lto.rs
Expand Up @@ -26,6 +26,7 @@ use std::ffi::{CStr, CString};
use std::fs::File;
use std::io;
use std::iter;
use std::mem::ManuallyDrop;
use std::path::Path;
use std::slice;
use std::sync::Arc;
Expand Down Expand Up @@ -736,7 +737,7 @@ pub unsafe fn optimize_thin_module(
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
let mut module = ModuleCodegen {
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
name: thin_module.name().to_string(),
kind: ModuleKind::Regular,
};
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_codegen_llvm/src/lib.rs
Expand Up @@ -49,6 +49,7 @@ use rustc_span::symbol::Symbol;
use std::any::Any;
use std::ffi::CStr;
use std::io::Write;
use std::mem::ManuallyDrop;

mod back {
pub mod archive;
Expand Down Expand Up @@ -404,8 +405,9 @@ pub struct ModuleLlvm {
llcx: &'static mut llvm::Context,
llmod_raw: *const llvm::Module,

// independent from llcx and llmod_raw, resources get disposed by drop impl
tm: OwnedTargetMachine,
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
tm: ManuallyDrop<OwnedTargetMachine>,
}

unsafe impl Send for ModuleLlvm {}
Expand All @@ -416,15 +418,23 @@ impl ModuleLlvm {
unsafe {
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
ModuleLlvm {
llmod_raw,
llcx,
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
}
}
}

fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
unsafe {
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
ModuleLlvm {
llmod_raw,
llcx,
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
}
}
}

Expand All @@ -445,7 +455,7 @@ impl ModuleLlvm {
}
};

Ok(ModuleLlvm { llmod_raw, llcx, tm })
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
}
}

Expand All @@ -457,6 +467,7 @@ impl ModuleLlvm {
impl Drop for ModuleLlvm {
fn drop(&mut self) {
unsafe {
ManuallyDrop::drop(&mut self.tm);
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/mir/place.rs
Expand Up @@ -466,6 +466,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::ProjectionElem::OpaqueCast(ty) => {
bug!("encountered OpaqueCast({ty}) in codegen")
}
mir::ProjectionElem::Subtype(ty) => cg_base.project_type(bx, self.monomorphize(ty)),
mir::ProjectionElem::Index(index) => {
let index = &mir::Operand::Copy(mir::Place::from(index));
let index = self.codegen_operand(bx, index);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Expand Up @@ -13,7 +13,7 @@ use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
TyAndLayout,
};
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_session::Limit;
use rustc_span::Span;
Expand Down Expand Up @@ -384,7 +384,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
// all normal lifetimes are erased, higher-ranked types with their
// late-bound lifetimes are still around and can lead to type
// differences.
if util::is_subtype(tcx, param_env, src.ty, dest.ty) {
if util::relate_types(tcx, param_env, Variance::Covariant, src.ty, dest.ty) {
// Make sure the layout is equal, too -- just to be safe. Miri really
// needs layout equality. For performance reason we skip this check when
// the types are equal. Equal types *can* have different layouts when
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Expand Up @@ -319,6 +319,8 @@ where
OpaqueCast(ty) => {
span_bug!(self.cur_span(), "OpaqueCast({ty}) encountered after borrowck")
}
// We don't want anything happening here, this is here as a dummy.
Subtype(_) => base.transmute(base.layout(), self)?,
Field(field, _) => self.project_field(base, field.index())?,
Downcast(_, variant) => self.project_downcast(base, variant)?,
Deref => self.deref_pointer(&base.to_op(self)?)?.into(),
Expand Down
Expand Up @@ -664,6 +664,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
| ProjectionElem::Downcast(..)
| ProjectionElem::OpaqueCast(..)
| ProjectionElem::Subslice { .. }
| ProjectionElem::Subtype(..)
| ProjectionElem::Field(..)
| ProjectionElem::Index(_) => {}
}
Expand Down
Expand Up @@ -306,6 +306,7 @@ where
ProjectionElem::Index(index) if in_local(index) => return true,

ProjectionElem::Deref
| ProjectionElem::Subtype(_)
| ProjectionElem::Field(_, _)
| ProjectionElem::OpaqueCast(_)
| ProjectionElem::ConstantIndex { .. }
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_const_eval/src/transform/promote_consts.rs
Expand Up @@ -357,7 +357,9 @@ impl<'tcx> Validator<'_, 'tcx> {
return Err(Unpromotable);
}

ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {}
ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subtype(_)
| ProjectionElem::Subslice { .. } => {}

ProjectionElem::Index(local) => {
let mut promotable = false;
Expand Down
32 changes: 30 additions & 2 deletions compiler/rustc_const_eval/src/transform/validate.rs
Expand Up @@ -7,7 +7,7 @@ use rustc_infer::traits::Reveal;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance};
use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
Expand All @@ -16,6 +16,8 @@ use rustc_target::spec::abi::Abi;

use crate::util::is_within_packed;

use crate::util::relate_types;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum EdgeKind {
Unwind,
Expand Down Expand Up @@ -602,7 +604,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return true;
}

crate::util::is_subtype(self.tcx, self.param_env, src, dest)
// After borrowck subtyping should be fully explicit via
// `Subtype` projections.
let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
Variance::Invariant
} else {
Variance::Covariant
};

crate::util::relate_types(self.tcx, self.param_env, variance, src, dest)
}
}

Expand Down Expand Up @@ -753,6 +763,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
}
ProjectionElem::Subtype(ty) => {
if !relate_types(
self.tcx,
self.param_env,
Variance::Covariant,
ty,
place_ref.ty(&self.body.local_decls, self.tcx).ty,
) {
self.fail(
location,
format!(
"Failed subtyping {ty:#?} and {:#?}",
place_ref.ty(&self.body.local_decls, self.tcx).ty
),
)
}
}
_ => {}
}
self.super_projection_elem(place_ref, elem, context, location);
Expand Down Expand Up @@ -1088,6 +1115,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// LHS and RHS of the assignment must have the same type.
let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);

if !self.mir_assign_valid_types(right_ty, left_ty) {
self.fail(
location,
Expand Down
14 changes: 10 additions & 4 deletions compiler/rustc_const_eval/src/util/compare_types.rs
Expand Up @@ -5,7 +5,7 @@

use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
use rustc_trait_selection::traits::ObligationCtxt;

/// Returns whether the two types are equal up to subtyping.
Expand All @@ -24,16 +24,22 @@ pub fn is_equal_up_to_subtyping<'tcx>(
}

// Check for subtyping in either direction.
is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
relate_types(tcx, param_env, Variance::Covariant, src, dest)
|| relate_types(tcx, param_env, Variance::Covariant, dest, src)
}

/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
///
/// When validating assignments, the variance should be `Covariant`. When checking
/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
/// because we want to check for type equality.
///
/// This mostly ignores opaque types as it can be used in constraining contexts
/// while still computing the final underlying type.
pub fn is_subtype<'tcx>(
pub fn relate_types<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
variance: Variance,
src: Ty<'tcx>,
dest: Ty<'tcx>,
) -> bool {
Expand All @@ -48,7 +54,7 @@ pub fn is_subtype<'tcx>(
let cause = ObligationCause::dummy();
let src = ocx.normalize(&cause, param_env, src);
let dest = ocx.normalize(&cause, param_env, dest);
match ocx.sub(&cause, param_env, src, dest) {
match ocx.relate(&cause, param_env, variance, src, dest) {
Ok(()) => {}
Err(_) => return false,
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/util/mod.rs
Expand Up @@ -7,7 +7,7 @@ mod type_name;

pub use self::alignment::{is_disaligned, is_within_packed};
pub use self::check_validity_requirement::check_validity_requirement;
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
pub use self::compare_types::{is_equal_up_to_subtyping, relate_types};
pub use self::type_name::type_name;

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
Expand Down

0 comments on commit a28077b

Please sign in to comment.