Skip to content

Commit

Permalink
Auto merge of #123147 - matthiaskrgr:rollup-2t5ot36, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #121943 (Clarify atomic bit validity)
 - #123075 (CFI: Fix drop and drop_in_place)
 - #123101 (Delegation: fix ICE on wrong `Self` instantiation)
 - #123130 (Load missing type of impl associated constant from trait definition)
 - #123133 (chore: fix some comments)
 - #123136 (Some wording improvement)
 - #123139 (`num::NonZero::get` can be 1 transmute instead of 2)
 - #123142 (Let nils know about changes to target docs)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Mar 28, 2024
2 parents 9d70954 + 145211e commit d779a7a
Show file tree
Hide file tree
Showing 43 changed files with 478 additions and 271 deletions.
4 changes: 2 additions & 2 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ toolchain.
directory and uncomment the line `MSYS2_PATH_TYPE=inherit`.
You could install and use MSYS2's version of git instead with `pacman`,
however this is not recommended as it's excrutiatingly slow, and not frequently
tested for compatability.
however this is not recommended as it's excruciatingly slow, and not frequently
tested for compatibility.
3. Start a MINGW64 or MINGW32 shell (depending on whether you want 32-bit
or 64-bit Rust) either from your start menu, or by running `mingw64.exe`
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub(crate) struct FixupContext {
}

/// The default amount of fixing is minimal fixing. Fixups should be turned on
/// in a targetted fashion where needed.
/// in a targeted fashion where needed.
impl Default for FixupContext {
fn default() -> Self {
FixupContext {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
}
// If the region is live at at least one location in the promoted MIR,
// If the region is live at least one location in the promoted MIR,
// then add a liveness constraint to the main MIR for this region
// at the location provided as an argument to this method
//
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ fn const_validate_mplace<'mir, 'tcx>(
}
};
ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
// Instead of just reporting the `InterpError` via the usual machinery, we give a more targetted
// Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
// error about the validation failure.
.map_err(|error| report_validation_error(&ecx, error, alloc_id))?;
inner = true;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::HirTyLowerer;
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Prohibit or lint against *bare* trait object types depending on the edition.
///
/// *Bare* trait object types are ones that aren't preceeded by the keyword `dyn`.
/// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
/// In edition 2021 and onward we emit a hard error for them.
pub(super) fn prohibit_or_lint_bare_trait_object_ty(
&self,
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2212,6 +2212,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
try_emit("delegation with early bound generics");
}

// There is no way to instantiate `Self` param for caller if
// 1. callee is a trait method
// 2. delegation item isn't an associative item
if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
&& let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
&& self.tcx().associated_item(sig_id).container
== ty::AssocItemContainer::TraitContainer
{
try_emit("delegation to a trait method from a free function");
}

if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
try_emit("delegation to async functions");
}
Expand Down
110 changes: 57 additions & 53 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,6 @@ macro_rules! type_error_struct {
})
}

/// If this `DefId` is a "primary tables entry", returns
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
///
/// If this function returns `Some`, then `typeck_results(def_id)` will
/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
/// may not succeed. In some cases where this function returns `None`
/// (notably closures), `typeck_results(def_id)` would wind up
/// redirecting to the owning function.
fn primary_body_of(
node: Node<'_>,
) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
Some((node.body_id()?, node.ty(), node.fn_sig()))
}

fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// Closures' typeck results come from their outermost function,
// as they are part of the same "inference environment".
Expand All @@ -106,7 +92,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}

if let Some(def_id) = def_id.as_local() {
primary_body_of(tcx.hir_node_by_def_id(def_id)).is_some()
tcx.hir_node_by_def_id(def_id).body_id().is_some()
} else {
false
}
Expand Down Expand Up @@ -163,7 +149,7 @@ fn typeck_with_fallback<'tcx>(
let span = tcx.hir().span(id);

// Figure out what primary body this item has.
let (body_id, body_ty, fn_sig) = primary_body_of(node).unwrap_or_else(|| {
let body_id = node.body_id().unwrap_or_else(|| {
span_bug!(span, "can't type-check body of {:?}", def_id);
});
let body = tcx.hir().body(body_id);
Expand All @@ -176,7 +162,7 @@ fn typeck_with_fallback<'tcx>(
}
let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id);

if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
fcx.lowerer().lower_fn_ty(id, header.unsafety, header.abi, decl, None, None)
} else {
Expand All @@ -191,42 +177,7 @@ fn typeck_with_fallback<'tcx>(

check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params);
} else {
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty {
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}))
} else if let Node::AnonConst(_) = node {
match tcx.parent_hir_node(id) {
Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), .. })
if anon_const.hir_id == id =>
{
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}))
}
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
asm.operands.iter().find_map(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
// Inline assembly constants must be integers.
Some(fcx.next_int_var())
}
hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}))
}
_ => None,
})
}
_ => None,
}
} else {
None
};
let expected_type = infer_type_if_missing(&fcx, node);
let expected_type = expected_type.unwrap_or_else(fallback);

let expected_type = fcx.normalize(body.value.span, expected_type);
Expand Down Expand Up @@ -296,6 +247,59 @@ fn typeck_with_fallback<'tcx>(
typeck_results
}

fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> {
let tcx = fcx.tcx;
let def_id = fcx.body_id;
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() {
if let Some(item) = tcx.opt_associated_item(def_id.into())
&& let ty::AssocKind::Const = item.kind
&& let ty::ImplContainer = item.container
&& let Some(trait_item) = item.trait_item_def_id
{
let args =
tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
Some(tcx.type_of(trait_item).instantiate(tcx, args))
} else {
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}))
}
} else if let Node::AnonConst(_) = node {
let id = tcx.local_def_id_to_hir_id(def_id);
match tcx.parent_hir_node(id) {
Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. })
if anon_const.hir_id == id =>
{
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
}))
}
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
asm.operands.iter().find_map(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
// Inline assembly constants must be integers.
Some(fcx.next_int_var())
}
hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}))
}
_ => None,
})
}
_ => None,
}
} else {
None
};
expected_type
}

/// When `check_fn` is invoked on a coroutine (i.e., a body that
/// includes yield), it returns back some information about the yield
/// points.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2768,7 +2768,7 @@ impl<'a> Parser<'a> {
};
return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) {
// We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the
// parser state and emit a targetted suggestion.
// parser state and emit a targeted suggestion.
let span = vec![start_span, self.token.span];
let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
self.bump(); // )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1112,8 +1112,36 @@ pub fn typeid_for_instance<'tcx>(
mut instance: Instance<'tcx>,
options: TypeIdOptions,
) -> String {
if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
instance.args = strip_receiver_auto(tcx, instance.args)
if (matches!(instance.def, ty::InstanceDef::Virtual(..))
&& Some(instance.def_id()) == tcx.lang_items().drop_in_place_fn())
|| matches!(instance.def, ty::InstanceDef::DropGlue(..))
{
// Adjust the type ids of DropGlues
//
// DropGlues may have indirect calls to one or more given types drop function. Rust allows
// for types to be erased to any trait object and retains the drop function for the original
// type, which means at the indirect call sites in DropGlues, when typeid_for_fnabi is
// called a second time, it only has information after type erasure and it could be a call
// on any arbitrary trait object. Normalize them to a synthesized Drop trait object, both on
// declaration/definition, and during code generation at call sites so they have the same
// type id and match.
//
// FIXME(rcvalle): This allows a drop call on any trait object to call the drop function of
// any other type.
//
let def_id = tcx
.lang_items()
.drop_trait()
.unwrap_or_else(|| bug!("typeid_for_instance: couldn't get drop_trait lang item"));
let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef {
def_id: def_id,
args: List::empty(),
});
let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]);
let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn);
instance.args = tcx.mk_args_trait(self_ty, List::empty());
} else if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
instance.args = strip_receiver_auto(tcx, instance.args);
}

if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
Expand Down
26 changes: 14 additions & 12 deletions library/core/src/num/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ use super::{IntErrorKind, ParseIntError};
///
/// # Safety
///
/// Types implementing this trait must be primitves that are valid when zeroed.
/// Types implementing this trait must be primitives that are valid when zeroed.
///
/// The associated `Self::NonZeroInner` type must have the same size+align as `Self`,
/// but with a niche and bit validity making it so the following `transmutes` are sound:
///
/// - `Self::NonZeroInner` to `Option<Self::NonZeroInner>`
/// - `Option<Self::NonZeroInner>` to `Self`
///
/// (And, consequently, `Self::NonZeroInner` to `Self`.)
#[unstable(
feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time",
Expand Down Expand Up @@ -434,17 +442,11 @@ where
// of some not-inlined function, LLVM don't have range metadata
// to understand that the value cannot be zero.
//
// SAFETY: `Self` is guaranteed to have the same layout as `Option<Self>`.
match unsafe { intrinsics::transmute_unchecked(self) } {
None => {
// SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
unsafe { intrinsics::unreachable() }
}
Some(Self(inner)) => {
// SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
unsafe { intrinsics::transmute_unchecked(inner) }
}
}
// For now, using the transmute `assume`s the range at runtime.
//
// SAFETY: `ZeroablePrimitive` guarantees that the size and bit validity
// of `.0` is such that this transmute is sound.
unsafe { intrinsics::transmute_unchecked(self) }
}
}

Expand Down
2 changes: 1 addition & 1 deletion library/core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@
//!
//! As a consequence, the struct *must not* be [`#[repr(packed)]`][packed].
//!
//! 3. *Structural Notice of Destruction.* You must uphold the the
//! 3. *Structural Notice of Destruction.* You must uphold the
//! [`Drop` guarantee][drop-guarantee]: once your struct is pinned, the struct's storage cannot
//! be re-used without calling the structurally-pinned fields' destructors, as well.
//!
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ const EMULATE_ATOMIC_BOOL: bool =

/// A boolean type which can be safely shared between threads.
///
/// This type has the same in-memory representation as a [`bool`].
/// This type has the same size, alignment, and bit validity as a [`bool`].
///
/// **Note**: This type is only available on platforms that support atomic
/// loads and stores of `u8`.
Expand Down Expand Up @@ -272,7 +272,7 @@ unsafe impl Sync for AtomicBool {}

/// A raw pointer type which can be safely shared between threads.
///
/// This type has the same in-memory representation as a `*mut T`.
/// This type has the same size and bit validity as a `*mut T`.
///
/// **Note**: This type is only available on platforms that support atomic
/// loads and stores of pointers. Its size depends on the target pointer's size.
Expand Down Expand Up @@ -2121,7 +2121,7 @@ macro_rules! atomic_int {
$int_type:ident $atomic_type:ident) => {
/// An integer type which can be safely shared between threads.
///
/// This type has the same in-memory representation as the underlying
/// This type has the same size and bit validity as the underlying
/// integer type, [`
#[doc = $s_int_type]
/// `].
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ impl File {
/// See the [`OpenOptions::open`] function for more details.
///
/// See also [`std::fs::write()`][self::write] for a simple function to
/// create a file with a given data.
/// create a file with some given data.
///
/// # Examples
///
Expand Down Expand Up @@ -1036,7 +1036,7 @@ impl OpenOptions {
/// [`OpenOptions::append`] access must be used.
///
/// See also [`std::fs::write()`][self::write] for a simple function to
/// create a file with a given data.
/// create a file with some given data.
///
/// # Examples
///
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Verifies that type metadata identifiers for drop functions are emitted correctly.
//
//@ needs-sanitizer-cfi
//@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static

#![crate_type="lib"]

// CHECK-LABEL: define{{.*}}4core3ptr47drop_in_place$LT$dyn$u20$core..marker..Send$GT$
// CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE")

struct EmptyDrop;
// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}

struct NonEmptyDrop;

impl Drop for NonEmptyDrop {
fn drop(&mut self) {}
// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}NonEmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
}

pub fn foo() {
let _ = Box::new(EmptyDrop) as Box<dyn Send>;
let _ = Box::new(NonEmptyDrop) as Box<dyn Send>;
}

// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE"}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b
trait Freeze { }
#[lang="drop_in_place"]
fn drop_in_place_fn<T>() { }
#[lang="drop"]
trait Drop { fn drop(&mut self); }

pub trait Trait1 {
fn foo(&self);
Expand Down
Loading

0 comments on commit d779a7a

Please sign in to comment.