Skip to content
Closed
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub(super) fn take_opaques_and_register_member_constraints<'tcx>(
let opaque_types = infcx
.take_opaque_types()
.into_iter()
.map(|(opaque_type_key, decl)| {
let hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
.map(|(opaque_type_key, hidden_type)| {
let hidden_type = infcx.resolve_vars_if_possible(hidden_type);
register_member_constraints(
typeck,
&mut member_constraints,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,9 @@ fn check_opaque_meets_bounds<'tcx>(
} else {
// Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
for (mut key, mut ty) in infcx.take_opaque_types() {
ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
ty.ty = infcx.resolve_vars_if_possible(ty.ty);
key = infcx.resolve_vars_if_possible(key);
sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
sanity_check_found_hidden_type(tcx, key, ty)?;
}
Ok(())
}
Expand Down Expand Up @@ -1873,7 +1873,7 @@ pub(super) fn check_coroutine_obligations(
// Check that any hidden types found when checking these stalled coroutine obligations
// are valid.
for (key, ty) in infcx.take_opaque_types() {
let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type);
let hidden_type = infcx.resolve_vars_if_possible(ty);
let key = infcx.resolve_vars_if_possible(key);
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,9 +562,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
// types or by using this function at the end of writeback and running it as a
// fixpoint.
let opaque_types = self.fcx.infcx.clone_opaque_types();
for (opaque_type_key, decl) in opaque_types {
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
for (opaque_type_key, hidden_type) in opaque_types {
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);

if !self.fcx.next_trait_solver() {
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,12 @@ impl<'tcx> InferCtxt<'tcx> {
.opaque_type_storage
.opaque_types
.iter()
.map(|(k, v)| (*k, v.hidden_type.ty))
.map(|(k, v)| (*k, v.ty))
.collect()
}

fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.hidden_type.ty)).collect()
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect()
}

/// Given the (canonicalized) result to a canonical query,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
pub fn iter_opaque_types(
&self,
) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> + '_ {
self.opaque_type_storage.opaque_types.iter().map(|(&k, v)| (k, v.hidden_type))
self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
}
}

Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,9 @@ use crate::traits::{self, Obligation, PredicateObligations};

mod table;

pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>;
pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};

/// Information about the opaque types whose values we
/// are inferring in this function (these are the `impl Trait` that
/// appear in the return type).
#[derive(Clone, Debug)]
pub struct OpaqueTypeDecl<'tcx> {
/// The hidden types that have been inferred for this opaque type.
/// There can be multiple, but they are all `lub`ed together at the end
/// to obtain the canonical hidden type.
pub hidden_type: OpaqueHiddenType<'tcx>,
}

impl<'tcx> InferCtxt<'tcx> {
/// This is a backwards compatibility hack to prevent breaking changes from
/// lazy TAIT around RPIT handling.
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_infer/src/infer/opaque_types/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@ use rustc_middle::bug;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
use tracing::instrument;

use super::{OpaqueTypeDecl, OpaqueTypeMap};
use super::OpaqueTypeMap;
use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};

#[derive(Default, Debug, Clone)]
pub(crate) struct OpaqueTypeStorage<'tcx> {
/// Opaque types found in explicit return types and their
/// associated fresh inference variable. Writeback resolves these
/// variables to get the concrete type, which can be used to
/// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
/// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions.
pub opaque_types: OpaqueTypeMap<'tcx>,
}

impl<'tcx> OpaqueTypeStorage<'tcx> {
#[instrument(level = "debug")]
pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
if let Some(idx) = idx {
self.opaque_types.get_mut(&key).unwrap().hidden_type = idx;
pub(crate) fn remove(
&mut self,
key: OpaqueTypeKey<'tcx>,
prev: Option<OpaqueHiddenType<'tcx>>,
) {
if let Some(prev) = prev {
*self.opaque_types.get_mut(&key).unwrap() = prev;
} else {
// FIXME(#120456) - is `swap_remove` correct?
match self.opaque_types.swap_remove(&key) {
Expand Down Expand Up @@ -59,13 +63,12 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
key: OpaqueTypeKey<'tcx>,
hidden_type: OpaqueHiddenType<'tcx>,
) -> Option<Ty<'tcx>> {
if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
if let Some(entry) = self.storage.opaque_types.get_mut(&key) {
let prev = std::mem::replace(entry, hidden_type);
self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
return Some(prev.ty);
}
let decl = OpaqueTypeDecl { hidden_type };
self.storage.opaque_types.insert(key, decl);
self.storage.opaque_types.insert(key, hidden_type);
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
None
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/impl_trait_overcaptures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ declare_lint! {
/// To fix this, remove the `use<'a>`, since the lifetime is already captured
/// since it is in scope.
pub IMPL_TRAIT_REDUNDANT_CAPTURES,
Warn,
Allow,
"redundant precise-capturing `use<...>` syntax on an `impl Trait`",
}

Expand Down
24 changes: 15 additions & 9 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1555,16 +1555,22 @@ pub fn write_allocations<'tcx>(
write!(w, " (vtable: impl {dyn_ty} for {ty})")?
}
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
match tcx.eval_static_initializer(did) {
Ok(alloc) => {
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
write_allocation_track_relocs(w, alloc)?;
write!(w, " (static: {}", tcx.def_path_str(did))?;
if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)
&& tcx.hir().body_const_context(body.source.def_id()).is_some()
{
// Statics may be cyclic and evaluating them too early
// in the MIR pipeline may cause cycle errors even though
// normal compilation is fine.
write!(w, ")")?;
} else {
match tcx.eval_static_initializer(did) {
Ok(alloc) => {
write!(w, ", ")?;
write_allocation_track_relocs(w, alloc)?;
}
Err(_) => write!(w, ", error during initializer evaluation)")?,
}
Err(_) => write!(
w,
" (static: {}, error during initializer evaluation)",
tcx.def_path_str(did)
)?,
}
}
Some(GlobalAlloc::Static(did)) => {
Expand Down
47 changes: 30 additions & 17 deletions library/std/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ macro_rules! rtunwrap {
};
}

fn handle_rt_panic(e: Box<dyn Any + Send>) {
fn handle_rt_panic<T>(e: Box<dyn Any + Send>) -> T {
mem::forget(e);
rtabort!("initialization or cleanup bug");
}
Expand Down Expand Up @@ -157,7 +157,7 @@ fn lang_start_internal(
argc: isize,
argv: *const *const u8,
sigpipe: u8,
) -> Result<isize, !> {
) -> isize {
// Guard against the code called by this function from unwinding outside of the Rust-controlled
// code, which is UB. This is a requirement imposed by a combination of how the
// `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
Expand All @@ -168,19 +168,33 @@ fn lang_start_internal(
// panic is a std implementation bug. A quite likely one too, as there isn't any way to
// prevent std from accidentally introducing a panic to these functions. Another is from
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
// SAFETY: Only called once during runtime initialization.
panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) })
.unwrap_or_else(handle_rt_panic);
let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
.map_err(move |e| {
mem::forget(e);
rtabort!("drop of the panic payload panicked");
//
// We use `catch_unwind` with `handle_rt_panic` instead of `abort_unwind` to make the error in
// case of a panic a bit nicer.
panic::catch_unwind(move || {
// SAFETY: Only called once during runtime initialization.
unsafe { init(argc, argv, sigpipe) };

let ret_code = panic::catch_unwind(main).unwrap_or_else(move |payload| {
// Carefully dispose of the panic payload.
let payload = panic::AssertUnwindSafe(payload);
panic::catch_unwind(move || drop({ payload }.0)).unwrap_or_else(move |e| {
mem::forget(e); // do *not* drop the 2nd payload
rtabort!("drop of the panic payload panicked");
});
// Return error code for panicking programs.
101
});
panic::catch_unwind(cleanup).unwrap_or_else(handle_rt_panic);
// Guard against multiple threads calling `libc::exit` concurrently.
// See the documentation for `unique_thread_exit` for more information.
panic::catch_unwind(crate::sys::exit_guard::unique_thread_exit).unwrap_or_else(handle_rt_panic);
ret_code
let ret_code = ret_code as isize;

cleanup();
// Guard against multiple threads calling `libc::exit` concurrently.
// See the documentation for `unique_thread_exit` for more information.
crate::sys::exit_guard::unique_thread_exit();

ret_code
})
.unwrap_or_else(handle_rt_panic)
}

#[cfg(not(any(test, doctest)))]
Expand All @@ -191,11 +205,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
argv: *const *const u8,
sigpipe: u8,
) -> isize {
let Ok(v) = lang_start_internal(
lang_start_internal(
&move || crate::sys::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
argc,
argv,
sigpipe,
);
v
)
}
6 changes: 3 additions & 3 deletions src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
= note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panic.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC
= note: inside `std::panicking::r#try::do_call::<{closure@std::rt::lang_start_internal::{closure#1}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panicking::r#try::<isize, {closure@std::rt::lang_start_internal::{closure#1}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#1}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC
= note: inside `std::panicking::r#try::do_call::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panicking::r#try::<isize, {closure@std::rt::lang_start_internal::{closure#0}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC
= note: inside `std::rt::lang_start_internal` at RUSTLIB/std/src/rt.rs:LL:CC
= note: inside `std::rt::lang_start::<()>` at RUSTLIB/std/src/rt.rs:LL:CC

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RUSTLIB/core/src/ops/function.rs:LL:CC (std::ops::function::impls::call_once)
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#1})
RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#0})
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
at RUSTLIB/std/src/panicking.rs:LL:CC
7: std::panic::catch_unwind
at RUSTLIB/std/src/panic.rs:LL:CC
8: std::rt::lang_start_internal::{closure#1}
8: std::rt::lang_start_internal::{closure#0}
at RUSTLIB/std/src/rt.rs:LL:CC
9: std::panicking::r#try::do_call
at RUSTLIB/std/src/panicking.rs:LL:CC
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/backtrace/backtrace-std.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
at RUSTLIB/std/src/panicking.rs:LL:CC
11: std::panic::catch_unwind
at RUSTLIB/std/src/panic.rs:LL:CC
12: std::rt::lang_start_internal::{closure#1}
12: std::rt::lang_start_internal::{closure#0}
at RUSTLIB/std/src/rt.rs:LL:CC
13: std::panicking::r#try::do_call
at RUSTLIB/std/src/panicking.rs:LL:CC
Expand Down
19 changes: 19 additions & 0 deletions tests/mir-opt/building/dump_mir_cycle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[derive(Debug)]
pub struct Thing {
pub next: &'static Thing,
}

pub static THING: Thing = Thing { next: &THING };
// CHECK: alloc{{.+}} (static: THING)

const fn thing() -> &'static Thing {
&MUTUALLY_RECURSIVE
}

pub static MUTUALLY_RECURSIVE: Thing = Thing { next: thing() };
// CHECK: alloc{{.+}} (static: MUTUALLY_RECURSIVE)

fn main() {
// Generate optimized MIR for the const fn, too.
thing();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,4 @@ const BAR::promoted[0]: &[&i32; 1] = {
}
}

ALLOC0 (static: Y, size: 4, align: 4) {
2a 00 00 00 │ *...
}
ALLOC0 (static: Y)
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@
bb2 (cleanup): {
resume;
}
- }
-
- ALLOC0 (static: Y, size: 4, align: 4) {
- 2a 00 00 00 │ *...
}
-
- ALLOC0 (static: Y)

10 changes: 5 additions & 5 deletions tests/ui/impl-trait/precise-capturing/redundant.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
//@ edition: 2024
//@ check-pass

#![feature(precise_capturing_in_traits)]
#![deny(impl_trait_redundant_captures)]

fn hello<'a>() -> impl Sized + use<'a> {}
//~^ WARN all possible in-scope parameters are already captured
//~^ ERROR all possible in-scope parameters are already captured

struct Inherent;
impl Inherent {
fn inherent(&self) -> impl Sized + use<'_> {}
//~^ WARN all possible in-scope parameters are already captured
//~^ ERROR all possible in-scope parameters are already captured
}

trait Test<'a> {
fn in_trait() -> impl Sized + use<'a, Self>;
//~^ WARN all possible in-scope parameters are already captured
//~^ ERROR all possible in-scope parameters are already captured
}
impl<'a> Test<'a> for () {
fn in_trait() -> impl Sized + use<'a> {}
//~^ WARN all possible in-scope parameters are already captured
//~^ ERROR all possible in-scope parameters are already captured
}

fn main() {}
Loading
Loading