Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4344,7 +4344,7 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_lint",
"rustc_lint_defs",
"rustc_macros",
"rustc_middle",
"rustc_pattern_analysis",
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_middle/src/query/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,8 @@ use parking_lot::{Condvar, Mutex};
use rustc_span::Span;

use crate::query::plumbing::CycleError;
use crate::query::stack::QueryStackFrame;
use crate::ty::TyCtxt;

/// Represents a span and a query key.
#[derive(Clone, Debug)]
pub struct QueryInfo<'tcx> {
/// The span corresponding to the reason for which this query was required.
pub span: Span,
pub frame: QueryStackFrame<'tcx>,
}

/// A value uniquely identifying an active query job.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct QueryJobId(pub NonZero<u64>);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_hir::def_id::LocalDefId;

pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter};
pub use self::job::{QueryJob, QueryJobId, QueryLatch, QueryWaiter};
pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey};
pub use self::plumbing::{
ActiveKeyStatus, CycleError, EnsureMode, IntoQueryParam, QueryMode, QueryState, TyCtxtAt,
Expand Down
12 changes: 7 additions & 5 deletions compiler/rustc_middle/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
use rustc_errors::Diag;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_span::Span;
use rustc_span::{Span, Spanned};
pub use sealed::IntoQueryParam;

use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
use crate::ich::StableHashingContext;
use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
use crate::query::on_disk_cache::OnDiskCache;
use crate::query::stack::QueryStackFrame;
use crate::query::{QueryCache, QueryInfo, QueryJob};
use crate::query::{QueryCache, QueryJob};
use crate::ty::TyCtxt;

/// For a particular query, keeps track of "active" keys, i.e. keys whose
Expand Down Expand Up @@ -50,11 +50,13 @@ pub enum ActiveKeyStatus<'tcx> {
Poisoned,
}

#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct CycleError<'tcx> {
/// The query and related span that uses the cycle.
pub usage: Option<(Span, QueryStackFrame<'tcx>)>,
pub cycle: Vec<QueryInfo<'tcx>>,
pub usage: Option<Spanned<QueryStackFrame<'tcx>>>,

/// The span here corresponds to the reason for which this query was required.
pub cycle: Vec<Spanned<QueryStackFrame<'tcx>>>,
}

#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_lint = { path = "../rustc_lint" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_pattern_analysis = { path = "../rustc_pattern_analysis" }
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_hir::def::*;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::Level;
use rustc_lint_defs::Level;
use rustc_middle::bug;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::thir::*;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_build/src/thir/pattern/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, pluralize};
use rustc_hir::{BindingMode, ByRef, HirId, Mutability};
use rustc_lint as lint;
use rustc_lint_defs::builtin::RUST_2024_INCOMPATIBLE_PAT;
use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt};
use rustc_span::{Ident, Span};

Expand Down Expand Up @@ -56,7 +56,7 @@ impl<'a> PatMigration<'a> {
err.emit();
} else {
tcx.emit_node_span_lint(
lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
RUST_2024_INCOMPATIBLE_PAT,
pat_id,
spans,
rustc_errors::DiagDecorator(|diag| {
Expand Down
28 changes: 14 additions & 14 deletions compiler/rustc_query_impl/src/from_cycle_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ fn fn_sig<'tcx>(
fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>) -> ! {
let mut item_and_field_ids = Vec::new();
let mut representable_ids = FxHashSet::default();
for info in &cycle_error.cycle {
if info.frame.dep_kind == DepKind::check_representability
&& let Some(field_id) = info.frame.def_id
for frame in &cycle_error.cycle {
if frame.node.dep_kind == DepKind::check_representability
&& let Some(field_id) = frame.node.def_id
&& let Some(field_id) = field_id.as_local()
&& let Some(DefKind::Field) = info.frame.tagged_key.def_kind(tcx)
&& let Some(DefKind::Field) = frame.node.tagged_key.def_kind(tcx)
{
let parent_id = tcx.parent(field_id.to_def_id());
let item_id = match tcx.def_kind(parent_id) {
Expand All @@ -90,8 +90,8 @@ fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>
item_and_field_ids.push((item_id.expect_local(), field_id));
}
}
for info in &cycle_error.cycle {
if let TaggedQueryKey::check_representability_adt_ty(key) = info.frame.tagged_key
for frame in &cycle_error.cycle {
if let TaggedQueryKey::check_representability_adt_ty(key) = frame.node.tagged_key
&& let Some(adt) = key.ty_adt_def()
&& let Some(def_id) = adt.did().as_local()
&& !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
Expand All @@ -109,9 +109,9 @@ fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>) -> &'tcx
search_for_cycle_permutation(
&cycle_error.cycle,
|cycle| {
if let Some(info) = cycle.get(0)
&& info.frame.dep_kind == DepKind::variances_of
&& let Some(def_id) = info.frame.def_id
if let Some(frame) = cycle.get(0)
&& frame.node.dep_kind == DepKind::variances_of
&& let Some(def_id) = frame.node.def_id
{
let n = tcx.generics_of(def_id).own_params.len();
ControlFlow::Break(tcx.arena.alloc_from_iter(iter::repeat_n(ty::Bivariant, n)))
Expand All @@ -121,7 +121,7 @@ fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>) -> &'tcx
},
|| {
span_bug!(
cycle_error.usage.as_ref().unwrap().0,
cycle_error.usage.as_ref().unwrap().span,
"only `variances_of` returns `&[ty::Variance]`"
)
},
Expand Down Expand Up @@ -154,7 +154,7 @@ fn layout_of<'tcx>(
let diag = search_for_cycle_permutation(
&cycle_error.cycle,
|cycle| {
if let TaggedQueryKey::layout_of(key) = cycle[0].frame.tagged_key
if let TaggedQueryKey::layout_of(key) = cycle[0].node.tagged_key
&& let ty::Coroutine(def_id, _) = key.value.kind()
&& let Some(def_id) = def_id.as_local()
&& let def_kind = tcx.def_kind(def_id)
Expand All @@ -178,8 +178,8 @@ fn layout_of<'tcx>(
tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
tcx.def_kind_descr(def_kind, def_id.to_def_id()),
);
for (i, info) in cycle.iter().enumerate() {
let TaggedQueryKey::layout_of(frame_key) = info.frame.tagged_key else {
for (i, frame) in cycle.iter().enumerate() {
let TaggedQueryKey::layout_of(frame_key) = frame.node.tagged_key else {
continue;
};
let &ty::Coroutine(frame_def_id, _) = frame_key.value.kind() else {
Expand All @@ -189,7 +189,7 @@ fn layout_of<'tcx>(
continue;
};
let frame_span =
info.frame.tagged_key.default_span(tcx, cycle[(i + 1) % cycle.len()].span);
frame.node.tagged_key.default_span(tcx, cycle[(i + 1) % cycle.len()].span);
if frame_span.is_dummy() {
continue;
}
Expand Down
33 changes: 16 additions & 17 deletions compiler/rustc_query_impl/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{Diag, DiagCtxtHandle};
use rustc_hir::def::DefKind;
use rustc_middle::query::{
CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackFrame, QueryWaiter,
CycleError, QueryJob, QueryJobId, QueryLatch, QueryStackFrame, QueryWaiter,
};
use rustc_middle::ty::TyCtxt;
use rustc_span::{DUMMY_SP, Span};
use rustc_span::{DUMMY_SP, Span, respan};

use crate::{CollectActiveJobsKind, collect_active_jobs_from_all_queries};

Expand Down Expand Up @@ -64,7 +64,7 @@ pub(crate) fn find_cycle_in_stack<'tcx>(

while let Some(job) = current_job {
let info = &job_map.map[&job];
cycle.push(QueryInfo { span: info.job.span, frame: info.frame.clone() });
cycle.push(respan(info.job.span, info.frame.clone()));

if job == id {
cycle.reverse();
Expand All @@ -77,7 +77,7 @@ pub(crate) fn find_cycle_in_stack<'tcx>(
// Find out why the cycle itself was used
let usage = try {
let parent = info.job.parent?;
(info.job.span, job_map.frame_of(parent).clone())
respan(info.job.span, job_map.frame_of(parent).clone())
};
return CycleError { usage, cycle };
}
Expand Down Expand Up @@ -313,14 +313,14 @@ fn remove_cycle<'tcx>(

let usage = entry_point
.query_waiting_on_cycle
.map(|(span, job)| (span, job_map.frame_of(job).clone()));
.map(|(span, job)| respan(span, job_map.frame_of(job).clone()));

// Create the cycle error
let error = CycleError {
usage,
cycle: stack
.iter()
.map(|&(span, job)| QueryInfo { span, frame: job_map.frame_of(job).clone() })
.map(|&(span, job)| respan(span, job_map.frame_of(job).clone()))
.collect(),
};

Expand Down Expand Up @@ -454,41 +454,40 @@ pub(crate) fn report_cycle<'tcx>(
) -> Diag<'tcx> {
assert!(!stack.is_empty());

let span = stack[0].frame.tagged_key.default_span(tcx, stack[1 % stack.len()].span);
let span = stack[0].node.tagged_key.default_span(tcx, stack[1 % stack.len()].span);

let mut cycle_stack = Vec::new();

use crate::error::StackCount;
let stack_bottom = stack[0].frame.tagged_key.description(tcx);
let stack_bottom = stack[0].node.tagged_key.description(tcx);
let stack_count = if stack.len() == 1 {
StackCount::Single { stack_bottom: stack_bottom.clone() }
} else {
StackCount::Multiple { stack_bottom: stack_bottom.clone() }
};

for i in 1..stack.len() {
let frame = &stack[i].frame;
let span = frame.tagged_key.default_span(tcx, stack[(i + 1) % stack.len()].span);
cycle_stack
.push(crate::error::CycleStack { span, desc: frame.tagged_key.description(tcx) });
let node = &stack[i].node;
let span = node.tagged_key.default_span(tcx, stack[(i + 1) % stack.len()].span);
cycle_stack.push(crate::error::CycleStack { span, desc: node.tagged_key.description(tcx) });
}

let mut cycle_usage = None;
if let Some((span, ref query)) = *usage {
if let Some(usage) = usage {
cycle_usage = Some(crate::error::CycleUsage {
span: query.tagged_key.default_span(tcx, span),
usage: query.tagged_key.description(tcx),
span: usage.node.tagged_key.default_span(tcx, usage.span),
usage: usage.node.tagged_key.description(tcx),
});
}

let alias = if stack
.iter()
.all(|entry| matches!(entry.frame.tagged_key.def_kind(tcx), Some(DefKind::TyAlias)))
.all(|entry| matches!(entry.node.tagged_key.def_kind(tcx), Some(DefKind::TyAlias)))
{
Some(crate::error::Alias::Ty)
} else if stack
.iter()
.all(|entry| entry.frame.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias))
.all(|entry| entry.node.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias))
{
Some(crate::error::Alias::Trait)
} else {
Expand Down
36 changes: 27 additions & 9 deletions library/core/src/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::{fmt, intrinsics, ptr, slice};
///
/// # Initialization invariant
///
/// The compiler, in general, assumes that a variable is properly initialized
/// The compiler, in general, assumes that a variable is [properly initialized or "valid"][validity]
/// according to the requirements of the variable's type. For example, a variable of
/// reference type must be aligned and non-null. This is an invariant that must
/// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a
/// variable of reference type causes instantaneous [undefined behavior][ub],
/// variable of reference type causes instantaneous undefined behavior,
/// no matter whether that reference ever gets used to access memory:
///
/// ```rust,no_run
Expand Down Expand Up @@ -53,6 +53,11 @@ use crate::{fmt, intrinsics, ptr, slice};
/// // The equivalent code with `MaybeUninit<i32>`:
/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
/// ```
///
/// Conversely, sometimes it is okay to not initialize *all* bytes of a `MaybeUninit`
/// before calling `assume_init`. For instance, padding bytes do not have to be initialized.
/// See the field-by-field struct initialization example below for a case of that.
///
/// On top of that, remember that most types have additional invariants beyond merely
/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
/// is considered initialized (under the current implementation; this does not constitute
Expand Down Expand Up @@ -197,7 +202,12 @@ use crate::{fmt, intrinsics, ptr, slice};
/// );
/// ```
/// [`&raw mut`]: https://doc.rust-lang.org/reference/types/pointer.html#r-type.pointer.raw.constructor
/// [ub]: ../../reference/behavior-considered-undefined.html
/// [validity]: ../../reference/behavior-considered-undefined.html#r-undefined.validity
///
/// Note that we have not initialized the padding, but that's fine -- it does not have to be
/// initialized. In fact, even if we had initialized the padding in `uninit`, those bytes would be
/// lost when copying the result: no matter the contents of the padding bytes in `uninit`, they will
/// always be uninitialized in `foo`.
///
/// # Layout
///
Expand Down Expand Up @@ -657,11 +667,18 @@ impl<T> MaybeUninit<T> {
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes immediate undefined
/// behavior. The [type-level documentation][inv] contains more information about
/// this initialization invariant.
/// state, i.e., a state that is considered ["valid" for type `T`][validity]. Calling this when
/// the content is not yet fully initialized causes immediate undefined behavior. The
/// [type-level documentation][inv] contains more information about this initialization
/// invariant.
///
/// It is a common mistake to assume that this function is safe to call on integers because they
/// can hold all bit patterns. It is also a common mistake to think that calling this function
/// is UB if any byte is uninitialized. Both of these assumptions are wrong. If that is
/// surprising to you, please read the [type-level documentation][inv].
///
/// [inv]: #initialization-invariant
/// [validity]: ../../reference/behavior-considered-undefined.html#r-undefined.validity
///
/// On top of that, remember that most types have additional invariants beyond merely
/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
Expand Down Expand Up @@ -689,12 +706,13 @@ impl<T> MaybeUninit<T> {
/// *Incorrect* usage of this method:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::MaybeUninit;
///
/// let x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_init = unsafe { x.assume_init() };
/// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
/// ```
///
/// See the [type-level documentation][#examples] for more examples.
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[rustc_const_stable(feature = "const_maybe_uninit_assume_init_by_value", since = "1.59.0")]
#[inline(always)]
Expand Down
31 changes: 28 additions & 3 deletions library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
//! Basic functions for dealing with memory.
//! Basic functions for dealing with memory, values, and types.
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.
//! The contents of this module can be seen as belonging to a few families:
//!
//! * [`drop`], [`replace`], [`swap`], and [`take`]
//! are safe functions for moving values in particular ways.
//! They are useful in everyday Rust code.
//!
//! * [`size_of`], [`size_of_val`], [`align_of`], [`align_of_val`], and [`offset_of`]
//! give information about the representation of values in memory.
//!
//! * [`discriminant`]
//! allows comparing the variants of [`enum`] values while ignoring their fields.
//!
//! * [`forget`] and [`ManuallyDrop`]
//! prevent destructors from running, which is used in certain kinds of ownership transfer.
//! [`needs_drop`]
//! tells you whether a type’s destructor even does anything.
//!
//! * [`transmute`], [`transmute_copy`], and [`MaybeUninit`]
//! convert and construct values in [`unsafe`] ways.
//!
//! See also the [`alloc`] and [`ptr`] modules for more primitive operations on memory.
//!
// core::alloc exists but doesn’t contain all the items we want to discuss
//! [`alloc`]: ../../std/alloc/index.html
//! [`enum`]: ../../std/keyword.enum.html
//! [`ptr`]: crate::ptr
//! [`unsafe`]: ../../std/keyword.unsafe.html

#![stable(feature = "rust1", since = "1.0.0")]

Expand Down
Loading
Loading