diff --git a/RELEASES.md b/RELEASES.md
index 99733bade32c4..fe557a08a9dc0 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,119 @@
+Version 1.84.0 (2025-01-09)
+==========================
+
+
+
+Language
+--------
+- [Allow `#[deny]` inside `#[forbid]` as a no-op](https://github.com/rust-lang/rust/pull/121560/)
+- [Show a warning when `-Ctarget-feature` is used to toggle features that can lead to unsoundness due to ABI mismatches](https://github.com/rust-lang/rust/pull/129884)
+- [Use the next-generation trait solver in coherence](https://github.com/rust-lang/rust/pull/130654)
+- [Allow coercions to drop the principal of trait objects](https://github.com/rust-lang/rust/pull/131857)
+- [Support `/` as the path separator for `include!()` in all cases on Windows](https://github.com/rust-lang/rust/pull/125205)
+- [Taking a raw ref (`raw (const|mut)`) of a deref of a pointer (`*ptr`) is now safe](https://github.com/rust-lang/rust/pull/129248)
+- [Stabilize s390x inline assembly](https://github.com/rust-lang/rust/pull/131258)
+- [Stabilize Arm64EC inline assembly](https://github.com/rust-lang/rust/pull/131781)
+- [Lint against creating pointers to immediately dropped temporaries](https://github.com/rust-lang/rust/pull/128985)
+- [Execute drop glue when unwinding in an `extern "C"` function](https://github.com/rust-lang/rust/pull/129582)
+
+
+
+Compiler
+--------
+- [Add `--print host-tuple` flag to print the host target tuple and affirm the "target tuple" terminology over "target triple"](https://github.com/rust-lang/rust/pull/125579)
+- [Declaring functions with a calling convention not supported on the current target now triggers a hard error](https://github.com/rust-lang/rust/pull/129935)
+- [Set up indirect access to external data for `loongarch64-unknown-linux-{musl,ohos}`](https://github.com/rust-lang/rust/pull/131583)
+- [Enable XRay instrumentation for LoongArch Linux targets](https://github.com/rust-lang/rust/pull/131818)
+- [Extend the `unexpected_cfgs` lint to also warn in external macros](https://github.com/rust-lang/rust/pull/132577)
+- [Stabilize WebAssembly `multivalue`, `reference-types`, and `tail-call` target features](https://github.com/rust-lang/rust/pull/131080)
+- [Added Tier 2 support for the `wasm32v1-none` target](https://github.com/rust-lang/rust/pull/131487)
+
+
+
+Libraries
+---------
+- [Implement `From<&mut {slice}>` for `Box/Rc/Arc<{slice}>`](https://github.com/rust-lang/rust/pull/129329)
+- [Move `::copysign`, `::abs`, `::signum` to `core`](https://github.com/rust-lang/rust/pull/131304)
+- [Add `LowerExp` and `UpperExp` implementations to `NonZero`](https://github.com/rust-lang/rust/pull/131377)
+- [Implement `FromStr` for `CString` and `TryFrom` for `String`](https://github.com/rust-lang/rust/pull/130608)
+- [`std::os::darwin` has been made public](https://github.com/rust-lang/rust/pull/130635)
+
+
+
+Stabilized APIs
+---------------
+
+- [`Ipv6Addr::is_unique_local`](https://doc.rust-lang.org/stable/core/net/struct.Ipv6Addr.html#method.is_unique_local)
+- [`Ipv6Addr::is_unicast_link_local`](https://doc.rust-lang.org/stable/core/net/struct.Ipv6Addr.html#method.is_unicast_link_local)
+- [`core::ptr::with_exposed_provenance`](https://doc.rust-lang.org/stable/core/ptr/fn.with_exposed_provenance.html)
+- [`core::ptr::with_exposed_provenance_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.with_exposed_provenance_mut.html)
+- [`::addr`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.addr)
+- [`::expose_provenance`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.expose_provenance)
+- [`::with_addr`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.with_addr)
+- [`::map_addr`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.map_addr)
+- [`::isqrt`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.isqrt)
+- [`::checked_isqrt`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.checked_isqrt)
+- [`::isqrt`](https://doc.rust-lang.org/stable/core/primitive.u32.html#method.isqrt)
+- [`NonZero::isqrt`](https://doc.rust-lang.org/stable/core/num/struct.NonZero.html#impl-NonZero%3Cu128%3E/method.isqrt)
+- [`core::ptr::without_provenance`](https://doc.rust-lang.org/stable/core/ptr/fn.without_provenance.html)
+- [`core::ptr::without_provenance_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.without_provenance_mut.html)
+- [`core::ptr::dangling`](https://doc.rust-lang.org/stable/core/ptr/fn.dangling.html)
+- [`core::ptr::dangling_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.dangling_mut.html)
+
+These APIs are now stable in const contexts
+
+- [`AtomicBool::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicBool.html#method.from_ptr)
+- [`AtomicPtr::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicPtr.html#method.from_ptr)
+- [`AtomicU8::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU8.html#method.from_ptr)
+- [`AtomicU16::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU16.html#method.from_ptr)
+- [`AtomicU32::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.from_ptr)
+- [`AtomicU64::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU64.html#method.from_ptr)
+- [`AtomicUsize::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicUsize.html#method.from_ptr)
+- [`AtomicI8::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI8.html#method.from_ptr)
+- [`AtomicI16::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI16.html#method.from_ptr)
+- [`AtomicI32::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI32.html#method.from_ptr)
+- [`AtomicI64::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicI64.html#method.from_ptr)
+- [`AtomicIsize::from_ptr`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicIsize.html#method.from_ptr)
+- [`::is_null`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_null-1)
+- [`::as_ref`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.as_ref-1)
+- [`::as_mut`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.as_mut)
+- [`Pin::new`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.new)
+- [`Pin::new_unchecked`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.new_unchecked)
+- [`Pin::get_ref`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.get_ref)
+- [`Pin::into_ref`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.into_ref)
+- [`Pin::get_mut`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.get_mut)
+- [`Pin::get_unchecked_mut`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.get_unchecked_mut)
+- [`Pin::static_ref`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.static_ref)
+- [`Pin::static_mut`](https://doc.rust-lang.org/stable/core/pin/struct.Pin.html#method.static_mut)
+
+
+
+Cargo
+-----
+- [Stabilize MSRV-aware resolver config](https://github.com/rust-lang/cargo/pull/14639/)
+- [Stabilize resolver v3](https://github.com/rust-lang/cargo/pull/14754/)
+
+
+
+Rustdoc
+-------
+
+- [rustdoc-search: improve type-driven search](https://github.com/rust-lang/rust/pull/127589)
+
+
+
+Compatibility Notes
+-------------------
+- [Enable by default the `LSX` target feature for LoongArch Linux targets](https://github.com/rust-lang/rust/pull/132140)
+- [The unstable `-Zprofile` flag (“gcov-style” coverage instrumentation) has been removed.](https://github.com/rust-lang/rust/pull/131829) This does not affect the stable flags for coverage instrumentation (`-Cinstrument-coverage`) and profile-guided optimization (`-Cprofile-generate`, `-Cprofile-use`), which are unrelated and remain available.
+- Support for the target named `wasm32-wasi` has been removed as the target is now named `wasm32-wasip1`. This completes the [transition](https://github.com/rust-lang/compiler-team/issues/607) [plan](https://github.com/rust-lang/compiler-team/issues/695) for this target following [the introduction of `wasm32-wasip1`](https://github.com/rust-lang/rust/pull/120468) in Rust 1.78. Compiler warnings on [use of `wasm32-wasi`](https://github.com/rust-lang/rust/pull/126662) introduced in Rust 1.81 are now gone as well as the target is removed.
+- [The syntax `&pin (mut|const) T` is now parsed as a type which in theory could affect macro expansion results in some edge cases](https://github.com/rust-lang/rust/pull/130635#issuecomment-2375462821)
+- [Legacy syntax for calling `std::arch` functions is no longer permitted to declare items or bodies (such as closures, inline consts, or async blocks).](https://github.com/rust-lang/rust/pull/130443#issuecomment-2445678945)
+- The `wasm32-unknown-emscripten` target's binary release of the standard library is now [built with the latest emsdk 3.1.68](https://github.com/rust-lang/rust/pull/131533), which fixes an ABI-incompatibility with Emscripten >= 3.1.42. If you are locally using a version of emsdk with an incompatible ABI (e.g. before 3.1.42 or a future one), you should build your code with `-Zbuild-std` to ensure that `std` uses the correct ABI.
+- [Declaring functions with a calling convention not supported on the current target now triggers a hard error](https://github.com/rust-lang/rust/pull/129935)
+- [The next-generation trait solver is now enabled for coherence, fixing multiple soundness issues](https://github.com/rust-lang/rust/pull/130654)
+
Version 1.83.0 (2024-11-28)
==========================
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index e18e91e569f5e..c3d7c217861fb 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -109,7 +109,10 @@ unsafe fn configure_llvm(sess: &Session) {
add("-wasm-enable-eh", false);
}
- if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind {
+ if sess.target.os == "emscripten"
+ && !sess.opts.unstable_opts.emscripten_wasm_eh
+ && sess.panic_strategy() == PanicStrategy::Unwind
+ {
add("-enable-emscripten-cxx-exceptions", false);
}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 2587d6dfdc4b3..e4b3ad198018f 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2451,10 +2451,12 @@ fn add_order_independent_options(
}
if sess.target.os == "emscripten" {
- cmd.cc_arg("-s").cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
- "DISABLE_EXCEPTION_CATCHING=1"
+ cmd.cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
+ "-sDISABLE_EXCEPTION_CATCHING=1"
+ } else if sess.opts.unstable_opts.emscripten_wasm_eh {
+ "-fwasm-exceptions"
} else {
- "DISABLE_EXCEPTION_CATCHING=0"
+ "-sDISABLE_EXCEPTION_CATCHING=0"
});
}
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 77e1fed720dfb..544578b29f107 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -388,7 +388,8 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// exceptions. This means that the VM does the unwinding for
// us
pub fn wants_wasm_eh(sess: &Session) -> bool {
- sess.target.is_like_wasm && sess.target.os != "emscripten"
+ sess.target.is_like_wasm
+ && (sess.target.os != "emscripten" || sess.opts.unstable_opts.emscripten_wasm_eh)
}
/// Returns `true` if this session's target will use SEH-based unwinding.
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 90f382e72268b..0413e5e86348b 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -52,8 +52,8 @@ use rustc_metadata::locator;
use rustc_middle::ty::TyCtxt;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::config::{
- CG_OPTIONS, ErrorOutputType, Input, OutFileName, OutputType, UnstableOptions, Z_OPTIONS,
- nightly_options,
+ CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions,
+ Z_OPTIONS, nightly_options,
};
use rustc_session::getopts::{self, Matches};
use rustc_session::lint::{Lint, LintId};
@@ -1124,14 +1124,6 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
return true;
}
- if cg_flags.iter().any(|x| *x == "no-stack-check") {
- early_dcx.early_warn("the `-Cno-stack-check` flag is deprecated and does nothing");
- }
-
- if cg_flags.iter().any(|x| x.starts_with("inline-threshold")) {
- early_dcx.early_warn("the `-Cinline-threshold` flag is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)");
- }
-
if cg_flags.iter().any(|x| *x == "passes=list") {
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
@@ -1156,18 +1148,16 @@ fn describe_codegen_flags() {
print_flag_list("-C", config::CG_OPTIONS);
}
-fn print_flag_list(
- cmdline_opt: &str,
- flag_list: &[(&'static str, T, &'static str, &'static str)],
-) {
- let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
+fn print_flag_list(cmdline_opt: &str, flag_list: &[OptionDesc]) {
+ let max_len =
+ flag_list.iter().map(|opt_desc| opt_desc.name().chars().count()).max().unwrap_or(0);
- for &(name, _, _, desc) in flag_list {
+ for opt_desc in flag_list {
safe_println!(
" {} {:>width$}=val -- {}",
cmdline_opt,
- name.replace('_', "-"),
- desc,
+ opt_desc.name().replace('_', "-"),
+ opt_desc.desc(),
width = max_len
);
}
@@ -1221,8 +1211,8 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option = match e {
getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
.iter()
- .map(|&(name, ..)| ('C', name))
- .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
+ .map(|opt_desc| ('C', opt_desc.name()))
+ .chain(Z_OPTIONS.iter().map(|opt_desc| ('Z', opt_desc.name())))
.find(|&(_, name)| *opt == name.replace('_', "-"))
.map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
getopts::Fail::ArgumentMissing(ref opt) => {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 00bb4d6557906..5421517046d86 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -37,6 +37,7 @@ const GATED_CFGS: &[GatedCfg] = &[
(sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
// this is consistent with naming of the compiler flag it's for
(sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
+ (sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
];
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d40823d2ed627..8cc4c18c02abf 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -202,6 +202,8 @@ declare_features! (
(internal, allow_internal_unstable, "1.0.0", None),
/// Allows using anonymous lifetimes in argument-position impl-trait.
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
+ /// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
+ (internal, cfg_emscripten_wasm_eh, "CURRENT_RUSTC_VERSION", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Allows writing custom MIR
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 789530d35dd81..f4929aae59901 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -40,13 +40,25 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+ /// FIXME: Move this check out of typeck, since it'll easily cycle when revealing opaques,
+ /// and we shouldn't need to check anything here if the typeck results are tainted.
pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
let tcx = self.tcx;
let dl = &tcx.data_layout;
let span = tcx.hir().span(hir_id);
let normalize = |ty| {
let ty = self.resolve_vars_if_possible(ty);
- self.tcx.normalize_erasing_regions(self.typing_env(self.param_env), ty)
+ if let Ok(ty) =
+ self.tcx.try_normalize_erasing_regions(self.typing_env(self.param_env), ty)
+ {
+ ty
+ } else {
+ Ty::new_error_with_message(
+ tcx,
+ span,
+ "tried to normalize non-wf type in check_transmute",
+ )
+ }
};
let from = normalize(from);
let to = normalize(to);
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0b008fd10b507..b4f1dcfb9cc8a 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::lang_items::LangItem;
@@ -690,6 +690,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
+ // Check if we wrote `Self::Assoc(1)` as if it were a tuple ctor.
+ if let SelfSource::QPath(ty) = source
+ && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
+ && let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res
+ && let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id)
+ && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
+ self.tcx,
+ item_name,
+ ty::AssocKind::Type,
+ impl_def_id,
+ )
+ && let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
+ && adt_def.is_struct()
+ && adt_def.non_enum_variant().ctor_kind() == Some(CtorKind::Fn)
+ {
+ let def_path = tcx.def_path_str(adt_def.did());
+ err.span_suggestion(
+ ty.span.to(item_name.span),
+ format!("to construct a value of type `{}`, use the explicit path", def_path),
+ def_path,
+ Applicability::MachineApplicable,
+ );
+ }
+
err
};
if tcx.sess.source_map().is_multiline(sugg_span) {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 9ad690399140e..53d7c84ac3f8f 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -582,6 +582,7 @@ fn test_codegen_options_tracking_hash() {
untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
untracked!(extra_filename, String::from("extra-filename"));
untracked!(incremental, Some(String::from("abc")));
+ untracked!(inline_threshold, Some(0xf007ba11));
// `link_arg` is omitted because it just forwards to `link_args`.
untracked!(link_args, vec![String::from("abc"), String::from("def")]);
untracked!(link_self_contained, LinkSelfContained::on());
@@ -613,7 +614,6 @@ fn test_codegen_options_tracking_hash() {
tracked!(embed_bitcode, false);
tracked!(force_frame_pointers, FramePointer::Always);
tracked!(force_unwind_tables, Some(true));
- tracked!(inline_threshold, Some(0xf007ba11));
tracked!(instrument_coverage, InstrumentCoverage::Yes);
tracked!(link_dead_code, Some(true));
tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
@@ -782,6 +782,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(dwarf_version, Some(5));
tracked!(embed_source, true);
tracked!(emit_thin_lto, false);
+ tracked!(emscripten_wasm_eh, true);
tracked!(export_executable_symbols, true);
tracked!(fewer_names, Some(true));
tracked!(fixed_x18, true);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 99211c1f92440..db2bb8a7248a6 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -125,6 +125,15 @@ impl<'tcx> ObligationCause<'tcx> {
self
}
+ pub fn derived_host_cause(
+ mut self,
+ parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+ variant: impl FnOnce(DerivedHostCause<'tcx>) -> ObligationCauseCode<'tcx>,
+ ) -> ObligationCause<'tcx> {
+ self.code = variant(DerivedHostCause { parent_host_pred, parent_code: self.code }).into();
+ self
+ }
+
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
match self.code() {
ObligationCauseCode::MatchImpl(cause, _) => cause.to_constraint_category(),
@@ -278,6 +287,14 @@ pub enum ObligationCauseCode<'tcx> {
/// Derived obligation for WF goals.
WellFormedDerived(DerivedCause<'tcx>),
+ /// Derived obligation (i.e. `where` clause) on an user-provided impl
+ /// or a trait alias.
+ ImplDerivedHost(Box>),
+
+ /// Derived obligation (i.e. `where` clause) on an user-provided impl
+ /// or a trait alias.
+ BuiltinDerivedHost(DerivedHostCause<'tcx>),
+
/// Derived obligation refined to point at a specific argument in
/// a call or method expression.
FunctionArg {
@@ -437,36 +454,38 @@ pub enum WellFormedLoc {
},
}
-#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-#[derive(TypeVisitable, TypeFoldable)]
-pub struct ImplDerivedCause<'tcx> {
- pub derived: DerivedCause<'tcx>,
- /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
- /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
- /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
- /// that exceptional case where appropriate.
- pub impl_or_alias_def_id: DefId,
- /// The index of the derived predicate in the parent impl's predicates.
- pub impl_def_predicate_index: Option,
- pub span: Span,
-}
-
impl<'tcx> ObligationCauseCode<'tcx> {
/// Returns the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self {
let mut base_cause = self;
- while let Some((parent_code, _)) = base_cause.parent() {
+ while let Some(parent_code) = base_cause.parent() {
base_cause = parent_code;
}
base_cause
}
+ pub fn parent(&self) -> Option<&Self> {
+ match self {
+ ObligationCauseCode::FunctionArg { parent_code, .. } => Some(parent_code),
+ ObligationCauseCode::BuiltinDerived(derived)
+ | ObligationCauseCode::WellFormedDerived(derived)
+ | ObligationCauseCode::ImplDerived(box ImplDerivedCause { derived, .. }) => {
+ Some(&derived.parent_code)
+ }
+ ObligationCauseCode::BuiltinDerivedHost(derived)
+ | ObligationCauseCode::ImplDerivedHost(box ImplDerivedHostCause { derived, .. }) => {
+ Some(&derived.parent_code)
+ }
+ _ => None,
+ }
+ }
+
/// Returns the base obligation and the base trait predicate, if any, ignoring
/// derived obligations.
pub fn peel_derives_with_predicate(&self) -> (&Self, Option>) {
let mut base_cause = self;
let mut base_trait_pred = None;
- while let Some((parent_code, parent_pred)) = base_cause.parent() {
+ while let Some((parent_code, parent_pred)) = base_cause.parent_with_predicate() {
base_cause = parent_code;
if let Some(parent_pred) = parent_pred {
base_trait_pred = Some(parent_pred);
@@ -476,7 +495,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
(base_cause, base_trait_pred)
}
- pub fn parent(&self) -> Option<(&Self, Option>)> {
+ pub fn parent_with_predicate(&self) -> Option<(&Self, Option>)> {
match self {
ObligationCauseCode::FunctionArg { parent_code, .. } => Some((parent_code, None)),
ObligationCauseCode::BuiltinDerived(derived)
@@ -573,6 +592,42 @@ pub struct DerivedCause<'tcx> {
pub parent_code: InternedObligationCauseCode<'tcx>,
}
+#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct ImplDerivedCause<'tcx> {
+ pub derived: DerivedCause<'tcx>,
+ /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+ /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
+ /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
+ /// that exceptional case where appropriate.
+ pub impl_or_alias_def_id: DefId,
+ /// The index of the derived predicate in the parent impl's predicates.
+ pub impl_def_predicate_index: Option,
+ pub span: Span,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct DerivedHostCause<'tcx> {
+ /// The trait predicate of the parent obligation that led to the
+ /// current obligation. Note that only trait obligations lead to
+ /// derived obligations, so we just store the trait predicate here
+ /// directly.
+ pub parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+
+ /// The parent trait had this cause.
+ pub parent_code: InternedObligationCauseCode<'tcx>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct ImplDerivedHostCause<'tcx> {
+ pub derived: DerivedHostCause<'tcx>,
+ /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+ pub impl_def_id: DefId,
+ pub span: Span,
+}
+
#[derive(Clone, Debug, PartialEq, Eq, TypeVisitable)]
pub enum SelectionError<'tcx> {
/// The trait is not implemented.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5e929fbec0bf8..2d69386176b80 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `arg` is
/// typically obtained via the second field of [`TyKind::Adt`].
- pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
- tcx.type_of(self.did).instantiate(tcx, arg)
+ pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+ tcx.type_of(self.did).instantiate(tcx, args)
}
/// Computes the `Ident` of this variant by looking up the `Span`
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 3ecaa3e22d39c..32d6455e82557 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -634,6 +634,28 @@ impl<'tcx> UpcastFrom, PolyProjectionPredicate<'tcx>> for Clause<'t
}
}
+impl<'tcx> UpcastFrom, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
+ for Predicate<'tcx>
+{
+ fn upcast_from(
+ from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+ tcx: TyCtxt<'tcx>,
+ ) -> Self {
+ from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
+ }
+}
+
+impl<'tcx> UpcastFrom, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
+ for Clause<'tcx>
+{
+ fn upcast_from(
+ from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+ tcx: TyCtxt<'tcx>,
+ ) -> Self {
+ from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
+ }
+}
+
impl<'tcx> UpcastFrom, NormalizesTo<'tcx>> for Predicate<'tcx> {
fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
PredicateKind::NormalizesTo(from).upcast(tcx)
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 7da4f5e010754..3c5d9b95e772d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable(
}
}
+// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
+// the old solver, for as long as that exists.
pub(in crate::solve) fn const_conditions_for_destruct(
cx: I,
self_ty: I::Ty,
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index ce7552e30f0fe..7669a305d58d1 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -103,7 +103,7 @@ where
|ecx| {
// Const conditions must hold for the implied const bound to hold.
ecx.add_goals(
- GoalSource::Misc,
+ GoalSource::AliasBoundConstCondition,
cx.const_conditions(alias_ty.def_id)
.iter_instantiated(cx, alias_ty.args)
.map(|trait_ref| {
@@ -353,7 +353,7 @@ where
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
ecx.add_goals(
- GoalSource::Misc,
+ GoalSource::AliasBoundConstCondition,
const_conditions.into_iter().map(|trait_ref| {
goal.with(
cx,
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 020128f29c59b..701f500e4f60b 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -26,7 +26,10 @@ pub(crate) fn check_crate(
if items.eh_personality().is_none() {
items.missing.push(LangItem::EhPersonality);
}
- if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() {
+ if tcx.sess.target.os == "emscripten"
+ && items.eh_catch_typeinfo().is_none()
+ && !tcx.sess.opts.unstable_opts.emscripten_wasm_eh
+ {
items.missing.push(LangItem::EhCatchTypeinfo);
}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 5c36c98649020..683993095c51b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2678,7 +2678,14 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result CrateType::Cdylib,
"bin" => CrateType::Executable,
"proc-macro" => CrateType::ProcMacro,
- _ => return Err(format!("unknown crate type: `{part}`")),
+ _ => {
+ return Err(format!(
+ "unknown crate type: `{part}`, expected one of: {display}",
+ display =
+ ["lib", "rlib", "staticlib", "dylib", "cdylib", "bin", "proc-macro"]
+ .join(", ")
+ ));
+ }
};
if !crate_types.contains(&new_part) {
crate_types.push(new_part)
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index b68dfeffa3451..d586f913335e0 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -143,6 +143,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
| (sym::target_has_atomic_load_store, Some(_))
| (sym::target_thread_local, None) => disallow(cfg, "--target"),
(sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
+ (sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),
_ => {}
}
}
@@ -295,6 +296,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
ins_none!(sym::ub_checks);
}
+ // Nightly-only implementation detail for the `panic_unwind` and `unwind` crates.
+ if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh {
+ ins_none!(sym::emscripten_wasm_eh);
+ }
ret
}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 3772a4a08af01..c1fba4c513da5 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -239,7 +239,8 @@ macro_rules! options {
$init:expr,
$parse:ident,
[$dep_tracking_marker:ident],
- $desc:expr)
+ $desc:expr
+ $(, deprecated_do_nothing: $dnn:literal )?)
),* ,) =>
(
#[derive(Clone)]
@@ -280,7 +281,8 @@ macro_rules! options {
}
pub const $stat: OptionDescrs<$struct_name> =
- &[ $( (stringify!($opt), $optmod::$opt, desc::$parse, $desc) ),* ];
+ &[ $( OptionDesc{ name: stringify!($opt), setter: $optmod::$opt,
+ type_desc: desc::$parse, desc: $desc, is_deprecated_and_do_nothing: false $( || $dnn )? } ),* ];
mod $optmod {
$(
@@ -315,7 +317,27 @@ macro_rules! redirect_field {
}
type OptionSetter = fn(&mut O, v: Option<&str>) -> bool;
-type OptionDescrs = &'static [(&'static str, OptionSetter, &'static str, &'static str)];
+type OptionDescrs = &'static [OptionDesc];
+
+pub struct OptionDesc {
+ name: &'static str,
+ setter: OptionSetter,
+ // description for return value/type from mod desc
+ type_desc: &'static str,
+ // description for option from options table
+ desc: &'static str,
+ is_deprecated_and_do_nothing: bool,
+}
+
+impl OptionDesc {
+ pub fn name(&self) -> &'static str {
+ self.name
+ }
+
+ pub fn desc(&self) -> &'static str {
+ self.desc
+ }
+}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn build_options(
@@ -333,8 +355,13 @@ fn build_options(
};
let option_to_lookup = key.replace('-', "_");
- match descrs.iter().find(|(name, ..)| *name == option_to_lookup) {
- Some((_, setter, type_desc, _)) => {
+ match descrs.iter().find(|opt_desc| opt_desc.name == option_to_lookup) {
+ Some(OptionDesc { name: _, setter, type_desc, desc, is_deprecated_and_do_nothing }) => {
+ if *is_deprecated_and_do_nothing {
+ // deprecation works for prefixed options only
+ assert!(!prefix.is_empty());
+ early_dcx.early_warn(format!("`-{prefix} {key}`: {desc}"));
+ }
if !setter(&mut op, value) {
match value {
None => early_dcx.early_fatal(
@@ -1546,7 +1573,8 @@ options! {
// tidy-alphabetical-start
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
ar: String = (String::new(), parse_string, [UNTRACKED],
- "this option is deprecated and does nothing"),
+ "this option is deprecated and does nothing",
+ deprecated_do_nothing: true),
#[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")]
code_model: Option = (None, parse_code_model, [TRACKED],
"choose the code model to use (`rustc --print code-models` for details)"),
@@ -1578,9 +1606,10 @@ options! {
incremental: Option = (None, parse_opt_string, [UNTRACKED],
"enable incremental compilation"),
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
- inline_threshold: Option = (None, parse_opt_number, [TRACKED],
+ inline_threshold: Option = (None, parse_opt_number, [UNTRACKED],
"this option is deprecated and does nothing \
- (consider using `-Cllvm-args=--inline-threshold=...`)"),
+ (consider using `-Cllvm-args=--inline-threshold=...`)",
+ deprecated_do_nothing: true),
#[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
"instrument the generated code to support LLVM source-based code coverage reports \
@@ -1616,7 +1645,8 @@ options! {
"disable the use of the redzone"),
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
no_stack_check: bool = (false, parse_no_value, [UNTRACKED],
- "this option is deprecated and does nothing"),
+ "this option is deprecated and does nothing",
+ deprecated_do_nothing: true),
no_vectorize_loops: bool = (false, parse_no_value, [TRACKED],
"disable loop vectorization optimization passes"),
no_vectorize_slp: bool = (false, parse_no_value, [TRACKED],
@@ -1771,6 +1801,8 @@ options! {
"emit a section containing stack size metadata (default: no)"),
emit_thin_lto: bool = (true, parse_bool, [TRACKED],
"emit the bc module with thin LTO info (default: yes)"),
+ emscripten_wasm_eh: bool = (false, parse_bool, [TRACKED],
+ "Use WebAssembly error handling for wasm32-unknown-emscripten"),
enforce_type_length_limit: bool = (false, parse_bool, [TRACKED],
"enforce the type length limit when monomorphizing instances in codegen"),
export_executable_symbols: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index bdfbfb1e38dd3..0dcf38e349365 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -570,6 +570,7 @@ symbols! {
cfg_autodiff_fallback,
cfg_boolean_literals,
cfg_doctest,
+ cfg_emscripten_wasm_eh,
cfg_eval,
cfg_fmt_debug,
cfg_hide,
@@ -823,6 +824,7 @@ symbols! {
emit_enum_variant_arg,
emit_struct,
emit_struct_field,
+ emscripten_wasm_eh,
enable,
encode,
end,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 14639039ae946..7ba87e180d0bc 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -737,7 +737,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
applied_do_not_recommend = true;
}
}
- if let Some((parent_cause, _parent_pred)) = base_cause.parent() {
+ if let Some(parent_cause) = base_cause.parent() {
base_cause = parent_cause.clone();
} else {
break;
@@ -797,7 +797,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind()
&& !found_kind.extends(expected_kind)
{
- if let Some((_, Some(parent))) = obligation.cause.code().parent() {
+ if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() {
// If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
trait_ref = parent.to_poly_trait_ref();
} else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
@@ -945,7 +945,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let Some(typeck) = &self.typeck_results else {
return false;
};
- let Some((ObligationCauseCode::QuestionMark, Some(y))) = obligation.cause.code().parent()
+ let Some((ObligationCauseCode::QuestionMark, Some(y))) =
+ obligation.cause.code().parent_with_predicate()
else {
return false;
};
@@ -1198,7 +1199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut code = obligation.cause.code();
let mut pred = obligation.predicate.as_trait_clause();
- while let Some((next_code, next_pred)) = code.parent() {
+ while let Some((next_code, next_pred)) = code.parent_with_predicate() {
if let Some(pred) = pred {
self.enter_forall(pred, |pred| {
diag.note(format!(
@@ -2114,7 +2115,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut code = obligation.cause.code();
let mut trait_pred = trait_predicate;
let mut peeled = false;
- while let Some((parent_code, parent_trait_pred)) = code.parent() {
+ while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
code = parent_code;
if let Some(parent_trait_pred) = parent_trait_pred {
trait_pred = parent_trait_pred;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 007a220ae697f..9d85ca1dd4dd7 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -464,7 +464,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// Get the root obligation, since the leaf obligation we have may be unhelpful (#87437)
let mut real_trait_pred = trait_pred;
- while let Some((parent_code, parent_trait_pred)) = code.parent() {
+ while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
code = parent_code;
if let Some(parent_trait_pred) = parent_trait_pred {
real_trait_pred = parent_trait_pred;
@@ -1447,7 +1447,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut span = obligation.cause.span;
let mut trait_pred = trait_pred;
let mut code = obligation.cause.code();
- while let Some((c, Some(parent_trait_pred))) = code.parent() {
+ while let Some((c, Some(parent_trait_pred))) = code.parent_with_predicate() {
// We want the root obligation, in order to detect properly handle
// `for _ in &mut &mut vec![] {}`.
code = c;
@@ -3470,6 +3470,59 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
)
});
}
+ ObligationCauseCode::ImplDerivedHost(ref data) => {
+ let self_ty =
+ self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty());
+ let msg = format!(
+ "required for `{self_ty}` to implement `{} {}`",
+ data.derived.parent_host_pred.skip_binder().constness,
+ data.derived
+ .parent_host_pred
+ .map_bound(|pred| pred.trait_ref)
+ .print_only_trait_path(),
+ );
+ match tcx.hir().get_if_local(data.impl_def_id) {
+ Some(Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+ ..
+ })) => {
+ let mut spans = vec![self_ty.span];
+ spans.extend(of_trait.as_ref().map(|t| t.path.span));
+ let mut spans: MultiSpan = spans.into();
+ spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
+ err.span_note(spans, msg);
+ }
+ _ => {
+ err.note(msg);
+ }
+ }
+ ensure_sufficient_stack(|| {
+ self.note_obligation_cause_code(
+ body_id,
+ err,
+ data.derived.parent_host_pred,
+ param_env,
+ &data.derived.parent_code,
+ obligated_types,
+ seen_requirements,
+ long_ty_file,
+ )
+ });
+ }
+ ObligationCauseCode::BuiltinDerivedHost(ref data) => {
+ ensure_sufficient_stack(|| {
+ self.note_obligation_cause_code(
+ body_id,
+ err,
+ data.parent_host_pred,
+ param_env,
+ &data.parent_code,
+ obligated_types,
+ seen_requirements,
+ long_ty_file,
+ )
+ });
+ }
ObligationCauseCode::WellFormedDerived(ref data) => {
let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
let parent_predicate = parent_trait_ref;
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index c79a8abca2049..7db0f2bb5a7cc 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -430,6 +430,7 @@ impl<'tcx> BestObligation<'tcx> {
matches!(
nested_goal.source(),
GoalSource::ImplWhereBound
+ | GoalSource::AliasBoundConstCondition
| GoalSource::InstantiateHigherRanked
| GoalSource::AliasWellFormed
) && match self.consider_ambiguities {
@@ -491,8 +492,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
// for normalizes-to.
let pred_kind = goal.goal().predicate.kind();
let child_mode = match pred_kind.skip_binder() {
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
- ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+ ChildMode::Trait(pred_kind.rebind(pred))
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => {
+ ChildMode::Host(pred_kind.rebind(pred))
}
ty::PredicateKind::NormalizesTo(normalizes_to)
if matches!(
@@ -521,7 +525,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
let obligation;
match (child_mode, nested_goal.source()) {
- (ChildMode::Trait(_), GoalSource::Misc) => {
+ (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => {
continue;
}
(ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
@@ -534,11 +538,25 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
));
impl_where_bound_count += 1;
}
+ (
+ ChildMode::Host(parent_host_pred),
+ GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
+ ) => {
+ obligation = make_obligation(derive_host_cause(
+ tcx,
+ candidate.kind(),
+ self.obligation.cause.clone(),
+ impl_where_bound_count,
+ parent_host_pred,
+ ));
+ impl_where_bound_count += 1;
+ }
// Skip over a higher-ranked predicate.
(_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone();
}
- (ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => {
+ (ChildMode::PassThrough, _)
+ | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
obligation = make_obligation(self.obligation.cause.clone());
}
}
@@ -592,6 +610,10 @@ enum ChildMode<'tcx> {
// and skip all `GoalSource::Misc`, which represent useless obligations
// such as alias-eq which may not hold.
Trait(ty::PolyTraitPredicate<'tcx>),
+ // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
+ // and skip all `GoalSource::Misc`, which represent useless obligations
+ // such as alias-eq which may not hold.
+ Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>),
// Skip trying to derive an `ObligationCause` from this obligation, and
// report *all* sub-obligations as if they came directly from the parent
// obligation.
@@ -633,3 +655,52 @@ fn derive_cause<'tcx>(
};
cause
}
+
+fn derive_host_cause<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ candidate_kind: inspect::ProbeKind>,
+ mut cause: ObligationCause<'tcx>,
+ idx: usize,
+ parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
+) -> ObligationCause<'tcx> {
+ match candidate_kind {
+ inspect::ProbeKind::TraitCandidate {
+ source: CandidateSource::Impl(impl_def_id),
+ result: _,
+ } => {
+ if let Some((_, span)) = tcx
+ .predicates_of(impl_def_id)
+ .instantiate_identity(tcx)
+ .into_iter()
+ .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
+ |(trait_ref, span)| {
+ (
+ trait_ref.to_host_effect_clause(
+ tcx,
+ parent_host_pred.skip_binder().constness,
+ ),
+ span,
+ )
+ },
+ ))
+ .nth(idx)
+ {
+ cause =
+ cause.derived_host_cause(parent_host_pred, |derived| {
+ ObligationCauseCode::ImplDerivedHost(Box::new(
+ traits::ImplDerivedHostCause { derived, impl_def_id, span },
+ ))
+ })
+ }
+ }
+ inspect::ProbeKind::TraitCandidate {
+ source: CandidateSource::BuiltinImpl(..),
+ result: _,
+ } => {
+ cause =
+ cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost);
+ }
+ _ => {}
+ };
+ cause
+}
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 91484ef99dbb8..b32909efe0be7 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -1,6 +1,8 @@
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
-use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
+use rustc_infer::traits::{
+ ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
+};
use rustc_middle::span_bug;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, TypingMode};
@@ -46,6 +48,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
Err(EvaluationFailure::NoSolution) => {}
}
+ match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
+ Ok(result) => return Ok(result),
+ Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+ Err(EvaluationFailure::NoSolution) => {}
+ }
+
match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
Ok(result) => return Ok(result),
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -226,6 +234,104 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
}
}
+fn evaluate_host_effect_from_builtin_impls<'tcx>(
+ selcx: &mut SelectionContext<'_, 'tcx>,
+ obligation: &HostEffectObligation<'tcx>,
+) -> Result>, EvaluationFailure> {
+ match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
+ Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
+ _ => Err(EvaluationFailure::NoSolution),
+ }
+}
+
+// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
+fn evaluate_host_effect_for_destruct_goal<'tcx>(
+ selcx: &mut SelectionContext<'_, 'tcx>,
+ obligation: &HostEffectObligation<'tcx>,
+) -> Result>, EvaluationFailure> {
+ let tcx = selcx.tcx();
+ let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None);
+ let self_ty = obligation.predicate.self_ty();
+
+ let const_conditions = match *self_ty.kind() {
+ // An ADT is `~const Destruct` only if all of the fields are,
+ // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`.
+ ty::Adt(adt_def, args) => {
+ let mut const_conditions: ThinVec<_> = adt_def
+ .all_fields()
+ .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
+ .collect();
+ match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
+ // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
+ Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
+ // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
+ Some(hir::Constness::Const) => {
+ let drop_def_id = tcx.require_lang_item(LangItem::Drop, None);
+ let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
+ const_conditions.push(drop_trait_ref);
+ }
+ // No `Drop` impl, no need to require anything else.
+ None => {}
+ }
+ const_conditions
+ }
+
+ ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
+ thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
+ }
+
+ ty::Tuple(tys) => {
+ tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
+ }
+
+ // Trivially implement `~const Destruct`
+ ty::Bool
+ | ty::Char
+ | ty::Int(..)
+ | ty::Uint(..)
+ | ty::Float(..)
+ | ty::Str
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(..)
+ | ty::Never
+ | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
+ | ty::Error(_) => thin_vec![],
+
+ // Coroutines and closures could implement `~const Drop`,
+ // but they don't really need to right now.
+ ty::Closure(_, _)
+ | ty::CoroutineClosure(_, _)
+ | ty::Coroutine(_, _)
+ | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
+
+ // FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
+ // if their inner type implements it.
+ ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
+
+ ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
+ return Err(EvaluationFailure::NoSolution);
+ }
+
+ ty::Bound(..)
+ | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ panic!("unexpected type `{self_ty:?}`")
+ }
+ };
+
+ Ok(const_conditions
+ .into_iter()
+ .map(|trait_ref| {
+ obligation.with(
+ tcx,
+ ty::Binder::dummy(trait_ref)
+ .to_host_effect_clause(tcx, obligation.predicate.constness),
+ )
+ })
+ .collect())
+}
+
fn evaluate_host_effect_from_selection_candiate<'tcx>(
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &HostEffectObligation<'tcx>,
@@ -248,9 +354,22 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
tcx.const_conditions(impl_.impl_def_id)
.instantiate(tcx, impl_.args)
.into_iter()
- .map(|(trait_ref, _)| {
- obligation.with(
+ .map(|(trait_ref, span)| {
+ Obligation::new(
tcx,
+ obligation.cause.clone().derived_host_cause(
+ ty::Binder::dummy(obligation.predicate),
+ |derived| {
+ ObligationCauseCode::ImplDerivedHost(Box::new(
+ ImplDerivedHostCause {
+ derived,
+ impl_def_id: impl_.impl_def_id,
+ span,
+ },
+ ))
+ },
+ ),
+ obligation.param_env,
trait_ref
.to_host_effect_clause(tcx, obligation.predicate.constness),
)
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 47447af22158d..cb59bc608c203 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -89,6 +89,7 @@ impl_binder_encode_decode! {
ty::ExistentialPredicate,
ty::TraitRef,
ty::ExistentialTraitRef,
+ ty::HostEffectPredicate,
}
impl Binder
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 8fe512026e5d9..1ae904d50e066 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -68,6 +68,10 @@ pub enum GoalSource {
/// FIXME(-Znext-solver=coinductive): Explain how and why this
/// changes whether cycles are coinductive.
ImplWhereBound,
+ /// Const conditions that need to hold for `~const` alias bounds to hold.
+ ///
+ /// FIXME(-Znext-solver=coinductive): Are these even coinductive?
+ AliasBoundConstCondition,
/// Instantiating a higher-ranked goal and re-proving it.
InstantiateHigherRanked,
/// Predicate required for an alias projection to be well-formed.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index c2c78dd9c67eb..a033b8bd30514 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -596,7 +596,7 @@ impl<'a> Arguments<'a> {
/// When using the format_args!() macro, this function is used to generate the
/// Arguments structure.
#[inline]
- pub fn new_v1(
+ pub const fn new_v1(
pieces: &'a [&'static str; P],
args: &'a [rt::Argument<'a>; A],
) -> Arguments<'a> {
@@ -612,7 +612,7 @@ impl<'a> Arguments<'a> {
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
#[inline]
- pub fn new_v1_formatted(
+ pub const fn new_v1_formatted(
pieces: &'a [&'static str],
args: &'a [rt::Argument<'a>],
fmt: &'a [rt::Placeholder],
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 94341a4da66cd..85d089a079082 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -96,12 +96,12 @@ pub struct Argument<'a> {
#[rustc_diagnostic_item = "ArgumentMethods"]
impl Argument<'_> {
#[inline]
- fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
+ const fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
Argument {
// INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
// a `fn(&T, ...)`, so the invariant is maintained.
ty: ArgumentType::Placeholder {
- value: NonNull::from(x).cast(),
+ value: NonNull::from_ref(x).cast(),
// SAFETY: function pointers always have the same layout.
formatter: unsafe { mem::transmute(f) },
_lifetime: PhantomData,
@@ -150,7 +150,7 @@ impl Argument<'_> {
Self::new(x, UpperExp::fmt)
}
#[inline]
- pub fn from_usize(x: &usize) -> Argument<'_> {
+ pub const fn from_usize(x: &usize) -> Argument<'_> {
Argument { ty: ArgumentType::Count(*x) }
}
@@ -181,7 +181,7 @@ impl Argument<'_> {
}
#[inline]
- pub(super) fn as_usize(&self) -> Option {
+ pub(super) const fn as_usize(&self) -> Option {
match self.ty {
ArgumentType::Count(count) => Some(count),
ArgumentType::Placeholder { .. } => None,
@@ -199,7 +199,7 @@ impl Argument<'_> {
/// println!("{f}");
/// ```
#[inline]
- pub fn none() -> [Self; 0] {
+ pub const fn none() -> [Self; 0] {
[]
}
}
@@ -216,7 +216,7 @@ impl UnsafeArg {
/// See documentation where `UnsafeArg` is required to know when it is safe to
/// create and use `UnsafeArg`.
#[inline]
- pub unsafe fn new() -> Self {
+ pub const unsafe fn new() -> Self {
Self { _private: () }
}
}
diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml
index 252f118fecfbb..c2abb79192e9f 100644
--- a/library/panic_unwind/Cargo.toml
+++ b/library/panic_unwind/Cargo.toml
@@ -23,4 +23,4 @@ libc = { version = "0.2", default-features = false }
[lints.rust.unexpected_cfgs]
level = "warn"
-check-cfg = []
+check-cfg = ['cfg(emscripten_wasm_eh)']
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 8c28bb5c5b033..dc78be76cb4d5 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -25,13 +25,14 @@
// `real_imp` is unused with Miri, so silence warnings.
#![cfg_attr(miri, allow(dead_code))]
#![allow(internal_features)]
+#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
use alloc::boxed::Box;
use core::any::Any;
use core::panic::PanicPayload;
cfg_if::cfg_if! {
- if #[cfg(target_os = "emscripten")] {
+ if #[cfg(all(target_os = "emscripten", not(emscripten_wasm_eh)))] {
#[path = "emcc.rs"]
mod imp;
} else if #[cfg(target_os = "hermit")] {
diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml
index e13c9a06c05d1..66e8d1a3ffe5f 100644
--- a/library/unwind/Cargo.toml
+++ b/library/unwind/Cargo.toml
@@ -37,4 +37,4 @@ system-llvm-libunwind = []
[lints.rust.unexpected_cfgs]
level = "warn"
-check-cfg = []
+check-cfg = ['cfg(emscripten_wasm_eh)']
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 7af1882ab73a9..e4ba2bc1ed874 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -4,10 +4,11 @@
#![feature(staged_api)]
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
#![cfg_attr(
- all(target_family = "wasm", not(target_os = "emscripten")),
+ all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)),
feature(simd_wasm64, wasm_exception_handling_intrinsics)
)]
#![allow(internal_features)]
+#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
// Force libc to be included even if unused. This is required by many platforms.
#[cfg(not(all(windows, target_env = "msvc")))]
diff --git a/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md
new file mode 100644
index 0000000000000..eab29a1744b67
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md
@@ -0,0 +1,6 @@
+# `emscripten-wasm-eh`
+
+Use the WebAssembly exception handling ABI to unwind for the
+`wasm32-unknown-emscripten`. If compiling with this setting, the `emcc` linker
+should be invoked with `-fwasm-exceptions`. If linking with C/C++ files, the
+C/C++ files should also be compiled with `-fwasm-exceptions`.
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index af39d15f67175..881df8b005017 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -357,7 +357,7 @@ fn sidebar_type_alias<'a>(
deref_id_map: &'a DefIdMap,
) {
if let Some(inner_type) = &t.inner_type {
- items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type"));
+ items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased Type"), "type"));
match inner_type {
clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive: _ } => {
let mut variants = variants
diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emscripten-catch-unwind-js-eh.rs
similarity index 100%
rename from tests/codegen/emcripten-catch-unwind.rs
rename to tests/codegen/emscripten-catch-unwind-js-eh.rs
diff --git a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs
new file mode 100644
index 0000000000000..72395f432d5f8
--- /dev/null
+++ b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs
@@ -0,0 +1,65 @@
+//@ compile-flags: -O --target wasm32-unknown-emscripten -Z emscripten-wasm-eh
+//@ needs-llvm-components: webassembly
+
+// Emscripten catch_unwind using wasm exceptions
+
+#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "freeze"]
+trait Freeze {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for *mut T {}
+
+#[rustc_intrinsic]
+fn size_of() -> usize {
+ loop {}
+}
+
+extern "rust-intrinsic" {
+ fn catch_unwind(
+ try_fn: fn(_: *mut u8),
+ data: *mut u8,
+ catch_fn: fn(_: *mut u8, _: *mut u8),
+ ) -> i32;
+}
+
+// CHECK-LABEL: @ptr_size
+#[no_mangle]
+pub fn ptr_size() -> usize {
+ // CHECK: ret [[PTR_SIZE:.*]]
+ size_of::<*mut u8>()
+}
+
+// CHECK-LABEL: @test_catch_unwind
+#[no_mangle]
+pub unsafe fn test_catch_unwind(
+ try_fn: fn(_: *mut u8),
+ data: *mut u8,
+ catch_fn: fn(_: *mut u8, _: *mut u8),
+) -> i32 {
+ // CHECK: start:
+ // CHECK: invoke void %try_fn(ptr %data)
+ // CHECK: to label %__rust_try.exit unwind label %catchswitch.i
+ // CHECK: catchswitch.i: ; preds = %start
+ // CHECK: %catchswitch1.i = catchswitch within none [label %catchpad.i] unwind to caller
+
+ // CHECK: catchpad.i: ; preds = %catchswitch.i
+ // CHECK: %catchpad2.i = catchpad within %catchswitch1.i [ptr null]
+ // CHECK: %0 = tail call ptr @llvm.wasm.get.exception(token %catchpad2.i)
+ // CHECK: %1 = tail call i32 @llvm.wasm.get.ehselector(token %catchpad2.i)
+ // CHECK: call void %catch_fn(ptr %data, ptr %0) [ "funclet"(token %catchpad2.i) ]
+ // CHECK: catchret from %catchpad2.i to label %__rust_try.exit
+
+ // CHECK: __rust_try.exit: ; preds = %start, %catchpad.i
+ // CHECK: %common.ret.op.i = phi i32 [ 0, %start ], [ 1, %catchpad.i ]
+ // CHECK: ret i32 %common.ret.op.i
+
+ catch_unwind(try_fn, data, catch_fn)
+}
diff --git a/tests/rustdoc/type-alias/deref-32077.rs b/tests/rustdoc/type-alias/deref-32077.rs
index 79a833813406e..faab4b6f522ba 100644
--- a/tests/rustdoc/type-alias/deref-32077.rs
+++ b/tests/rustdoc/type-alias/deref-32077.rs
@@ -19,8 +19,8 @@ impl Foo for GenericStruct {}
impl Bar for GenericStruct {}
//@ has 'foo/type.TypedefStruct.html'
-// We check that "Aliased type" is also present as a title in the sidebar.
-//@ has - '//*[@class="sidebar-elems"]//h3/a[@href="#aliased-type"]' 'Aliased type'
+// We check that "Aliased Type" is also present as a title in the sidebar.
+//@ has - '//*[@class="sidebar-elems"]//h3/a[@href="#aliased-type"]' 'Aliased Type'
// We check that we have the implementation of the type alias itself.
//@ has - '//*[@id="impl-GenericStruct%3Cu8%3E"]/h3' 'impl TypedefStruct'
//@ has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()'
diff --git a/tests/ui/associated-types/invalid-ctor.fixed b/tests/ui/associated-types/invalid-ctor.fixed
new file mode 100644
index 0000000000000..eba3820de0c1c
--- /dev/null
+++ b/tests/ui/associated-types/invalid-ctor.fixed
@@ -0,0 +1,22 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+struct Constructor(i32);
+
+trait Trait {
+ type Out;
+
+ fn mk() -> Self::Out;
+}
+
+impl Trait for () {
+ type Out = Constructor;
+
+ fn mk() -> Self::Out {
+ Constructor(1)
+ //~^ ERROR no associated item named `Out` found for unit type `()`
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-types/invalid-ctor.rs b/tests/ui/associated-types/invalid-ctor.rs
new file mode 100644
index 0000000000000..73335c065c2ae
--- /dev/null
+++ b/tests/ui/associated-types/invalid-ctor.rs
@@ -0,0 +1,22 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+struct Constructor(i32);
+
+trait Trait {
+ type Out;
+
+ fn mk() -> Self::Out;
+}
+
+impl Trait for () {
+ type Out = Constructor;
+
+ fn mk() -> Self::Out {
+ Self::Out(1)
+ //~^ ERROR no associated item named `Out` found for unit type `()`
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-types/invalid-ctor.stderr b/tests/ui/associated-types/invalid-ctor.stderr
new file mode 100644
index 0000000000000..b545c95a76814
--- /dev/null
+++ b/tests/ui/associated-types/invalid-ctor.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no associated item named `Out` found for unit type `()` in the current scope
+ --> $DIR/invalid-ctor.rs:17:15
+ |
+LL | Self::Out(1)
+ | ^^^ associated item not found in `()`
+ |
+help: to construct a value of type `Constructor`, use the explicit path
+ |
+LL | Constructor(1)
+ | ~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr
new file mode 100644
index 0000000000000..8b2ee0e5c0c3d
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg emscripten_wasm_eh` flag
+ |
+ = note: config `emscripten_wasm_eh` is only supposed to be controlled by `-Z emscripten_wasm_eh`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs
index 3c9ee87f28ab8..cae9c65cb45ac 100644
--- a/tests/ui/cfg/disallowed-cli-cfgs.rs
+++ b/tests/ui/cfg/disallowed-cli-cfgs.rs
@@ -7,6 +7,7 @@
//@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_
//@ revisions: target_thread_local_ relocation_model_
//@ revisions: fmt_debug_
+//@ revisions: emscripten_wasm_eh_
//@ [overflow_checks_]compile-flags: --cfg overflow_checks
//@ [debug_assertions_]compile-flags: --cfg debug_assertions
@@ -33,5 +34,6 @@
//@ [target_thread_local_]compile-flags: --cfg target_thread_local
//@ [relocation_model_]compile-flags: --cfg relocation_model="a"
//@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow"
+//@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh
fn main() {}
diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr
index 370244fe8c984..f219c90849a26 100644
--- a/tests/ui/const-generics/issues/issue-88119.stderr
+++ b/tests/ui/const-generics/issues/issue-88119.stderr
@@ -11,12 +11,30 @@ error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{con
|
LL | impl const ConstName for &T
| ^^ cannot normalize `<&T as ConstName>::{constant#0}`
+ |
+note: required for `&T` to implement `~const ConstName`
+ --> $DIR/issue-88119.rs:19:35
+ |
+LL | impl const ConstName for &T
+ | ^^^^^^^^^ ^^
+LL | where
+LL | [(); name_len::()]:,
+ | --------------------- unsatisfied trait bound introduced here
error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
--> $DIR/issue-88119.rs:26:49
|
LL | impl const ConstName for &mut T
| ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
+ |
+note: required for `&mut T` to implement `~const ConstName`
+ --> $DIR/issue-88119.rs:26:35
+ |
+LL | impl const ConstName for &mut T
+ | ^^^^^^^^^ ^^^^^^
+LL | where
+LL | [(); name_len::()]:,
+ | --------------------- unsatisfied trait bound introduced here
error: aborting due to 3 previous errors
diff --git a/tests/ui/consts/const-eval/format.rs b/tests/ui/consts/const-eval/format.rs
index e56d15e935bc5..1878fc0382767 100644
--- a/tests/ui/consts/const-eval/format.rs
+++ b/tests/ui/consts/const-eval/format.rs
@@ -1,13 +1,11 @@
const fn failure() {
panic!("{:?}", 0);
//~^ ERROR cannot call non-const formatting macro in constant functions
- //~| ERROR cannot call non-const associated function `Arguments::<'_>::new_v1::<1, 1>` in constant functions
}
const fn print() {
println!("{:?}", 0);
//~^ ERROR cannot call non-const formatting macro in constant functions
- //~| ERROR cannot call non-const associated function `Arguments::<'_>::new_v1::<2, 1>` in constant functions
//~| ERROR cannot call non-const function `_print` in constant functions
}
diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr
index 25ed44e0f3382..af90acc2a2605 100644
--- a/tests/ui/consts/const-eval/format.stderr
+++ b/tests/ui/consts/const-eval/format.stderr
@@ -7,17 +7,8 @@ LL | panic!("{:?}", 0);
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0015]: cannot call non-const associated function `Arguments::<'_>::new_v1::<1, 1>` in constant functions
- --> $DIR/format.rs:2:5
- |
-LL | panic!("{:?}", 0);
- | ^^^^^^^^^^^^^^^^^
- |
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
- = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
error[E0015]: cannot call non-const formatting macro in constant functions
- --> $DIR/format.rs:8:15
+ --> $DIR/format.rs:7:15
|
LL | println!("{:?}", 0);
| ^^^^
@@ -25,17 +16,8 @@ LL | println!("{:?}", 0);
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0015]: cannot call non-const associated function `Arguments::<'_>::new_v1::<2, 1>` in constant functions
- --> $DIR/format.rs:8:5
- |
-LL | println!("{:?}", 0);
- | ^^^^^^^^^^^^^^^^^^^
- |
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
- = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
error[E0015]: cannot call non-const function `_print` in constant functions
- --> $DIR/format.rs:8:5
+ --> $DIR/format.rs:7:5
|
LL | println!("{:?}", 0);
| ^^^^^^^^^^^^^^^^^^^
@@ -43,6 +25,6 @@ LL | println!("{:?}", 0);
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index e0dbecff8e587..d688bfbde2bc2 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -155,90 +155,21 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
- --> $DIR/fn_trait_refs.rs:70:32
+error[E0015]: cannot call non-const operator in constants
+ --> $DIR/fn_trait_refs.rs:71:17
|
-LL | let test_one = test_fn(one);
- | ------- ^^^
- | |
- | required by a bound introduced by this call
+LL | assert!(test_one == (1, 1, 1));
+ | ^^^^^^^^^^^^^^^^^^^^^
|
-note: required by a bound in `test_fn`
- --> $DIR/fn_trait_refs.rs:35:24
- |
-LL | const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output)
- | ------- required by a bound in this function
-LL | where
-LL | T: ~const Fn<()> + ~const Destruct,
- | ^^^^^^ required by this bound in `test_fn`
-
-error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
- --> $DIR/fn_trait_refs.rs:73:36
- |
-LL | let test_two = test_fn_mut(two);
- | ----------- ^^^
- | |
- | required by a bound introduced by this call
- |
-note: required by a bound in `test_fn_mut`
- --> $DIR/fn_trait_refs.rs:49:27
- |
-LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output)
- | ----------- required by a bound in this function
-LL | where
-LL | T: ~const FnMut<()> + ~const Destruct,
- | ^^^^^^ required by this bound in `test_fn_mut`
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
- --> $DIR/fn_trait_refs.rs:39:19
- |
-LL | tester_fn(&f),
- | --------- ^^
- | |
- | required by a bound introduced by this call
+error[E0015]: cannot call non-const operator in constants
+ --> $DIR/fn_trait_refs.rs:74:17
|
-note: required by a bound in `tester_fn`
- --> $DIR/fn_trait_refs.rs:14:24
+LL | assert!(test_two == (2, 2));
+ | ^^^^^^^^^^^^^^^^^^
|
-LL | const fn tester_fn(f: T) -> T::Output
- | --------- required by a bound in this function
-LL | where
-LL | T: ~const Fn<()> + ~const Destruct,
- | ^^^^^^ required by this bound in `tester_fn`
-
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
- --> $DIR/fn_trait_refs.rs:41:23
- |
-LL | tester_fn_mut(&f),
- | ------------- ^^
- | |
- | required by a bound introduced by this call
- |
-note: required by a bound in `tester_fn_mut`
- --> $DIR/fn_trait_refs.rs:21:27
- |
-LL | const fn tester_fn_mut(mut f: T) -> T::Output
- | ------------- required by a bound in this function
-LL | where
-LL | T: ~const FnMut<()> + ~const Destruct,
- | ^^^^^^ required by this bound in `tester_fn_mut`
-
-error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
- --> $DIR/fn_trait_refs.rs:53:23
- |
-LL | tester_fn_mut(&mut f),
- | ------------- ^^^^^^
- | |
- | required by a bound introduced by this call
- |
-note: required by a bound in `tester_fn_mut`
- --> $DIR/fn_trait_refs.rs:21:27
- |
-LL | const fn tester_fn_mut(mut f: T) -> T::Output
- | ------------- required by a bound in this function
-LL | where
-LL | T: ~const FnMut<()> + ~const Destruct,
- | ^^^^^^ required by this bound in `tester_fn_mut`
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/fn_trait_refs.rs:16:5
@@ -264,7 +195,7 @@ LL | f()
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-error: aborting due to 25 previous errors
+error: aborting due to 22 previous errors
-Some errors have detailed explanations: E0015, E0277, E0635.
+Some errors have detailed explanations: E0015, E0635.
For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr
index dd70bb601c47d..40c6d083b066f 100644
--- a/tests/ui/consts/promoted_const_call.stderr
+++ b/tests/ui/consts/promoted_const_call.stderr
@@ -5,6 +5,10 @@ LL | let _: &'static _ = &id(&Panic);
| ^^^^^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
+ |
+ = note: see issue #133214 for more information
+ = help: add `#![feature(const_destruct)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0716]: temporary value dropped while borrowed
--> $DIR/promoted_const_call.rs:16:26
diff --git a/tests/ui/crate_type_flag.rs b/tests/ui/crate_type_flag.rs
new file mode 100644
index 0000000000000..bd71c61cb2664
--- /dev/null
+++ b/tests/ui/crate_type_flag.rs
@@ -0,0 +1,4 @@
+//@ compile-flags: --crate-type dynlib
+//@ error-pattern: unknown crate type: `dynlib`, expected one of: lib, rlib, staticlib, dylib, cdylib, bin, proc-macro
+
+fn main() {}
diff --git a/tests/ui/crate_type_flag.stderr b/tests/ui/crate_type_flag.stderr
new file mode 100644
index 0000000000000..fa3065e3ccf60
--- /dev/null
+++ b/tests/ui/crate_type_flag.stderr
@@ -0,0 +1,2 @@
+error: unknown crate type: `dynlib`, expected one of: lib, rlib, staticlib, dylib, cdylib, bin, proc-macro
+
diff --git a/tests/ui/deprecation/deprecated_ar.rs b/tests/ui/deprecation/deprecated_ar.rs
new file mode 100644
index 0000000000000..404d062e6a449
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_ar.rs
@@ -0,0 +1,4 @@
+//@ check-pass
+//@ compile-flags: -Car=foo
+
+fn main() {}
diff --git a/tests/ui/deprecation/deprecated_ar.stderr b/tests/ui/deprecation/deprecated_ar.stderr
new file mode 100644
index 0000000000000..de776c674996a
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_ar.stderr
@@ -0,0 +1,2 @@
+warning: `-C ar`: this option is deprecated and does nothing
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr
new file mode 100644
index 0000000000000..2e7a99010ae9b
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr
@@ -0,0 +1,4 @@
+warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
+
+error: incorrect value `asd` for codegen option `inline-threshold` - a number was expected
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr
new file mode 100644
index 0000000000000..2d6f3652d252e
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr
@@ -0,0 +1,2 @@
+warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr
new file mode 100644
index 0000000000000..25104e637e001
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr
@@ -0,0 +1,4 @@
+warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
+
+error: codegen option `inline-threshold` requires a number (C inline-threshold=)
+
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.rs b/tests/ui/deprecation/deprecated_inline_threshold.rs
index 56e033b8cf547..b54fa36397af0 100644
--- a/tests/ui/deprecation/deprecated_inline_threshold.rs
+++ b/tests/ui/deprecation/deprecated_inline_threshold.rs
@@ -1,4 +1,8 @@
-//@ check-pass
-//@ compile-flags: -Cinline-threshold=666
+//@ revisions: good_val bad_val no_val
+//
+//@[good_val] compile-flags: -Cinline-threshold=666
+//@[good_val] check-pass
+//@[bad_val] compile-flags: -Cinline-threshold=asd
+//@[no_val] compile-flags: -Cinline-threshold
fn main() {}
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.stderr b/tests/ui/deprecation/deprecated_inline_threshold.stderr
deleted file mode 100644
index c4f8ff092b29a..0000000000000
--- a/tests/ui/deprecation/deprecated_inline_threshold.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-warning: the `-Cinline-threshold` flag is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)
-
diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
new file mode 100644
index 0000000000000..62584ec23e336
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
@@ -0,0 +1,4 @@
+//@ check-pass
+//@ compile-flags: -Cno-stack-check
+
+fn main() {}
diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr b/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr
new file mode 100644
index 0000000000000..17efba787f070
--- /dev/null
+++ b/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr
@@ -0,0 +1,2 @@
+warning: `-C no-stack-check`: this option is deprecated and does nothing
+
diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs
new file mode 100644
index 0000000000000..cff98b43fe745
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs
@@ -0,0 +1,4 @@
+//@ compile-flags: --check-cfg=cfg(emscripten_wasm_eh)
+#[cfg(not(emscripten_wasm_eh))]
+//~^ `cfg(emscripten_wasm_eh)` is experimental
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr
new file mode 100644
index 0000000000000..67769e3c7586b
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(emscripten_wasm_eh)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-emscripten-wasm-eh.rs:2:11
+ |
+LL | #[cfg(not(emscripten_wasm_eh))]
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(cfg_emscripten_wasm_eh)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 0f79cefeaecb7..f4e8a872cec12 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -17,20 +17,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied
- --> $DIR/normalize-tait-in-const.rs:33:19
- |
-LL | with_positive(foo);
- | ------------- ^^^
- | |
- | required by a bound introduced by this call
- |
-note: required by a bound in `with_positive`
- --> $DIR/normalize-tait-in-const.rs:26:62
- |
-LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
- | ^^^^^^ required by this bound in `with_positive`
-
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/normalize-tait-in-const.rs:27:5
|
@@ -39,7 +25,6 @@ LL | fun(filter_positive());
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr
index 03da9159bea0b..4cd87002e4910 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr
@@ -5,7 +5,7 @@ LL | T::Assoc::::func();
| ^^^^^^^^^^^^^
error[E0277]: the trait bound `U: ~const Other` is not satisfied
- --> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
+ --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
|
LL | ::Assoc::::func();
| ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr
index ce58b486a16ef..4cd87002e4910 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr
@@ -1,11 +1,11 @@
-error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied
+error[E0277]: the trait bound `U: ~const Other` is not satisfied
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
|
LL | T::Assoc::::func();
| ^^^^^^^^^^^^^
-error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied
- --> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
+error[E0277]: the trait bound `U: ~const Other` is not satisfied
+ --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
|
LL | ::Assoc::::func();
| ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs
index bdd98eaf541f8..e1c30b5361124 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs
@@ -22,11 +22,9 @@ trait Other {}
const fn fails() {
T::Assoc::::func();
- //[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
- //[next]~^^ ERROR the trait bound `::Assoc: ~const Trait` is not satisfied
+ //~^ ERROR the trait bound `U: ~const Other` is not satisfied
::Assoc::::func();
- //[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
- //[next]~^^ ERROR the trait bound `::Assoc: ~const Trait` is not satisfied
+ //~^ ERROR the trait bound `U: ~const Other` is not satisfied
}
const fn works() {
diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs
index 398fb39064055..4819da7c3a403 100644
--- a/tests/ui/traits/const-traits/const-drop-bound.rs
+++ b/tests/ui/traits/const-traits/const-drop-bound.rs
@@ -1,5 +1,4 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
#![feature(const_trait_impl)]
#![feature(const_precise_live_drops, const_destruct)]
diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr
deleted file mode 100644
index 78ba0279566de..0000000000000
--- a/tests/ui/traits/const-traits/const-drop-bound.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Foo: ~const Destruct` is not satisfied
- --> $DIR/const-drop-bound.rs:23:9
- |
-LL | foo(res)
- | --- ^^^
- | |
- | required by a bound introduced by this call
- |
-note: required by a bound in `foo`
- --> $DIR/const-drop-bound.rs:9:61
- |
-LL | const fn foo(res: Result) -> Option where E: ~const Destruct {
- | ^^^^^^ required by this bound in `foo`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
index 7b2cafb612441..7a32a6c4a15ac 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
--> $DIR/const-drop-fail-2.rs:31:23
|
LL | const _: () = check::>(
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
index 7b2cafb612441..7a32a6c4a15ac 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
--> $DIR/const-drop-fail-2.rs:31:23
|
LL | const _: () = check::>(
diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
similarity index 87%
rename from tests/ui/traits/const-traits/const-drop-fail.precise.stderr
rename to tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
index 8b3e777a0b098..682f48fe07af6 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
@@ -1,5 +1,5 @@
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
- --> $DIR/const-drop-fail.rs:32:5
+ --> $DIR/const-drop-fail.rs:33:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL | NonTrivialDrop,
| ^^^^^^^^^^^^^^
|
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:23:19
+ --> $DIR/const-drop-fail.rs:24:19
|
LL | const fn check(_: T) {}
| ^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
- --> $DIR/const-drop-fail.rs:34:5
+ --> $DIR/const-drop-fail.rs:35:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:23:19
+ --> $DIR/const-drop-fail.rs:24:19
|
LL | const fn check(_: T) {}
| ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
similarity index 87%
rename from tests/ui/traits/const-traits/const-drop-fail.stock.stderr
rename to tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
index 8b3e777a0b098..682f48fe07af6 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
@@ -1,5 +1,5 @@
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
- --> $DIR/const-drop-fail.rs:32:5
+ --> $DIR/const-drop-fail.rs:33:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL | NonTrivialDrop,
| ^^^^^^^^^^^^^^
|
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:23:19
+ --> $DIR/const-drop-fail.rs:24:19
|
LL | const fn check(_: T) {}
| ^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
- --> $DIR/const-drop-fail.rs:34:5
+ --> $DIR/const-drop-fail.rs:35:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:23:19
+ --> $DIR/const-drop-fail.rs:24:19
|
LL | const fn check(_: T) {}
| ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
new file mode 100644
index 0000000000000..682f48fe07af6
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+ --> $DIR/const-drop-fail.rs:33:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | NonTrivialDrop,
+ | ^^^^^^^^^^^^^^
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:24:19
+ |
+LL | const fn check(_: T) {}
+ | ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+ --> $DIR/const-drop-fail.rs:35:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstImplWithDropGlue(NonTrivialDrop),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:24:19
+ |
+LL | const fn check(_: T) {}
+ | ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
new file mode 100644
index 0000000000000..682f48fe07af6
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+ --> $DIR/const-drop-fail.rs:33:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | NonTrivialDrop,
+ | ^^^^^^^^^^^^^^
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:24:19
+ |
+LL | const fn check(_: T) {}
+ | ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+ --> $DIR/const-drop-fail.rs:35:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstImplWithDropGlue(NonTrivialDrop),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:24:19
+ |
+LL | const fn check(_: T) {}
+ | ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs
index 5e05b9db474a6..a7f3d5654de93 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.rs
+++ b/tests/ui/traits/const-traits/const-drop-fail.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -Znext-solver
-//@ revisions: stock precise
+//@[new_precise] compile-flags: -Znext-solver
+//@[new_stock] compile-flags: -Znext-solver
+//@ revisions: new_stock old_stock new_precise old_precise
#![feature(const_trait_impl, const_destruct)]
-#![cfg_attr(precise, feature(const_precise_live_drops))]
+#![cfg_attr(any(new_precise, old_precise), feature(const_precise_live_drops))]
use std::marker::{Destruct, PhantomData};
diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
index 3fc6f58470947..0d53bc5897ef3 100644
--- a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
+++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
@@ -16,6 +16,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied
LL | type Assoc = C
| ^^^^
|
+note: required for `C` to implement `~const Bar`
+ --> $DIR/item-bound-entailment-fails.rs:14:15
+ |
+LL | impl const Bar for C where T: ~const Bar {}
+ | ^^^ ^^^^ ------ unsatisfied trait bound introduced here
note: required by a bound in `Foo::Assoc`
--> $DIR/item-bound-entailment-fails.rs:5:20
|
diff --git a/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.rs b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.rs
new file mode 100644
index 0000000000000..129e90a07f43a
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Znext-solver
+
+trait Trait<'a> {
+ type Assoc;
+}
+
+fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+ //~^ ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ unsafe { std::mem::transmute::<_, ()>(x); }
+ //~^ ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ //~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr
new file mode 100644
index 0000000000000..2d42fedae4381
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-ice-on-bad-transmute-in-typeck.stderr
@@ -0,0 +1,75 @@
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:11
+ |
+LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+ |
+LL | trait Trait<'a> {
+ | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:8
+ |
+LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+ | ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+ |
+LL | trait Trait<'a> {
+ | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:14
+ |
+LL | unsafe { std::mem::transmute::<_, ()>(x); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+ |
+LL | trait Trait<'a> {
+ | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:36
+ |
+LL | unsafe { std::mem::transmute::<_, ()>(x); }
+ | ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+ |
+LL | trait Trait<'a> {
+ | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:43
+ |
+LL | unsafe { std::mem::transmute::<_, ()>(x); }
+ | ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+ |
+LL | trait Trait<'a> {
+ | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:1
+ |
+LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
+ |
+LL | trait Trait<'a> {
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/triagebot.toml b/triagebot.toml
index 7efa63c2642fd..2a0ad610c1a00 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -824,7 +824,7 @@ cc = ["@rust-lang/rustfmt"]
[mentions."compiler/rustc_middle/src/mir/syntax.rs"]
message = "This PR changes MIR"
-cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakaras"]
+cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@vakaras"]
[mentions."compiler/rustc_error_messages"]
message = "`rustc_error_messages` was changed"
@@ -1004,7 +1004,6 @@ warn_non_default_branch.enable = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
"jyn514",
- "celinval",
"nnethercote",
"spastorino",
"workingjubilee",