=
- ty_params.map(|ty_param| ty_param.ident.name).collect();
-
- for field_ty in field_tys {
- let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
-
- for field_ty_param in field_ty_params {
- // if we have already handled this type, skip it
- if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
- && let [sole_segment] = &*p.segments
- && ty_param_names.contains(&sole_segment.ident.name)
- {
- continue;
- }
- let mut bounds: Vec<_> = self
- .additional_bounds
- .iter()
- .map(|p| {
- cx.trait_bound(
- p.to_path(cx, self.span, type_ident, generics),
- self.is_const,
- )
- })
- .collect();
-
- // Require the current trait.
- if !self.skip_path_as_bound {
- bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
- }
+ let ty_param_names: Vec = params
+ .iter()
+ .filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
+ .map(|ty_param| ty_param.ident.name)
+ .collect();
- // Add a `Copy` bound if required.
- if is_packed && self.needs_copy_as_bound_if_packed {
- let p = deriving::path_std!(marker::Copy);
- bounds.push(cx.trait_bound(
+ if !ty_param_names.is_empty() {
+ for field_ty in field_tys {
+ let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
+
+ for field_ty_param in field_ty_params {
+ // if we have already handled this type, skip it
+ if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
+ && let [sole_segment] = &*p.segments
+ && ty_param_names.contains(&sole_segment.ident.name)
+ {
+ continue;
+ }
+ let mut bounds: Vec<_> = self
+ .additional_bounds
+ .iter()
+ .map(|p| {
+ cx.trait_bound(
p.to_path(cx, self.span, type_ident, generics),
self.is_const,
- ));
- }
+ )
+ })
+ .collect();
- if !bounds.is_empty() {
- let predicate = ast::WhereBoundPredicate {
- span: self.span,
- bound_generic_params: field_ty_param.bound_generic_params,
- bounded_ty: field_ty_param.ty,
- bounds,
- };
+ // Require the current trait.
+ if !self.skip_path_as_bound {
+ bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
+ }
- let predicate = ast::WherePredicate::BoundPredicate(predicate);
- where_clause.predicates.push(predicate);
- }
+ // Add a `Copy` bound if required.
+ if is_packed && self.needs_copy_as_bound_if_packed {
+ let p = deriving::path_std!(marker::Copy);
+ bounds.push(cx.trait_bound(
+ p.to_path(cx, self.span, type_ident, generics),
+ self.is_const,
+ ));
+ }
+
+ if !bounds.is_empty() {
+ let predicate = ast::WhereBoundPredicate {
+ span: self.span,
+ bound_generic_params: field_ty_param.bound_generic_params,
+ bounded_ty: field_ty_param.ty,
+ bounds,
+ };
+
+ let predicate = ast::WherePredicate::BoundPredicate(predicate);
+ where_clause.predicates.push(predicate);
}
}
}
@@ -1026,6 +1039,7 @@ impl<'a> MethodDef<'a> {
}
/// The normal case uses field access.
+ ///
/// ```
/// #[derive(PartialEq)]
/// # struct Dummy;
@@ -1038,10 +1052,12 @@ impl<'a> MethodDef<'a> {
/// }
/// }
/// ```
+ ///
/// But if the struct is `repr(packed)`, we can't use something like
/// `&self.x` because that might cause an unaligned ref. So for any trait
/// method that takes a reference, we use a local block to force a copy.
/// This requires that the field impl `Copy`.
+ ///
/// ```rust,ignore (example)
/// # struct A { x: u8, y: u8 }
/// impl PartialEq for A {
@@ -1053,7 +1069,7 @@ impl<'a> MethodDef<'a> {
/// impl Hash for A {
/// fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
/// ::core::hash::Hash::hash(&{ self.x }, state);
- /// ::core::hash::Hash::hash(&{ self.y }, state)
+ /// ::core::hash::Hash::hash(&{ self.y }, state);
/// }
/// }
/// ```
@@ -1107,7 +1123,9 @@ impl<'a> MethodDef<'a> {
/// A2(i32)
/// }
/// ```
+ ///
/// is equivalent to:
+ ///
/// ```
/// #![feature(core_intrinsics)]
/// enum A {
@@ -1119,15 +1137,15 @@ impl<'a> MethodDef<'a> {
/// fn eq(&self, other: &A) -> bool {
/// let __self_tag = ::core::intrinsics::discriminant_value(self);
/// let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- /// __self_tag == __arg1_tag &&
- /// match (self, other) {
- /// (A::A2(__self_0), A::A2(__arg1_0)) =>
- /// *__self_0 == *__arg1_0,
+ /// __self_tag == __arg1_tag
+ /// && match (self, other) {
+ /// (A::A2(__self_0), A::A2(__arg1_0)) => *__self_0 == *__arg1_0,
/// _ => true,
/// }
/// }
/// }
/// ```
+ ///
/// Creates a tag check combined with a match for a tuple of all
/// `selflike_args`, with an arm for each variant with fields, possibly an
/// arm for each fieldless variant (if `unify_fieldless_variants` is not
@@ -1349,7 +1367,7 @@ impl<'a> MethodDef<'a> {
// (Variant1, Variant1, ...) => Body1
// (Variant2, Variant2, ...) => Body2,
// ...
- // _ => ::core::intrinsics::unreachable()
+ // _ => ::core::intrinsics::unreachable(),
// }
let get_match_expr = |mut selflike_args: ThinVec>| {
let match_arg = if selflike_args.len() == 1 {
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 9e834b83df43c..6e3a4cae2f62b 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -362,9 +362,14 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
// currently use this mode so we have to allow it -- but we absolutely
// shouldn't let any more targets do that.
// (Also see .)
+ //
+ // The unstable abi `PtxKernel` also uses Direct for now.
+ // It needs to switch to something else before stabilization can happen.
+ // (See issue: https://github.com/rust-lang/rust/issues/117271)
assert!(
- matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64"),
- "`PassMode::Direct` for aggregates only allowed on wasm targets\nProblematic type: {:#?}",
+ matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64")
+ || self.conv == Conv::PtxKernel,
+ "`PassMode::Direct` for aggregates only allowed on wasm and `extern \"ptx-kernel\"` fns\nProblematic type: {:#?}",
arg.layout,
);
}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index f16fe372a92c9..d8c89f5947fb5 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -22,7 +22,9 @@ use rustc_session::utils::NativeLibKind;
/// need out of the shared crate context before we get rid of it.
use rustc_session::{filesearch, Session};
use rustc_span::symbol::Symbol;
-use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
+use rustc_target::spec::crt_objects::CrtObjects;
+use rustc_target::spec::LinkSelfContainedComponents;
+use rustc_target::spec::LinkSelfContainedDefault;
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
@@ -728,6 +730,7 @@ fn link_natively<'a>(
) -> Result<(), ErrorGuaranteed> {
info!("preparing {:?} to {:?}", crate_type, out_filename);
let (linker_path, flavor) = linker_and_flavor(sess);
+ let self_contained_components = self_contained_components(sess, crate_type);
let mut cmd = linker_with_args(
&linker_path,
flavor,
@@ -737,6 +740,7 @@ fn link_natively<'a>(
tmpdir,
out_filename,
codegen_results,
+ self_contained_components,
)?;
linker::disable_localization(&mut cmd);
@@ -812,14 +816,14 @@ fn link_natively<'a>(
"Linker does not support -static-pie command line option. Retrying with -static instead."
);
// Mirror `add_(pre,post)_link_objects` to replace CRT objects.
- let self_contained = self_contained(sess, crate_type);
+ let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
let opts = &sess.target;
- let pre_objects = if self_contained {
+ let pre_objects = if self_contained_crt_objects {
&opts.pre_link_objects_self_contained
} else {
&opts.pre_link_objects
};
- let post_objects = if self_contained {
+ let post_objects = if self_contained_crt_objects {
&opts.post_link_objects_self_contained
} else {
&opts.post_link_objects
@@ -830,7 +834,9 @@ fn link_natively<'a>(
.iter()
.copied()
.flatten()
- .map(|obj| get_object_file_path(sess, obj, self_contained).into_os_string())
+ .map(|obj| {
+ get_object_file_path(sess, obj, self_contained_crt_objects).into_os_string()
+ })
.collect::>()
};
let pre_objects_static_pie = get_objects(pre_objects, LinkOutputKind::StaticPicExe);
@@ -1710,26 +1716,43 @@ fn detect_self_contained_mingw(sess: &Session) -> bool {
/// Various toolchain components used during linking are used from rustc distribution
/// instead of being found somewhere on the host system.
/// We only provide such support for a very limited number of targets.
-fn self_contained(sess: &Session, crate_type: CrateType) -> bool {
- if let Some(self_contained) = sess.opts.cg.link_self_contained.explicitly_set {
- if sess.target.link_self_contained == LinkSelfContainedDefault::False {
- sess.emit_err(errors::UnsupportedLinkSelfContained);
- }
- return self_contained;
- }
+fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents {
+ // Turn the backwards compatible bool values for `self_contained` into fully inferred
+ // `LinkSelfContainedComponents`.
+ let self_contained =
+ if let Some(self_contained) = sess.opts.cg.link_self_contained.explicitly_set {
+ // Emit an error if the user requested self-contained mode on the CLI but the target
+ // explicitly refuses it.
+ if sess.target.link_self_contained.is_disabled() {
+ sess.emit_err(errors::UnsupportedLinkSelfContained);
+ }
+ self_contained
+ } else {
+ match sess.target.link_self_contained {
+ LinkSelfContainedDefault::False => false,
+ LinkSelfContainedDefault::True => true,
+
+ LinkSelfContainedDefault::WithComponents(components) => {
+ // For target specs with explicitly enabled components, we can return them
+ // directly.
+ return components;
+ }
- match sess.target.link_self_contained {
- LinkSelfContainedDefault::False => false,
- LinkSelfContainedDefault::True => true,
- // FIXME: Find a better heuristic for "native musl toolchain is available",
- // based on host and linker path, for example.
- // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237).
- LinkSelfContainedDefault::Musl => sess.crt_static(Some(crate_type)),
- LinkSelfContainedDefault::Mingw => {
- sess.host == sess.target
- && sess.target.vendor != "uwp"
- && detect_self_contained_mingw(&sess)
- }
+ // FIXME: Find a better heuristic for "native musl toolchain is available",
+ // based on host and linker path, for example.
+ // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237).
+ LinkSelfContainedDefault::InferredForMusl => sess.crt_static(Some(crate_type)),
+ LinkSelfContainedDefault::InferredForMingw => {
+ sess.host == sess.target
+ && sess.target.vendor != "uwp"
+ && detect_self_contained_mingw(&sess)
+ }
+ }
+ };
+ if self_contained {
+ LinkSelfContainedComponents::all()
+ } else {
+ LinkSelfContainedComponents::empty()
}
}
@@ -1889,37 +1912,14 @@ fn add_linked_symbol_object(
return;
};
- // NOTE(nbdd0121): MSVC will hang if the input object file contains no sections,
- // so add an empty section.
if file.format() == object::BinaryFormat::Coff {
+ // NOTE(nbdd0121): MSVC will hang if the input object file contains no sections,
+ // so add an empty section.
file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text);
// We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the
// default mangler in `object` crate.
file.set_mangling(object::write::Mangling::None);
-
- // Add feature flags to the object file. On MSVC this is optional but LLD will complain if
- // not present.
- let mut feature = 0;
-
- if file.architecture() == object::Architecture::I386 {
- // Indicate that all SEH handlers are registered in .sxdata section.
- // We don't have generate any code, so we don't need .sxdata section but LLD still
- // expects us to set this bit (see #96498).
- // Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
- feature |= 1;
- }
-
- file.add_symbol(object::write::Symbol {
- name: "@feat.00".into(),
- value: feature,
- size: 0,
- kind: object::SymbolKind::Data,
- scope: object::SymbolScope::Compilation,
- weak: false,
- section: object::write::SymbolSection::Absolute,
- flags: object::SymbolFlags::None,
- });
}
for (sym, kind) in symbols.iter() {
@@ -2053,13 +2053,14 @@ fn linker_with_args<'a>(
tmpdir: &Path,
out_filename: &Path,
codegen_results: &CodegenResults,
+ self_contained_components: LinkSelfContainedComponents,
) -> Result {
- let self_contained = self_contained(sess, crate_type);
+ let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
let cmd = &mut *super::linker::get_linker(
sess,
path,
flavor,
- self_contained,
+ self_contained_components.are_any_components_enabled(),
&codegen_results.crate_info.target_cpu,
);
let link_output_kind = link_output_kind(sess, crate_type);
@@ -2086,7 +2087,7 @@ fn linker_with_args<'a>(
// ------------ Object code and libraries, order-dependent ------------
// Pre-link CRT objects.
- add_pre_link_objects(cmd, sess, flavor, link_output_kind, self_contained);
+ add_pre_link_objects(cmd, sess, flavor, link_output_kind, self_contained_crt_objects);
add_linked_symbol_object(
cmd,
@@ -2229,7 +2230,7 @@ fn linker_with_args<'a>(
cmd,
sess,
link_output_kind,
- self_contained,
+ self_contained_components,
flavor,
crate_type,
codegen_results,
@@ -2245,7 +2246,7 @@ fn linker_with_args<'a>(
// ------------ Object code and libraries, order-dependent ------------
// Post-link CRT objects.
- add_post_link_objects(cmd, sess, link_output_kind, self_contained);
+ add_post_link_objects(cmd, sess, link_output_kind, self_contained_crt_objects);
// ------------ Late order-dependent options ------------
@@ -2262,7 +2263,7 @@ fn add_order_independent_options(
cmd: &mut dyn Linker,
sess: &Session,
link_output_kind: LinkOutputKind,
- self_contained: bool,
+ self_contained_components: LinkSelfContainedComponents,
flavor: LinkerFlavor,
crate_type: CrateType,
codegen_results: &CodegenResults,
@@ -2270,7 +2271,7 @@ fn add_order_independent_options(
tmpdir: &Path,
) {
// Take care of the flavors and CLI options requesting the `lld` linker.
- add_lld_args(cmd, sess, flavor);
+ add_lld_args(cmd, sess, flavor, self_contained_components);
add_apple_sdk(cmd, sess, flavor);
@@ -2295,7 +2296,7 @@ fn add_order_independent_options(
// Make the binary compatible with data execution prevention schemes.
cmd.add_no_exec();
- if self_contained {
+ if self_contained_components.is_crt_objects_enabled() {
cmd.no_crt_objects();
}
@@ -2326,7 +2327,7 @@ fn add_order_independent_options(
cmd.linker_plugin_lto();
- add_library_search_dirs(cmd, sess, self_contained);
+ add_library_search_dirs(cmd, sess, self_contained_components.are_any_components_enabled());
cmd.output_filename(out_filename);
@@ -2976,8 +2977,16 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result Option {
let arch = match sess.target.options.cpu.as_ref() {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index e401f6bbcbfb2..5900c764073df 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
-use rustc_hir::{AsyncCoroutineKind, CoroutineKind, Mutability};
+use rustc_hir::{CoroutineKind, CoroutineSource, Mutability};
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
@@ -560,9 +560,9 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &
fn coroutine_kind_label(coroutine_kind: Option) -> &'static str {
match coroutine_kind {
- Some(CoroutineKind::Async(AsyncCoroutineKind::Block)) => "async_block",
- Some(CoroutineKind::Async(AsyncCoroutineKind::Closure)) => "async_closure",
- Some(CoroutineKind::Async(AsyncCoroutineKind::Fn)) => "async_fn",
+ Some(CoroutineKind::Async(CoroutineSource::Block)) => "async_block",
+ Some(CoroutineKind::Async(CoroutineSource::Closure)) => "async_closure",
+ Some(CoroutineKind::Async(CoroutineSource::Fn)) => "async_fn",
Some(CoroutineKind::Coroutine) => "coroutine",
None => "closure",
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 616fab8fe7d65..40183baccf8fe 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -360,7 +360,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
pub struct Coroutine(pub hir::CoroutineKind);
impl<'tcx> NonConstOp<'tcx> for Coroutine {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
- if let hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) = self.0 {
+ if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 {
Status::Unstable(sym::const_async_blocks)
} else {
Status::Forbidden
@@ -372,8 +372,8 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
- if let hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) = self.0 {
+ let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
+ if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 {
ccx.tcx.sess.create_feature_err(
errors::UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index d3bd3244a52aa..39462112dc287 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,5 +1,6 @@
driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
driver_impl_ice_flags = compiler flags: {$flags}
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 7e4a7d93210e5..c6c8fd22f4efc 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -60,7 +60,7 @@ use std::path::PathBuf;
use std::process::{self, Command, Stdio};
use std::str;
use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::OnceLock;
+use std::sync::{Arc, OnceLock};
use std::time::{Instant, SystemTime};
use time::OffsetDateTime;
@@ -136,7 +136,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
rustc_query_system::DEFAULT_LOCALE_RESOURCE,
rustc_resolve::DEFAULT_LOCALE_RESOURCE,
rustc_session::DEFAULT_LOCALE_RESOURCE,
- rustc_symbol_mangling::DEFAULT_LOCALE_RESOURCE,
rustc_trait_selection::DEFAULT_LOCALE_RESOURCE,
rustc_ty_utils::DEFAULT_LOCALE_RESOURCE,
// tidy-alphabetical-end
@@ -223,11 +222,18 @@ pub struct RunCompiler<'a, 'b> {
file_loader: Option>,
make_codegen_backend:
Option Box + Send>>,
+ using_internal_features: Arc,
}
impl<'a, 'b> RunCompiler<'a, 'b> {
pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
- Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
+ Self {
+ at_args,
+ callbacks,
+ file_loader: None,
+ make_codegen_backend: None,
+ using_internal_features: Arc::default(),
+ }
}
/// Set a custom codegen backend.
@@ -259,9 +265,23 @@ impl<'a, 'b> RunCompiler<'a, 'b> {
self
}
+ /// Set the session-global flag that checks whether internal features have been used,
+ /// suppressing the message about submitting an issue in ICEs when enabled.
+ #[must_use]
+ pub fn set_using_internal_features(mut self, using_internal_features: Arc) -> Self {
+ self.using_internal_features = using_internal_features;
+ self
+ }
+
/// Parse args and run the compiler.
pub fn run(self) -> interface::Result<()> {
- run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
+ run_compiler(
+ self.at_args,
+ self.callbacks,
+ self.file_loader,
+ self.make_codegen_backend,
+ self.using_internal_features,
+ )
}
}
@@ -272,6 +292,7 @@ fn run_compiler(
make_codegen_backend: Option<
Box Box + Send>,
>,
+ using_internal_features: Arc,
) -> interface::Result<()> {
let mut early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default());
@@ -316,6 +337,7 @@ fn run_compiler(
override_queries: None,
make_codegen_backend,
registry: diagnostics_registry(),
+ using_internal_features,
expanded_args: args,
};
@@ -1333,8 +1355,12 @@ fn ice_path() -> &'static Option {
/// If you have no extra info to report, pass the empty closure `|_| ()` as the argument to
/// extra_info.
///
+/// Returns a flag that can be set to disable the note for submitting a bug. This can be passed to
+/// [`RunCompiler::set_using_internal_features`] to let macro expansion set it when encountering
+/// internal features.
+///
/// A custom rustc driver can skip calling this to set up a custom ICE hook.
-pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) {
+pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) -> Arc {
// If the user has not explicitly overridden "RUST_BACKTRACE", then produce
// full backtraces. When a compiler ICE happens, we want to gather
// as much information as possible to present in the issue opened
@@ -1345,6 +1371,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
std::env::set_var("RUST_BACKTRACE", "full");
}
+ let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
+ let using_internal_features_hook = using_internal_features.clone();
panic::update_hook(Box::new(
move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static),
info: &PanicInfo<'_>| {
@@ -1394,9 +1422,11 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
}
// Print the ICE message
- report_ice(info, bug_report_url, extra_info);
+ report_ice(info, bug_report_url, extra_info, &using_internal_features_hook);
},
));
+
+ using_internal_features
}
/// Prints the ICE message, including query stack, but without backtrace.
@@ -1405,7 +1435,12 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
///
/// When `install_ice_hook` is called, this function will be called as the panic
/// hook.
-fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: fn(&Handler)) {
+fn report_ice(
+ info: &panic::PanicInfo<'_>,
+ bug_report_url: &str,
+ extra_info: fn(&Handler),
+ using_internal_features: &AtomicBool,
+) {
let fallback_bundle =
rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
@@ -1422,7 +1457,11 @@ fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: fn(
handler.emit_err(session_diagnostics::Ice);
}
- handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+ if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
+ handler.emit_note(session_diagnostics::IceBugReportInternalFeature);
+ } else {
+ handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+ }
let version = util::version_str!().unwrap_or("unknown_version");
let triple = config::host_triple();
@@ -1506,7 +1545,7 @@ pub fn main() -> ! {
init_rustc_env_logger(&handler);
signal_handler::install();
let mut callbacks = TimePassesCallbacks::default();
- install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
+ let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
let exit_code = catch_with_exit_code(|| {
let args = env::args_os()
.enumerate()
@@ -1516,7 +1555,9 @@ pub fn main() -> ! {
})
})
.collect::>();
- RunCompiler::new(&args, &mut callbacks).run()
+ RunCompiler::new(&args, &mut callbacks)
+ .set_using_internal_features(using_internal_features)
+ .run()
});
if let Some(format) = callbacks.time_passes {
diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs
index 442989f8de83a..2b31fdd77cca3 100644
--- a/compiler/rustc_driver_impl/src/session_diagnostics.rs
+++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs
@@ -42,6 +42,10 @@ pub(crate) struct IceBugReport<'a> {
pub bug_report_url: &'a str,
}
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_bug_report_internal_feature)]
+pub(crate) struct IceBugReportInternalFeature;
+
#[derive(Diagnostic)]
#[diag(driver_impl_ice_version)]
pub(crate) struct IceVersion<'a> {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index da74ee6391ae2..5e3fdf170bc0c 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -508,6 +508,8 @@ pub enum StashKey {
TraitMissingMethod,
OpaqueHiddenTypeMismatch,
MaybeForgetReturn,
+ /// Query cycle detected, stashing in favor of a better error.
+ Cycle,
}
fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index b73c7593381c3..bef48765937f5 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -35,7 +35,7 @@ pub struct StripUnconfigured<'a> {
pub lint_node_id: NodeId,
}
-pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
+pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -> Features {
fn feature_list(attr: &Attribute) -> ThinVec {
if attr.has_name(sym::feature)
&& let Some(list) = attr.meta_item_list()
@@ -167,6 +167,15 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
// If the declared feature is unstable, record it.
if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) {
(f.set_enabled)(&mut features);
+ // When the ICE comes from core, alloc or std (approximation of the standard library), there's a chance
+ // that the person hitting the ICE may be using -Zbuild-std or similar with an untested target.
+ // The bug is probably in the standard library and not the compiler in that case, but that doesn't
+ // really matter - we want a bug report.
+ if features.internal(name)
+ && ![sym::core, sym::alloc, sym::std].contains(&crate_name)
+ {
+ sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
+ }
features.set_declared_lang_feature(name, mi.span(), None);
continue;
}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f8d55192a3747..17c6352ce24c2 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -246,6 +246,8 @@ impl<'hir> PathSegment<'hir> {
pub struct ConstArg {
pub value: AnonConst,
pub span: Span,
+ /// Indicates whether this comes from a `~const` desugaring.
+ pub is_desugared_from_effects: bool,
}
#[derive(Clone, Copy, Debug, HashStable_Generic)]
@@ -400,7 +402,14 @@ impl<'hir> GenericArgs<'hir> {
/// This function returns the number of type and const generic params.
/// It should only be used for diagnostics.
pub fn num_generic_params(&self) -> usize {
- self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
+ self.args
+ .iter()
+ .filter(|arg| match arg {
+ GenericArg::Lifetime(_)
+ | GenericArg::Const(ConstArg { is_desugared_from_effects: true, .. }) => false,
+ _ => true,
+ })
+ .count()
}
/// The span encompassing the text inside the surrounding brackets.
@@ -1511,7 +1520,7 @@ impl<'hir> Body<'hir> {
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum CoroutineKind {
/// An explicit `async` block or the body of an async function.
- Async(AsyncCoroutineKind),
+ Async(CoroutineSource),
/// A coroutine literal created via a `yield` inside a closure.
Coroutine,
@@ -1520,56 +1529,45 @@ pub enum CoroutineKind {
impl fmt::Display for CoroutineKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- CoroutineKind::Async(k) => fmt::Display::fmt(k, f),
+ CoroutineKind::Async(k) => {
+ if f.alternate() {
+ f.write_str("`async` ")?;
+ } else {
+ f.write_str("async ")?
+ }
+ k.fmt(f)
+ }
CoroutineKind::Coroutine => f.write_str("coroutine"),
}
}
}
-impl CoroutineKind {
- pub fn descr(&self) -> &'static str {
- match self {
- CoroutineKind::Async(ask) => ask.descr(),
- CoroutineKind::Coroutine => "coroutine",
- }
- }
-}
-
-/// In the case of a coroutine created as part of an async construct,
-/// which kind of async construct caused it to be created?
+/// In the case of a coroutine created as part of an async/gen construct,
+/// which kind of async/gen construct caused it to be created?
///
/// This helps error messages but is also used to drive coercions in
/// type-checking (see #60424).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
#[derive(HashStable_Generic, Encodable, Decodable)]
-pub enum AsyncCoroutineKind {
- /// An explicit `async` block written by the user.
+pub enum CoroutineSource {
+ /// An explicit `async`/`gen` block written by the user.
Block,
- /// An explicit `async` closure written by the user.
+ /// An explicit `async`/`gen` closure written by the user.
Closure,
- /// The `async` block generated as the body of an async function.
+ /// The `async`/`gen` block generated as the body of an async/gen function.
Fn,
}
-impl fmt::Display for AsyncCoroutineKind {
+impl fmt::Display for CoroutineSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(match self {
- AsyncCoroutineKind::Block => "async block",
- AsyncCoroutineKind::Closure => "async closure body",
- AsyncCoroutineKind::Fn => "async fn body",
- })
- }
-}
-
-impl AsyncCoroutineKind {
- pub fn descr(&self) -> &'static str {
match self {
- AsyncCoroutineKind::Block => "`async` block",
- AsyncCoroutineKind::Closure => "`async` closure body",
- AsyncCoroutineKind::Fn => "`async fn` body",
+ CoroutineSource::Block => "block",
+ CoroutineSource::Closure => "closure body",
+ CoroutineSource::Fn => "fn body",
}
+ .fmt(f)
}
}
@@ -3781,6 +3779,7 @@ impl<'hir> Node<'hir> {
ItemKind::TyAlias(ty, _)
| ItemKind::Static(ty, _, _)
| ItemKind::Const(ty, _, _) => Some(ty),
+ ItemKind::Impl(impl_item) => Some(&impl_item.self_ty),
_ => None,
},
Node::TraitItem(it) => match it.kind {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index cdfc67d5740f6..c8ac95e29949b 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -210,6 +210,7 @@ language_item_table! {
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
+ Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
CoroutineState, sym::coroutine_state, gen_state, Target::Enum, GenericRequirement::None;
Coroutine, sym::coroutine, gen_trait, Target::Trait, GenericRequirement::Minimum(1);
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 7f0c0b961e4e8..d29a27eced0e7 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -429,6 +429,14 @@ pub(crate) fn check_generic_arg_count(
.filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
.count();
let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
+ let synth_const_param_count = gen_params
+ .params
+ .iter()
+ .filter(|param| {
+ matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. })
+ })
+ .count();
+ let named_const_param_count = param_counts.consts - synth_const_param_count;
let infer_lifetimes =
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
@@ -573,11 +581,13 @@ pub(crate) fn check_generic_arg_count(
debug!(?expected_min);
debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params());
+ let provided = gen_args.num_generic_params();
+
check_types_and_consts(
expected_min,
- param_counts.consts + named_type_param_count,
- param_counts.consts + named_type_param_count + synth_type_param_count,
- gen_args.num_generic_params(),
+ named_const_param_count + named_type_param_count,
+ named_const_param_count + named_type_param_count + synth_type_param_count,
+ provided,
param_counts.lifetimes + has_self as usize,
gen_args.num_lifetime_params(),
)
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 360d31b863c1d..e61ca232de643 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -128,7 +128,11 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
let param_env = tcx.param_env(item_def_id);
for field in &def.non_enum_variant().fields {
- let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, args));
+ let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args))
+ else {
+ tcx.sess.delay_span_bug(span, "could not normalize field type");
+ continue;
+ };
if !allowed_union_field(field_ty, tcx, param_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 0622aa2ee80fb..2b8219c01c769 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -181,14 +181,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
})?;
}
- tcx.sess.track_errors(|| {
- tcx.sess.time("impl_wf_inference", || {
- tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
- });
- })?;
-
tcx.sess.track_errors(|| {
tcx.sess.time("coherence_checking", || {
+ // Check impls constrain their parameters
+ tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
+
for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
tcx.ensure().coherent_trait(trait_def_id);
}
@@ -205,15 +202,19 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
})?;
}
- tcx.sess.time("wf_checking", || {
+ let errs = tcx.sess.time("wf_checking", || {
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
- })?;
+ });
// NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
tcx.sess.time("item_types_checking", || {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
+ // HACK: `check_mod_type_wf` may spuriously emit errors due to `delay_span_bug`, even if those errors
+ // only actually get emitted in `check_mod_item_types`.
+ errs?;
+
if tcx.features().rustc_attrs {
tcx.sess.track_errors(|| collect::test_opaque_hidden_types(tcx))?;
}
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 2b5f6fd214c1f..76bd370a641b4 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -129,6 +129,44 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
if self.missing_lifetimes() { "lifetime" } else { "generic" }
}
+ /// Returns true if the generic type is a trait
+ /// and is being referred to from one of its trait impls
+ fn is_in_trait_impl(&self) -> bool {
+ if self.tcx.is_trait(self.def_id) {
+ // Here we check if the reference to the generic type
+ // is from the 'of_trait' field of the enclosing impl
+
+ let parent = self.tcx.hir().get_parent(self.path_segment.hir_id);
+ let parent_item = self
+ .tcx
+ .hir()
+ .get_by_def_id(self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id);
+
+ // Get the HIR id of the trait ref
+ let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else {
+ return false;
+ };
+
+ // Get the HIR id of the 'of_trait' field of the impl
+ let hir::Node::Item(hir::Item {
+ kind:
+ hir::ItemKind::Impl(hir::Impl {
+ of_trait: Some(hir::TraitRef { hir_ref_id: id_in_of_trait, .. }),
+ ..
+ }),
+ ..
+ }) = parent_item
+ else {
+ return false;
+ };
+
+ // Check that trait is referred to from the of_trait field of impl
+ trait_ref_id == id_in_of_trait
+ } else {
+ false
+ }
+ }
+
fn num_provided_args(&self) -> usize {
if self.missing_lifetimes() {
self.num_provided_lifetime_args()
@@ -955,20 +993,26 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
// If there is a single unbound associated type and a single excess generic param
// suggest replacing the generic param with the associated type bound
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
- let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
- let suggestions = iter::zip(unused_generics, &unbound_types)
- .map(|(potential, name)| (potential.span().shrink_to_lo(), format!("{name} = ")))
- .collect::>();
+ // Don't suggest if we're in a trait impl as
+ // that would result in invalid syntax (fixes #116464)
+ if !self.is_in_trait_impl() {
+ let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
+ let suggestions = iter::zip(unused_generics, &unbound_types)
+ .map(|(potential, name)| {
+ (potential.span().shrink_to_lo(), format!("{name} = "))
+ })
+ .collect::>();
- if !suggestions.is_empty() {
- err.multipart_suggestion_verbose(
- format!(
- "replace the generic bound{s} with the associated type{s}",
- s = pluralize!(unbound_types.len())
- ),
- suggestions,
- Applicability::MaybeIncorrect,
- );
+ if !suggestions.is_empty() {
+ err.multipart_suggestion_verbose(
+ format!(
+ "replace the generic bound{s} with the associated type{s}",
+ s = pluralize!(unbound_types.len())
+ ),
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
+ }
}
} else if remove_entire_generics {
let span = self
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 5eb68cf6b28c3..6b6d1574b2bf6 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -305,7 +305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) = (parent_node, callee_node)
{
let fn_decl_span = if hir.body(body).coroutine_kind
- == Some(hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Closure))
+ == Some(hir::CoroutineKind::Async(hir::CoroutineSource::Closure))
{
// Actually need to unwrap one more layer of HIR to get to
// the _real_ closure...
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index a834ea150477c..ee23f47c2711c 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -660,9 +660,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
} else {
match self.try_coercion_cast(fcx) {
Ok(()) => {
- self.trivial_cast_lint(fcx);
- debug!(" -> CoercionCast");
- fcx.typeck_results.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id);
+ if self.expr_ty.is_unsafe_ptr() && self.cast_ty.is_unsafe_ptr() {
+ // When casting a raw pointer to another raw pointer, we cannot convert the cast into
+ // a coercion because the pointee types might only differ in regions, which HIR typeck
+ // cannot distinguish. This would cause us to erroneously discard a cast which will
+ // lead to a borrowck error like #113257.
+ // We still did a coercion above to unify inference variables for `ptr as _` casts.
+ // This does cause us to miss some trivial casts in the trival cast lint.
+ debug!(" -> PointerCast");
+ } else {
+ self.trivial_cast_lint(fcx);
+ debug!(" -> CoercionCast");
+ fcx.typeck_results
+ .borrow_mut()
+ .set_coercion_cast(self.expr.hir_id.local_id);
+ }
}
Err(_) => {
match self.do_check(fcx) {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index cf8a4cafbb611..47bde21ceb2eb 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -636,7 +636,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// In the case of the async block that we create for a function body,
// we expect the return type of the block to match that of the enclosing
// function.
- Some(hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Fn)) => {
+ Some(hir::CoroutineKind::Async(hir::CoroutineSource::Fn)) => {
debug!("closure is async fn body");
let def_id = self.tcx.hir().body_owner_def_id(body.id());
self.deduce_future_output_from_obligations(expr_def_id, def_id).unwrap_or_else(
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index f379e8477e389..abb8322803010 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -962,38 +962,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
- let ty::Adt(e, args_e) = expected.kind() else {
- return false;
- };
- let ty::Adt(f, args_f) = found.kind() else {
- return false;
- };
- if e.did() != f.did() {
- return false;
- }
- if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
- return false;
- }
let map = self.tcx.hir();
- if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
- && let hir::ExprKind::Ret(_) = expr.kind
- {
- // `return foo;`
- } else if map.get_return_block(expr.hir_id).is_some() {
- // Function's tail expression.
- } else {
- return false;
- }
- let e = args_e.type_at(1);
- let f = args_f.type_at(1);
- if self
- .infcx
- .type_implements_trait(
- self.tcx.get_diagnostic_item(sym::Into).unwrap(),
- [f, e],
- self.param_env,
- )
- .must_apply_modulo_regions()
+ let returned = matches!(
+ map.find_parent(expr.hir_id),
+ Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. }))
+ ) || map.get_return_block(expr.hir_id).is_some();
+ if returned
+ && let ty::Adt(e, args_e) = expected.kind()
+ && let ty::Adt(f, args_f) = found.kind()
+ && e.did() == f.did()
+ && Some(e.did()) == self.tcx.get_diagnostic_item(sym::Result)
+ && let e_ok = args_e.type_at(0)
+ && let f_ok = args_f.type_at(0)
+ && self.infcx.can_eq(self.param_env, f_ok, e_ok)
+ && let e_err = args_e.type_at(1)
+ && let f_err = args_f.type_at(1)
+ && self
+ .infcx
+ .type_implements_trait(
+ self.tcx.get_diagnostic_item(sym::Into).unwrap(),
+ [f_err, e_err],
+ self.param_env,
+ )
+ .must_apply_modulo_regions()
{
err.multipart_suggestion(
"use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index afa5a3b9379ea..b5a07f0d3e9ec 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{
- self, AdtKind, CanonicalUserType, GenericParamDefKind, Ty, TyCtxt, UserType,
+ self, AdtKind, CanonicalUserType, GenericParamDefKind, IsIdentity, Ty, TyCtxt, UserType,
};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef, UserArgs, UserSelfTy};
use rustc_session::lint;
@@ -207,6 +207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
debug!("fcx {}", self.tag());
+ // FIXME: is_identity being on `UserType` and not `Canonical` is awkward
if !canonical_user_type_annotation.is_identity() {
self.typeck_results
.borrow_mut()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 13aa6454bc363..ca7dc298de64f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -10,8 +10,8 @@ use rustc_hir::def::Res;
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
- AsyncCoroutineKind, CoroutineKind, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath,
- Stmt, StmtKind, TyKind, WherePredicate,
+ CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath, Stmt,
+ StmtKind, TyKind, WherePredicate,
};
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::traits::{self, StatementAsExpression};
@@ -536,7 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Coroutine(def_id, ..)
if matches!(
self.tcx.coroutine_kind(def_id),
- Some(CoroutineKind::Async(AsyncCoroutineKind::Closure))
+ Some(CoroutineKind::Async(CoroutineSource::Closure))
) =>
{
errors::SuggestBoxing::AsyncBody
@@ -1747,19 +1747,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
- let ty::Adt(adt, args) = found.kind() else { return false };
+ let ty::Adt(adt, args) = found.kind() else {
+ return false;
+ };
let ret_ty_matches = |diagnostic_item| {
- if let Some(ret_ty) = self
- .ret_coercion
- .as_ref()
- .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
- && let ty::Adt(kind, _) = ret_ty.kind()
- && self.tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
- {
- true
- } else {
- false
- }
+ let Some(sig) = self.body_fn_sig() else {
+ return false;
+ };
+ let ty::Adt(kind, _) = sig.output().kind() else {
+ return false;
+ };
+ self.tcx.is_diagnostic_item(diagnostic_item, kind.did())
};
// don't suggest anything like `Ok(ok_val).unwrap()` , `Some(some_val).unwrap()`,
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index bdae07a3946f5..dde138973b931 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -5,7 +5,6 @@
#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![cfg_attr(not(bootstrap), allow(internal_features))]
-#![feature(never_type)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
@@ -19,15 +18,11 @@ mod assert_dep_graph;
mod errors;
mod persist;
-use assert_dep_graph::assert_dep_graph;
pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir;
-pub use persist::delete_workproduct_files;
pub use persist::finalize_session_directory;
-pub use persist::garbage_collect_session_directories;
pub use persist::in_incr_comp_dir;
pub use persist::in_incr_comp_dir_sess;
pub use persist::load_query_result_cache;
-pub use persist::prepare_session_directory;
pub use persist::save_dep_graph;
pub use persist::save_work_product_index;
pub use persist::setup_dep_graph;
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index db8ea2bfe48aa..f56fb0d0534be 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -53,7 +53,7 @@
//! ## Synchronization
//!
//! There is some synchronization needed in order for the compiler to be able to
-//! determine whether a given private session directory is not in used any more.
+//! determine whether a given private session directory is not in use any more.
//! This is done by creating a lock file for each session directory and
//! locking it while the directory is still being used. Since file locks have
//! operating system support, we can rely on the lock being released if the
@@ -136,26 +136,29 @@ const QUERY_CACHE_FILENAME: &str = "query-cache.bin";
const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE;
/// Returns the path to a session's dependency graph.
-pub fn dep_graph_path(sess: &Session) -> PathBuf {
+pub(crate) fn dep_graph_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
}
+
/// Returns the path to a session's staging dependency graph.
///
/// On the difference between dep-graph and staging dep-graph,
/// see `build_dep_graph`.
-pub fn staging_dep_graph_path(sess: &Session) -> PathBuf {
+pub(crate) fn staging_dep_graph_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME)
}
-pub fn work_products_path(sess: &Session) -> PathBuf {
+
+pub(crate) fn work_products_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)
}
+
/// Returns the path to a session's query cache.
pub fn query_cache_path(sess: &Session) -> PathBuf {
in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME)
}
/// Locks a given session directory.
-pub fn lock_file_path(session_dir: &Path) -> PathBuf {
+fn lock_file_path(session_dir: &Path) -> PathBuf {
let crate_dir = session_dir.parent().unwrap();
let directory_name = session_dir.file_name().unwrap().to_string_lossy();
@@ -202,7 +205,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
/// The garbage collection will take care of it.
///
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
-pub fn prepare_session_directory(
+pub(crate) fn prepare_session_directory(
sess: &Session,
crate_name: Symbol,
stable_crate_id: StableCrateId,
@@ -373,7 +376,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option) {
let _ = garbage_collect_session_directories(sess);
}
-pub fn delete_all_session_dir_contents(sess: &Session) -> io::Result<()> {
+pub(crate) fn delete_all_session_dir_contents(sess: &Session) -> io::Result<()> {
let sess_dir_iterator = sess.incr_comp_session_dir().read_dir()?;
for entry in sess_dir_iterator {
let entry = entry?;
@@ -621,7 +624,7 @@ fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool {
}
/// Runs garbage collection for the current session.
-pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
+pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
debug!("garbage_collect_session_directories() - begin");
let session_directory = sess.incr_comp_session_dir();
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 2310d0b12ef0c..cbd55fe420563 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -1,4 +1,4 @@
-//! Code to save/load the dep-graph from files.
+//! Code to load the dep-graph from files.
use crate::errors;
use rustc_data_structures::memmap::Mmap;
diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs
index fdecaca5a2dc1..94c05f4a2c81e 100644
--- a/compiler/rustc_incremental/src/persist/mod.rs
+++ b/compiler/rustc_incremental/src/persist/mod.rs
@@ -11,14 +11,11 @@ mod save;
mod work_product;
pub use fs::finalize_session_directory;
-pub use fs::garbage_collect_session_directories;
pub use fs::in_incr_comp_dir;
pub use fs::in_incr_comp_dir_sess;
-pub use fs::prepare_session_directory;
pub use load::load_query_result_cache;
pub use load::setup_dep_graph;
pub use load::LoadResult;
pub use save::save_dep_graph;
pub use save::save_work_product_index;
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;
-pub use work_product::delete_workproduct_files;
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 210da751d95e4..fa21320be263e 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -1,3 +1,4 @@
+use crate::assert_dep_graph::assert_dep_graph;
use crate::errors;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::join;
@@ -39,7 +40,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
let dep_graph_path = dep_graph_path(sess);
let staging_dep_graph_path = staging_dep_graph_path(sess);
- sess.time("assert_dep_graph", || crate::assert_dep_graph(tcx));
+ sess.time("assert_dep_graph", || assert_dep_graph(tcx));
sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx));
if sess.opts.unstable_opts.incremental_info {
diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs
index bce5ca1e16bd1..fb96bed5a7180 100644
--- a/compiler/rustc_incremental/src/persist/work_product.rs
+++ b/compiler/rustc_incremental/src/persist/work_product.rs
@@ -11,7 +11,8 @@ use rustc_session::Session;
use std::fs as std_fs;
use std::path::Path;
-/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it.
+/// Copies a CGU work product to the incremental compilation directory, so next compilation can
+/// find and reuse it.
pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
sess: &Session,
cgu_name: &str,
@@ -45,7 +46,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
}
/// Removes files for a given work product.
-pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
+pub(crate) fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
for (_, path) in work_product.saved_files.items().into_sorted_stable_ord() {
let path = in_incr_comp_dir_sess(sess, path);
if let Err(err) = std_fs::remove_file(&path) {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ba118f8110f31..e4be435fded30 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1584,14 +1584,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
target: &str,
types: &FxIndexMap>,
) {
- for (key, values) in types.iter() {
+ for (kind, values) in types.iter() {
let count = values.len();
- let kind = key.descr();
for &sp in values {
err.span_label(
sp,
format!(
- "{}{} {}{}",
+ "{}{} {:#}{}",
if count == 1 { "the " } else { "one of the " },
target,
kind,
@@ -2952,17 +2951,19 @@ pub enum TyCategory {
Foreign,
}
-impl TyCategory {
- fn descr(&self) -> &'static str {
+impl fmt::Display for TyCategory {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Self::Closure => "closure",
- Self::Opaque => "opaque type",
- Self::OpaqueFuture => "future",
- Self::Coroutine(gk) => gk.descr(),
- Self::Foreign => "foreign type",
+ Self::Closure => "closure".fmt(f),
+ Self::Opaque => "opaque type".fmt(f),
+ Self::OpaqueFuture => "future".fmt(f),
+ Self::Coroutine(gk) => gk.fmt(f),
+ Self::Foreign => "foreign type".fmt(f),
}
}
+}
+impl TyCategory {
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
match *ty.kind() {
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 00289f9bfb411..a8ae43d52978d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -54,13 +54,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
(ty::Param(expected), ty::Param(found)) => {
let generics = tcx.generics_of(body_owner_def_id);
- let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
- if !sp.contains(e_span) {
- diag.span_label(e_span, "expected type parameter");
+ if let Some(param) = generics.opt_type_param(expected, tcx) {
+ let e_span = tcx.def_span(param.def_id);
+ if !sp.contains(e_span) {
+ diag.span_label(e_span, "expected type parameter");
+ }
}
- let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
- if !sp.contains(f_span) {
- diag.span_label(f_span, "found type parameter");
+ if let Some(param) = generics.opt_type_param(found, tcx) {
+ let f_span = tcx.def_span(param.def_id);
+ if !sp.contains(f_span) {
+ diag.span_label(f_span, "found type parameter");
+ }
}
diag.note(
"a type parameter was expected, but a different one was found; \
@@ -83,23 +87,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
| (ty::Alias(ty::Projection, proj), ty::Param(p))
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
{
- let p_def_id = tcx.generics_of(body_owner_def_id).type_param(p, tcx).def_id;
- let p_span = tcx.def_span(p_def_id);
- let expected = match (values.expected.kind(), values.found.kind()) {
- (ty::Param(_), _) => "expected ",
- (_, ty::Param(_)) => "found ",
- _ => "",
- };
- if !sp.contains(p_span) {
- diag.span_label(p_span, format!("{expected}this type parameter"));
- }
- let hir = tcx.hir();
+ let parent = tcx.generics_of(body_owner_def_id)
+ .opt_type_param(p, tcx)
+ .and_then(|param| {
+ let p_def_id = param.def_id;
+ let p_span = tcx.def_span(p_def_id);
+ let expected = match (values.expected.kind(), values.found.kind()) {
+ (ty::Param(_), _) => "expected ",
+ (_, ty::Param(_)) => "found ",
+ _ => "",
+ };
+ if !sp.contains(p_span) {
+ diag.span_label(
+ p_span,
+ format!("{expected}this type parameter"),
+ );
+ }
+ p_def_id.as_local().and_then(|id| {
+ let local_id = tcx.hir().local_def_id_to_hir_id(id);
+ let generics = tcx.hir().find_parent(local_id)?.generics()?;
+ Some((id, generics))
+ })
+ });
let mut note = true;
- let parent = p_def_id.as_local().and_then(|id| {
- let local_id = hir.local_def_id_to_hir_id(id);
- let generics = tcx.hir().find_parent(local_id)?.generics()?;
- Some((id, generics))
- });
if let Some((local_id, generics)) = parent {
// Synthesize the associated type restriction `Add