diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 841bc39bf1e6f..674b6ccf34f95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,6 @@ name: CI on: push: branches: - # CI on master only serves for caching citool builds for the `calculate_matrix` job. - # In order to use GHA cache on PR CI (and auto/try) jobs, we need to write to it - # from the default branch. - - master - auto - try - try-perf @@ -57,13 +53,6 @@ jobs: steps: - name: Checkout the source code uses: actions/checkout@v4 - # Cache citool to make its build faster, as it's in the critical path. - # The rust-cache doesn't bleed into the main `job`, so it should not affect any other - # Rust compilation. - - name: Cache citool - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8 - with: - workspaces: src/ci/citool - name: Test citool # Only test citool on the auto branch, to reduce latency of the calculate matrix job # on PR/try builds. diff --git a/RELEASES.md b/RELEASES.md index 8a6bb214d2d52..1ae221774dc9e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -54,23 +54,35 @@ Stabilized APIs --------------- - [`Cell::update`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.update) -- [`impl Default for *const T`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#impl-Default-for-*const+T) -- [`impl Default for *mut T`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#impl-Default-for-*mut+T) +- [`impl Default for *const T`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#impl-Default-for-*const+T) +- [`impl Default for *mut T`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#impl-Default-for-*mut+T) - [`HashMap::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.extract_if) - [`HashSet::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html#method.extract_if) +- [`hint::select_unpredictable`](https://doc.rust-lang.org/stable/std/hint/fn.select_unpredictable.html) - [`proc_macro::Span::line`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.line) - [`proc_macro::Span::column`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.column) - [`proc_macro::Span::start`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.start) - [`proc_macro::Span::end`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.end) - [`proc_macro::Span::file`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.file) - [`proc_macro::Span::local_file`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.local_file) +- [`<[T]>::as_chunks`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_chunks) +- [`<[T]>::as_chunks_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_chunks_mut) +- [`<[T]>::as_chunks_unchecked`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_chunks_unchecked) +- [`<[T]>::as_chunks_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_chunks_unchecked_mut) +- [`<[T]>::as_rchunks`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_rchunks) +- [`<[T]>::as_rchunks_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_rchunks_mut) +- [`mod ffi::c_str`](https://doc.rust-lang.org/stable/std/ffi/c_str/index.html) These previously stable APIs are now stable in const contexts: - [`NonNull::replace`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.replace) - [`<*mut T>::replace`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.replace) -- [`std::ptr::swap_nonoverlapping`](https://github.com/rust-lang/rust/pull/137280) -- [`Cell::{replace, get, get_mut, from_mut, as_slice_of_cells}`](https://github.com/rust-lang/rust/pull/137928) +- [`std::ptr::swap_nonoverlapping`](https://doc.rust-lang.org/stable/std/ptr/fn.swap_nonoverlapping.html) +- [`Cell::replace`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.replace) +- [`Cell::get`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.get) +- [`Cell::get_mut`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.get_mut) +- [`Cell::from_mut`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.from_mut) +- [`Cell::as_slice_of_cells`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.as_slice_of_cells) diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index dc3598bcc361e..d755afad59fb8 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -231,6 +231,14 @@ pub enum AttributeKind { /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html). DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol }, + /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute). + ExportName { + /// The name to export this item with. + /// It may not contain \0 bytes as it will be converted to a null-terminated string. + name: Symbol, + span: Span, + }, + /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index e41dd8bde8ff9..d4402f4e2e63d 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -22,6 +22,7 @@ impl AttributeKind { ConstStabilityIndirect => No, Deprecation { .. } => Yes, DocComment { .. } => Yes, + ExportName { .. } => Yes, Inline(..) => No, MacroTransparency(..) => Yes, Repr(..) => No, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 2bb27ede86055..39652335f5553 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -93,9 +93,12 @@ attr_parsing_naked_functions_incompatible_attribute = attribute incompatible with `#[unsafe(naked)]` .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` .naked_attribute = function marked with `#[unsafe(naked)]` here + attr_parsing_non_ident_feature = 'feature' is not an identifier +attr_parsing_null_on_export = `export_name` may not contain null characters + attr_parsing_repr_ident = meta item in `repr` must be an identifier diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index eadf8657a0fd6..5a849e79cc32d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol, sym}; use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::ArgParser; -use crate::session_diagnostics::NakedFunctionIncompatibleAttribute; +use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport}; pub(crate) struct OptimizeParser; @@ -59,6 +59,33 @@ impl SingleAttributeParser for ColdParser { } } +pub(crate) struct ExportNameParser; + +impl SingleAttributeParser for ExportNameParser { + const PATH: &[rustc_span::Symbol] = &[sym::export_name]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + let Some(name) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + if name.as_str().contains('\0') { + // `#[export_name = ...]` will be converted to a null-terminated string, + // so it may not contain any null characters. + cx.emit_err(NullOnExport { span: cx.attr_span }); + return None; + } + Some(AttributeKind::ExportName { name, span: cx.attr_span }) + } +} + #[derive(Default)] pub(crate) struct NakedParser { span: Option, diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 6ca5c64e0bc5d..83e3c75dedb4e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -16,7 +16,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; use crate::attributes::codegen_attrs::{ - ColdParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, + ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -117,6 +117,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 263b323e3eb1f..7cfce5799792a 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -445,6 +445,13 @@ pub(crate) struct MustUseIllFormedAttributeInput { pub suggestions: DiagArgValue, } +#[derive(Diagnostic)] +#[diag(attr_parsing_null_on_export, code = E0648)] +pub(crate) struct NullOnExport { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(attr_parsing_stability_outside_std, code = E0734)] pub(crate) struct StabilityOutsideStd { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d27e08573e037..a611557dc924f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -10,7 +10,7 @@ use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate}; -use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; +use rustc_infer::infer::{NllRegionVariableOrigin, SubregionOrigin}; use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; @@ -329,7 +329,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.infcx.tcx, type_test.generic_kind.to_ty(self.infcx.tcx), ); - let origin = RelateParamBound(type_test_span, generic_ty, None); + let origin = + SubregionOrigin::RelateParamBound(type_test_span, generic_ty, None); self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure( self.body.source.def_id().expect_local(), type_test_span, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 0a114467f4325..8ed552cfa4f00 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -3,7 +3,7 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; -use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; +use rustc_infer::infer::{InferCtxt, SubregionOrigin}; use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::bug; use rustc_middle::ty::{ @@ -172,7 +172,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ty::Region::new_var(tcx, universal_regions.implicit_region_bound()); // we don't actually use this for anything, but // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(self.span, t1, None); + let origin = SubregionOrigin::RelateParamBound(self.span, t1, None); TypeOutlives::new( &mut *self, tcx, diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 0c46e0c0c2204..99392ea19151c 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -66,10 +66,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Ty::new_tup(self.tcx(), user_provided_sig.inputs()), args.tupled_upvars_ty(), args.coroutine_captures_by_ref_ty(), - self.infcx - .next_region_var(RegionVariableOrigin::MiscVariable(self.body.span), || { - RegionCtxt::Unknown - }), + self.infcx.next_region_var(RegionVariableOrigin::Misc(self.body.span), || { + RegionCtxt::Unknown + }), ); let next_ty_var = || self.infcx.next_ty_var(self.body.span); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9b6dcfd17c62e..e37b5a33af82c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -16,7 +16,7 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::{ - BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, + BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, }; use rustc_infer::traits::PredicateObligations; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; @@ -794,7 +794,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; self.infcx.next_region_var( - BoundRegion( + RegionVariableOrigin::BoundRegion( term.source_info.span, br.kind, BoundRegionConversionTime::FnCall, diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index b2e86414d9024..6362d2edf8554 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -205,11 +205,6 @@ codegen_ssa_missing_features = add the missing features in a `target_feature` at codegen_ssa_missing_query_depgraph = found CGU-reuse attribute but `-Zquery-dep-graph` was not specified -codegen_ssa_mixed_export_name_and_no_mangle = `{$no_mangle_attr}` attribute may not be used in combination with `#[export_name]` - .label = `{$no_mangle_attr}` is ignored - .note = `#[export_name]` takes precedence - .suggestion = remove the `{$no_mangle_attr}` attribute - codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions @@ -230,8 +225,6 @@ codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't -codegen_ssa_null_on_export = `export_name` may not contain null characters - codegen_ssa_out_of_range_integer = integer value out of range .label = value must be between `0` and `255` diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 7bd27eb3ef1cd..94df5e8b361d7 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -9,7 +9,7 @@ use rustc_attr_data_structures::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; -use rustc_hir::{self as hir, HirId, LangItem, lang_items}; +use rustc_hir::{self as hir, LangItem, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; @@ -87,7 +87,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; - let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState::default(); for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` @@ -119,16 +118,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .max(); } AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, + AttributeKind::ExportName { name, .. } => { + codegen_fn_attrs.export_name = Some(*name); + } AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align), AttributeKind::NoMangle(attr_span) => { if tcx.opt_item_name(did.to_def_id()).is_some() { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; - mixed_export_name_no_mangle_lint_state.track_no_mangle( - *attr_span, - tcx.local_def_id_to_hir_id(did), - attr, - ); } else { tcx.dcx().emit_err(NoMangleNameless { span: *attr_span, @@ -223,17 +220,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::export_name => { - if let Some(s) = attr.value_str() { - if s.as_str().contains('\0') { - // `#[export_name = ...]` will be converted to a null-terminated string, - // so it may not contain any null characters. - tcx.dcx().emit_err(errors::NullOnExport { span: attr.span() }); - } - codegen_fn_attrs.export_name = Some(s); - mixed_export_name_no_mangle_lint_state.track_export_name(attr.span()); - } - } sym::target_feature => { let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else { tcx.dcx().span_delayed_bug(attr.span(), "target_feature applied to non-fn"); @@ -444,8 +430,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - mixed_export_name_no_mangle_lint_state.lint_if_mixed(tcx); - // Apply the minimum function alignment here, so that individual backends don't have to. codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); @@ -672,49 +656,6 @@ fn check_link_name_xor_ordinal( } } -#[derive(Default)] -struct MixedExportNameAndNoMangleState<'a> { - export_name: Option, - hir_id: Option, - no_mangle: Option, - no_mangle_attr: Option<&'a hir::Attribute>, -} - -impl<'a> MixedExportNameAndNoMangleState<'a> { - fn track_export_name(&mut self, span: Span) { - self.export_name = Some(span); - } - - fn track_no_mangle(&mut self, span: Span, hir_id: HirId, attr_name: &'a hir::Attribute) { - self.no_mangle = Some(span); - self.hir_id = Some(hir_id); - self.no_mangle_attr = Some(attr_name); - } - - /// Emit diagnostics if the lint condition is met. - fn lint_if_mixed(self, tcx: TyCtxt<'_>) { - if let Self { - export_name: Some(export_name), - no_mangle: Some(no_mangle), - hir_id: Some(hir_id), - no_mangle_attr: Some(_), - } = self - { - tcx.emit_node_span_lint( - lint::builtin::UNUSED_ATTRIBUTES, - hir_id, - no_mangle, - errors::MixedExportNameAndNoMangle { - no_mangle, - no_mangle_attr: "#[unsafe(no_mangle)]".to_string(), - export_name, - removal_span: no_mangle, - }, - ); - } - } -} - /// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)] /// macros. There are two forms. The pure one without args to mark primal functions (the functions /// being differentiated). The other form is #[rustc_autodiff(Mode, ActivityList)] on top of the diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index caac0f83f9d95..db536af0162f1 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -140,13 +140,6 @@ pub(crate) struct RequiresRustAbi { pub span: Span, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_null_on_export, code = E0648)] -pub(crate) struct NullOnExport { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_unsupported_instruction_set, code = E0779)] pub(crate) struct UnsupportedInstructionSet { @@ -1207,18 +1200,6 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> { #[diag(codegen_ssa_aix_strip_not_used)] pub(crate) struct AixStripNotUsed; -#[derive(LintDiagnostic)] -#[diag(codegen_ssa_mixed_export_name_and_no_mangle)] -pub(crate) struct MixedExportNameAndNoMangle { - #[label] - pub no_mangle: Span, - pub no_mangle_attr: String, - #[note] - pub export_name: Span, - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] - pub removal_span: Span, -} - #[derive(Diagnostic, Debug)] pub(crate) enum XcrunError { #[diag(codegen_ssa_xcrun_failed_invoking)] diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 7f9abe8aa8e72..97b154ad14235 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -124,12 +124,13 @@ const_eval_incompatible_return_types = const_eval_incompatible_types = calling a function with argument of type {$callee_ty} passing data of type {$caller_ty} -const_eval_interior_mutable_ref_escaping = - {const_eval_const_context}s cannot refer to interior mutable data - .label = this borrow of an interior mutable value may end up in the final value +const_eval_interior_mutable_borrow_escaping = + interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed + .label = this borrow of an interior mutable value refers to a lifetime-extended temporary .help = to fix this, the value can be extracted to a separate `static` item and then referenced .teach_note = - References that escape into the final value of a constant or static must be immutable. + This creates a raw pointer to a temporary that has its lifetime extended to last for the entire program. + Lifetime-extended temporaries in constants and statics must be immutable. This is to avoid accidentally creating shared mutable state. @@ -207,33 +208,23 @@ const_eval_long_running = .label = the const evaluator is currently interpreting this expression .help = the constant being evaluated -const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id} - const_eval_memory_exhausted = tried to allocate more memory than available to compiler const_eval_modified_global = modifying a static's initial value from another static's initializer -const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} - -const_eval_mutable_raw_escaping = - raw mutable pointers are not allowed in the final value of {const_eval_const_context}s +const_eval_mutable_borrow_escaping = + mutable borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed .teach_note = - Pointers that escape into the final value of a constant or static must be immutable. + This creates a reference to a temporary that has its lifetime extended to last for the entire program. + Lifetime-extended temporaries in constants and statics must be immutable. This is to avoid accidentally creating shared mutable state. If you really want global mutable state, try using an interior mutable `static` or a `static mut`. -const_eval_mutable_ref_escaping = - mutable references are not allowed in the final value of {const_eval_const_context}s - .teach_note = - References that escape into the final value of a constant or static must be immutable. - This is to avoid accidentally creating shared mutable state. - - - If you really want global mutable state, try using an interior mutable `static` or a `static mut`. +const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead @@ -437,9 +428,6 @@ const_eval_unwind_past_top = ## (We'd love to sort this differently to make that more clear but tidy won't let us...) const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty} -const_eval_validation_const_ref_to_extern = {$front_matter}: encountered reference to `extern` static in `const` -const_eval_validation_const_ref_to_mutable = {$front_matter}: encountered reference to mutable memory in `const` - const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance) const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation) const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free) @@ -479,6 +467,7 @@ const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid re const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}` +const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in `const` value const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!` const_eval_validation_null_box = {$front_matter}: encountered a null box diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 576b174369d46..c151e8acf9229 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -595,11 +595,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut); if !is_allowed && self.place_may_escape(place) { - self.check_op(ops::EscapingMutBorrow(if matches!(rvalue, Rvalue::Ref(..)) { - hir::BorrowKind::Ref - } else { - hir::BorrowKind::Raw - })); + self.check_op(ops::EscapingMutBorrow); } } diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index f5b7a6066c8b7..02edff8f63294 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -567,7 +567,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow { DiagImportance::Secondary } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - ccx.dcx().create_err(errors::InteriorMutableRefEscaping { + ccx.dcx().create_err(errors::InteriorMutableBorrowEscaping { span, opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)), kind: ccx.const_kind(), @@ -580,7 +580,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow { /// This op is for `&mut` borrows in the trailing expression of a constant /// which uses the "enclosing scopes rule" to leak its locals into anonymous /// static or const items. -pub(crate) struct EscapingMutBorrow(pub hir::BorrowKind); +pub(crate) struct EscapingMutBorrow; impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { @@ -594,20 +594,11 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - match self.0 { - hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping { - span, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0764), - }), - hir::BorrowKind::Ref | hir::BorrowKind::Pin => { - ccx.dcx().create_err(errors::MutableRefEscaping { - span, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0764), - }) - } - } + ccx.dcx().create_err(errors::MutableBorrowEscaping { + span, + kind: ccx.const_kind(), + teach: ccx.tcx.sess.teach(E0764), + }) } } diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 6fd0b9d26e393..73cb1e774361d 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -26,13 +26,6 @@ pub(crate) use self::valtrees::{eval_to_valtree, valtree_to_const_value}; // We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes. const VALTREE_MAX_NODES: usize = 100000; -pub(crate) enum ValTreeCreationError<'tcx> { - NodesOverflow, - /// Values of this type, or this particular value, are not supported as valtrees. - NonSupportedType(Ty<'tcx>), -} -pub(crate) type ValTreeCreationResult<'tcx> = Result, ValTreeCreationError<'tcx>>; - #[instrument(skip(tcx), level = "debug")] pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 58d230af683ed..b3d2e1a0598e2 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,17 +1,16 @@ use rustc_abi::{BackendRepr, FieldIdx, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ReportedErrorInfo}; +use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; use tracing::{debug, instrument, trace}; +use super::VALTREE_MAX_NODES; use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const}; use super::machine::CompileTimeInterpCx; -use super::{VALTREE_MAX_NODES, ValTreeCreationError, ValTreeCreationResult}; use crate::const_eval::CanAccessMutGlobal; -use crate::errors::MaxNumNodesInConstErr; use crate::interpret::{ ImmTy, Immediate, InternKind, MPlaceTy, MemPlaceMeta, MemoryKind, PlaceTy, Projectable, Scalar, intern_const_alloc_recursive, @@ -24,7 +23,7 @@ fn branches<'tcx>( field_count: usize, variant: Option, num_nodes: &mut usize, -) -> ValTreeCreationResult<'tcx> { +) -> EvalToValTreeResult<'tcx> { let place = match variant { Some(variant) => ecx.project_downcast(place, variant).unwrap(), None => place.clone(), @@ -58,7 +57,7 @@ fn slice_branches<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, -) -> ValTreeCreationResult<'tcx> { +) -> EvalToValTreeResult<'tcx> { let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {place:?}")); let mut elems = Vec::with_capacity(n as usize); @@ -76,7 +75,7 @@ fn const_to_valtree_inner<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, -) -> ValTreeCreationResult<'tcx> { +) -> EvalToValTreeResult<'tcx> { let tcx = *ecx.tcx; let ty = place.layout.ty; debug!("ty kind: {:?}", ty.kind()); @@ -91,7 +90,7 @@ fn const_to_valtree_inner<'tcx>( Ok(ty::ValTree::zst(tcx)) } ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { - let val = ecx.read_immediate(place).unwrap(); + let val = ecx.read_immediate(place).report_err()?; let val = val.to_scalar_int().unwrap(); *num_nodes += 1; @@ -113,7 +112,7 @@ fn const_to_valtree_inner<'tcx>( // equality at compile-time (see `ptr_guaranteed_cmp`). // However we allow those that are just integers in disguise. // First, get the pointer. Remember it might be wide! - let val = ecx.read_immediate(place).unwrap(); + let val = ecx.read_immediate(place).report_err()?; // We could allow wide raw pointers where both sides are integers in the future, // but for now we reject them. if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) { @@ -134,7 +133,7 @@ fn const_to_valtree_inner<'tcx>( ty::FnPtr(..) => Err(ValTreeCreationError::NonSupportedType(ty)), ty::Ref(_, _, _) => { - let derefd_place = ecx.deref_pointer(place).unwrap(); + let derefd_place = ecx.deref_pointer(place).report_err()?; const_to_valtree_inner(ecx, &derefd_place, num_nodes) } @@ -158,7 +157,7 @@ fn const_to_valtree_inner<'tcx>( bug!("uninhabited types should have errored and never gotten converted to valtree") } - let variant = ecx.read_discriminant(place).unwrap(); + let variant = ecx.read_discriminant(place).report_err()?; branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes) } @@ -249,24 +248,7 @@ pub(crate) fn eval_to_valtree<'tcx>( debug!(?place); let mut num_nodes = 0; - let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes); - - match valtree_result { - Ok(valtree) => Ok(Ok(valtree)), - Err(err) => { - let did = cid.instance.def_id(); - let global_const_id = cid.display(tcx); - let span = tcx.hir_span_if_local(did); - match err { - ValTreeCreationError::NodesOverflow => { - let handled = - tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id }); - Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) - } - ValTreeCreationError::NonSupportedType(ty) => Ok(Err(ty)), - } - } - } + const_to_valtree_inner(&ecx, &place, &mut num_nodes) } /// Converts a `ValTree` to a `ConstValue`, which is needed after mir diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 609749554cece..b2c3103c34af6 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -92,14 +92,6 @@ pub(crate) struct PanicNonStrErr { pub span: Span, } -#[derive(Diagnostic)] -#[diag(const_eval_max_num_nodes_in_const)] -pub(crate) struct MaxNumNodesInConstErr { - #[primary_span] - pub span: Option, - pub global_const_id: String, -} - #[derive(Diagnostic)] #[diag(const_eval_unallowed_fn_pointer_call)] pub(crate) struct UnallowedFnPointerCall { @@ -158,8 +150,8 @@ pub(crate) struct UnmarkedIntrinsicExposed { } #[derive(Diagnostic)] -#[diag(const_eval_mutable_ref_escaping, code = E0764)] -pub(crate) struct MutableRefEscaping { +#[diag(const_eval_mutable_borrow_escaping, code = E0764)] +pub(crate) struct MutableBorrowEscaping { #[primary_span] pub span: Span, pub kind: ConstContext, @@ -167,15 +159,6 @@ pub(crate) struct MutableRefEscaping { pub teach: bool, } -#[derive(Diagnostic)] -#[diag(const_eval_mutable_raw_escaping, code = E0764)] -pub(crate) struct MutableRawEscaping { - #[primary_span] - pub span: Span, - pub kind: ConstContext, - #[note(const_eval_teach_note)] - pub teach: bool, -} #[derive(Diagnostic)] #[diag(const_eval_non_const_fmt_macro_call, code = E0015)] pub(crate) struct NonConstFmtMacroCall { @@ -233,8 +216,8 @@ pub(crate) struct UnallowedInlineAsm { } #[derive(Diagnostic)] -#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)] -pub(crate) struct InteriorMutableRefEscaping { +#[diag(const_eval_interior_mutable_borrow_escaping, code = E0492)] +pub(crate) struct InteriorMutableBorrowEscaping { #[primary_span] #[label] pub span: Span, @@ -655,9 +638,8 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { PointerAsInt { .. } => const_eval_validation_pointer_as_int, PartialPointer => const_eval_validation_partial_pointer, - ConstRefToMutable => const_eval_validation_const_ref_to_mutable, - ConstRefToExtern => const_eval_validation_const_ref_to_extern, MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable, + MutableRefInConst => const_eval_validation_mutable_ref_in_const, NullFnPtr => const_eval_validation_null_fn_ptr, NeverVal => const_eval_validation_never_val, NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range, @@ -815,9 +797,8 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { err.arg("expected_dyn_type", expected_dyn_type.to_string()); } NullPtr { .. } - | ConstRefToMutable - | ConstRefToExtern | MutableRefToImmutable + | MutableRefInConst | NullFnPtr | NeverVal | UnsafeCellInImmutable diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 7d76d925ef23e..7e26b7f3d9629 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -570,6 +570,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { }; let (size, _align) = global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env); + let alloc_actual_mutbl = + global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env); if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { @@ -597,9 +599,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { skip_recursive_check = !nested; } CtfeValidationMode::Const { .. } => { - // We can't recursively validate `extern static`, so we better reject them. - if self.ecx.tcx.is_foreign_item(did) { - throw_validation_failure!(self.path, ConstRefToExtern); + // If this is mutable memory or an `extern static`, there's no point in checking it -- we'd + // just get errors trying to read the value. + if alloc_actual_mutbl.is_mut() || self.ecx.tcx.is_foreign_item(did) + { + skip_recursive_check = true; } } } @@ -618,9 +622,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { mutbl } }; - // Determine what it actually points to. - let alloc_actual_mutbl = - global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env); // Mutable pointer to immutable memory is no good. if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not @@ -628,12 +629,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // This can actually occur with transmutes. throw_validation_failure!(self.path, MutableRefToImmutable); } - // In a const, everything must be completely immutable. + // In a const, any kind of mutable reference is not good. if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) { - if ptr_expected_mutbl == Mutability::Mut - || alloc_actual_mutbl == Mutability::Mut - { - throw_validation_failure!(self.path, ConstRefToMutable); + if ptr_expected_mutbl == Mutability::Mut { + throw_validation_failure!(self.path, MutableRefInConst); } } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 485dd1d220441..f08a24514964d 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -312,7 +312,7 @@ fn check_opaque_meets_bounds<'tcx>( // here rather than using ReErased. let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args); let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() { - ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)), + ty::ReErased => infcx.next_region_var(RegionVariableOrigin::Misc(span)), _ => re, }); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 47681a78ecca8..372a383fb39f7 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -9,7 +9,7 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; -use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ @@ -311,7 +311,7 @@ fn compare_method_predicate_entailment<'tcx>( let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars( impl_m_span, - infer::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity(), ); @@ -518,7 +518,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( param_env, infcx.instantiate_binder_with_fresh_vars( return_span, - infer::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity(), ), ); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d05e381f8c86b..00f9347b1cc81 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{AmbigArg, ItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt}; use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION; use rustc_macros::LintDiagnostic; use rustc_middle::mir::interpret::ErrorHandled; @@ -739,7 +739,7 @@ fn ty_known_to_outlive<'tcx>( infcx.register_type_outlives_constraint_inner(infer::TypeOutlivesConstraint { sub_region: region, sup_type: ty, - origin: infer::RelateParamBound(DUMMY_SP, ty, None), + origin: SubregionOrigin::RelateParamBound(DUMMY_SP, ty, None), }); }) } @@ -755,7 +755,11 @@ fn region_known_to_outlive<'tcx>( region_b: ty::Region<'tcx>, ) -> bool { test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { - infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a); + infcx.sub_regions( + SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + region_b, + region_a, + ); }) } @@ -1491,7 +1495,9 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id ty::ConstKind::Unevaluated(uv) => { infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) } - ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(wfcx.param_env), + ty::ConstKind::Param(param_ct) => { + param_ct.find_const_ty_from_env(wfcx.param_env) + } }; let param_ty = tcx.type_of(param.def_id).instantiate_identity(); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 4779f4fb702b7..734c9c58c08a5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -10,7 +10,7 @@ use rustc_hir as hir; use rustc_hir::ItemKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt}; +use rustc_infer::infer::{self, RegionResolutionError, SubregionOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::print::PrintTraitRefExt as _; @@ -415,7 +415,7 @@ pub(crate) fn coerce_unsized_info<'tcx>( }; let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) { (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => { - infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); + infcx.sub_regions(SubregionOrigin::RelateObjectBound(span), r_b, r_a); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b }; check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty)) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index f790c51f8f195..94f16977bd9d3 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem}; use rustc_hir_analysis::autoderef::Autoderef; -use rustc_infer::infer; +use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, @@ -219,7 +219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_sig = args.as_closure().sig(); let closure_sig = self.instantiate_binder_with_fresh_vars( call_expr.span, - infer::FnCall, + BoundRegionConversionTime::FnCall, closure_sig, ); let adjustments = self.adjust_steps(autoderef); @@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_args = args.as_coroutine_closure(); let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars( call_expr.span, - infer::FnCall, + BoundRegionConversionTime::FnCall, closure_args.coroutine_closure_sig(), ); let tupled_upvars_ty = self.next_ty_var(callee_expr.span); @@ -545,7 +545,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // renormalize the associated types at this point, since they // previously appeared within a `Binder<>` and hence would not // have been normalized before. - let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig); + let fn_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + BoundRegionConversionTime::FnCall, + fn_sig, + ); let fn_sig = self.normalize(call_expr.span, fn_sig); self.check_argument_types( diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index ac42eebf08c0d..612396858841f 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -58,7 +58,7 @@ pub(super) fn check_fn<'a, 'tcx>( let maybe_va_list = fn_sig.c_variadic.then(|| { let span = body.params.last().unwrap().span; let va_list_did = tcx.require_lang_item(LangItem::VaList, span); - let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span)); + let region = fcx.next_region_var(RegionVariableOrigin::Misc(span)); tcx.type_of(va_list_did).instantiate(tcx, &[region.into()]) }); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 0ce0bc313c770..83bd1e2cede55 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -44,7 +44,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::relate::RelateResult; -use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk, InferResult, RegionVariableOrigin}; use rustc_infer::traits::{ IfExpressionCause, ImplSource, MatchExpressionArmCause, Obligation, PredicateObligation, PredicateObligations, SelectionError, @@ -431,7 +431,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } else { if r_borrow_var.is_none() { // create var lazily, at most once - let coercion = Coercion(span); + let coercion = RegionVariableOrigin::Coercion(span); let r = self.next_region_var(coercion); r_borrow_var = Some(r); // [4] above } @@ -549,7 +549,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => { coerce_mutbls(mutbl_a, mutbl_b)?; - let coercion = Coercion(self.cause.span); + let coercion = RegionVariableOrigin::Coercion(self.cause.span); let r_borrow = self.next_region_var(coercion); // We don't allow two-phase borrows here, at least for initial @@ -672,7 +672,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return Err(TypeError::Mismatch); } } - Err(traits::Unimplemented) => { + Err(SelectionError::Unimplemented) => { debug!("coerce_unsized: early return - can't prove obligation"); return Err(TypeError::Mismatch); } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2bc9dadb6653b..b9f9b06e4d588 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -22,8 +22,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; use rustc_hir_analysis::NoVariantNamed; use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; -use rustc_infer::infer; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; +use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, RegionVariableOrigin}; use rustc_infer::traits::query::NoSolution; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -705,7 +704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this time with enough precision to check that the value // whose address was taken can actually be made to live as long // as it needs to live. - let region = self.next_region_var(infer::BorrowRegion(expr.span)); + let region = self.next_region_var(RegionVariableOrigin::BorrowRegion(expr.span)); match kind { hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl), hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 95c7f251c884c..c7b9cb470913c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -11,7 +11,7 @@ use rustc_hir::{ExprKind, HirId, LangItem, Node, QPath}; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants}; use rustc_index::IndexVec; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; @@ -30,7 +30,6 @@ use crate::TupleArgumentsFlag::*; use crate::coercion::CoerceMany; use crate::errors::SuggestPtrNullMut; use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; -use crate::fn_ctxt::infer::FnCall; use crate::gather_locals::Declaration; use crate::inline_asm::InlineAsmCtxt; use crate::method::probe::IsSuggestion; @@ -657,7 +656,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id); let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args); - self.instantiate_binder_with_fresh_vars(call_name.span, FnCall, fn_sig); + self.instantiate_binder_with_fresh_vars( + call_name.span, + BoundRegionConversionTime::FnCall, + fn_sig, + ); } None }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 8c18642e54a18..0c6226ce71e78 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -15,7 +15,7 @@ use rustc_hir::{self as hir, HirId, ItemLocalMap}; use rustc_hir_analysis::hir_ty_lowering::{ HirTyLowerer, InherentAssocCandidate, RegionInferReason, }; -use rustc_infer::infer; +use rustc_infer::infer::{self, RegionVariableOrigin}; use rustc_infer::traits::{DynCompatibilityViolation, Obligation}; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; @@ -244,8 +244,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { let v = match reason { - RegionInferReason::Param(def) => infer::RegionParameterDefinition(span, def.name), - _ => infer::MiscVariable(span), + RegionInferReason::Param(def) => { + RegionVariableOrigin::RegionParameterDefinition(span, def.name) + } + _ => RegionVariableOrigin::Misc(span), }; self.next_region_var(v) } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 53b5dff9c6b50..9563cf734f687 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -9,7 +9,9 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ use rustc_hir_analysis::hir_ty_lowering::{ FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, }; -use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; +use rustc_infer::infer::{ + BoundRegionConversionTime, DefineOpaqueTypes, InferOk, RegionVariableOrigin, +}; use rustc_lint::builtin::SUPERTRAIT_ITEM_SHADOWING_USAGE; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::{ @@ -194,7 +196,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { match pick.autoref_or_ptr_adjustment { Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => { - let region = self.next_region_var(infer::Autoref(self.span)); + let region = self.next_region_var(RegionVariableOrigin::Autoref(self.span)); // Type we're wrapping in a reference, used later for unsizing let base_ty = target; @@ -239,7 +241,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => { - let region = self.next_region_var(infer::Autoref(self.span)); + let region = self.next_region_var(RegionVariableOrigin::Autoref(self.span)); target = match target.kind() { ty::Adt(pin, args) if self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => { @@ -752,6 +754,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { where T: TypeFoldable> + Copy, { - self.fcx.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, value) + self.fcx.instantiate_binder_with_fresh_vars( + self.span, + BoundRegionConversionTime::FnCall, + value, + ) } } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 34bbb7d7c05e6..085e7a2f5df14 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -11,7 +11,7 @@ use rustc_errors::{Applicability, Diag, SubdiagMessage}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; -use rustc_infer::infer::{self, InferOk}; +use rustc_infer::infer::{BoundRegionConversionTime, InferOk}; use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; @@ -400,8 +400,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // function signature so that normalization does not need to deal // with bound regions. let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args); - let fn_sig = - self.instantiate_binder_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig); + let fn_sig = self.instantiate_binder_with_fresh_vars( + obligation.cause.span, + BoundRegionConversionTime::FnCall, + fn_sig, + ); let InferOk { value: fn_sig, obligations: o } = self.at(&obligation.cause, self.param_env).normalize(fn_sig); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 589dbb531168b..be0eb13cace67 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -12,7 +12,7 @@ use rustc_hir::HirId; use rustc_hir::def::DefKind; use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; -use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::middle::stability; use rustc_middle::query::Providers; @@ -995,7 +995,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ty::AssocKind::Fn { .. } => self.probe(|_| { let args = self.fresh_args_for_item(self.span, method.def_id); let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args); - let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty); + let fty = self.instantiate_binder_with_fresh_vars( + self.span, + BoundRegionConversionTime::FnCall, + fty, + ); self.can_eq(self.param_env, fty.output(), expected) }), _ => false, @@ -1756,8 +1760,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { - let trait_ref = - self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, trait_ref); + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + BoundRegionConversionTime::FnCall, + trait_ref, + ); let (xform_self_ty, _) = self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args); // Guide the trait selection to show impls that have methods whose type matches @@ -1873,7 +1880,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let trait_ref = self.instantiate_binder_with_fresh_vars( self.span, - infer::FnCall, + BoundRegionConversionTime::FnCall, poly_trait_ref, ); let trait_ref = ocx.normalize(cause, self.param_env, trait_ref); @@ -1936,7 +1943,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => { let trait_ref = self.instantiate_binder_with_fresh_vars( self.span, - infer::FnCall, + BoundRegionConversionTime::FnCall, poly_trait_ref, ); (xform_self_ty, xform_ret_ty) = diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b35aef13c5255..d0a48872f759c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -22,7 +22,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath}; -use rustc_infer::infer::{self, RegionVariableOrigin}; +use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin}; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; use rustc_middle::ty::print::{ @@ -1951,7 +1951,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if def_kind == DefKind::AssocFn { let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id); let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args); - let fn_sig = self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig); + let fn_sig = self.instantiate_binder_with_fresh_vars( + span, + BoundRegionConversionTime::FnCall, + fn_sig, + ); if similar_candidate.is_method() { if let Some(args) = args && fn_sig.inputs()[1..].len() == args.len() @@ -2033,7 +2037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.fn_sig(inherent_method.def_id).instantiate(self.tcx, args); let fn_sig = self.instantiate_binder_with_fresh_vars( item_name.span, - infer::FnCall, + BoundRegionConversionTime::FnCall, fn_sig, ); let name = inherent_method.name(); @@ -2348,9 +2352,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !arg.is_suggestable(self.tcx, true) { has_unsuggestable_args = true; match arg.kind() { - GenericArgKind::Lifetime(_) => self - .next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) - .into(), + GenericArgKind::Lifetime(_) => { + self.next_region_var(RegionVariableOrigin::Misc(DUMMY_SP)).into() + } GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(), GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(), } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 432eeae8016cc..349e72090d3ea 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -16,7 +16,7 @@ use rustc_hir::{ PatExprKind, PatKind, expr_needs_parens, }; use rustc_hir_analysis::autoderef::report_autoderef_recursion_limit_error; -use rustc_infer::infer; +use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; @@ -2777,7 +2777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Create a reference type with a fresh region variable. fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx> { - let region = self.next_region_var(infer::PatternRegion(span)); + let region = self.next_region_var(RegionVariableOrigin::PatternRegion(span)); Ty::new_ref(self.tcx, region, ty, mutbl) } diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 5dffedc709968..79a2aa54ef834 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -128,10 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { } CanonicalVarKind::Region(ui) => self - .next_region_var_in_universe( - RegionVariableOrigin::MiscVariable(span), - universe_map(ui), - ) + .next_region_var_in_universe(RegionVariableOrigin::Misc(span), universe_map(ui)) .into(), CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => { diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index f7c702d321b21..bb9c88500936f 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -141,7 +141,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn next_region_infer(&self) -> ty::Region<'tcx> { - self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) + self.next_region_var(RegionVariableOrigin::Misc(DUMMY_SP)) } fn next_ty_infer(&self) -> Ty<'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e9b58eb959bda..bfec0d12485eb 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,9 +1,6 @@ use std::cell::{Cell, RefCell}; use std::fmt; -pub use BoundRegionConversionTime::*; -pub use RegionVariableOrigin::*; -pub use SubregionOrigin::*; pub use at::DefineOpaqueTypes; use free_regions::RegionRelations; pub use freshen::TypeFreshener; @@ -403,7 +400,7 @@ pub enum RegionVariableOrigin { /// Region variables created for ill-categorized reasons. /// /// They mostly indicate places in need of refactoring. - MiscVariable(Span), + Misc(Span), /// Regions created by a `&P` or `[...]` pattern. PatternRegion(Span), @@ -467,21 +464,19 @@ pub struct FixupError { impl fmt::Display for FixupError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use TyOrConstInferVar::*; - match self.unresolved { - TyInt(_) => write!( + TyOrConstInferVar::TyInt(_) => write!( f, "cannot determine the type of this integer; \ add a suffix to specify the type explicitly" ), - TyFloat(_) => write!( + TyOrConstInferVar::TyFloat(_) => write!( f, "cannot determine the type of this number; \ add a suffix to specify the type explicitly" ), - Ty(_) => write!(f, "unconstrained type"), - Const(_) => write!(f, "unconstrained const value"), + TyOrConstInferVar::Ty(_) => write!(f, "unconstrained type"), + TyOrConstInferVar::Const(_) => write!(f, "unconstrained const value"), } } } @@ -865,7 +860,10 @@ impl<'tcx> InferCtxt<'tcx> { GenericParamDefKind::Lifetime => { // Create a region inference variable for the given // region parameter definition. - self.next_region_var(RegionParameterDefinition(span, param.name)).into() + self.next_region_var(RegionVariableOrigin::RegionParameterDefinition( + span, param.name, + )) + .into() } GenericParamDefKind::Type { .. } => { // Create a type inference variable for the given @@ -1172,7 +1170,7 @@ impl<'tcx> InferCtxt<'tcx> { let arg: ty::GenericArg<'_> = match bound_var_kind { ty::BoundVariableKind::Ty(_) => self.next_ty_var(span).into(), ty::BoundVariableKind::Region(br) => { - self.next_region_var(BoundRegion(span, br, lbrct)).into() + self.next_region_var(RegionVariableOrigin::BoundRegion(span, br, lbrct)).into() } ty::BoundVariableKind::Const => self.next_const_var(span).into(), }; @@ -1472,15 +1470,15 @@ impl<'tcx> TypeTrace<'tcx> { impl<'tcx> SubregionOrigin<'tcx> { pub fn span(&self) -> Span { match *self { - Subtype(ref a) => a.span(), - RelateObjectBound(a) => a, - RelateParamBound(a, ..) => a, - RelateRegionParamBound(a, _) => a, - Reborrow(a) => a, - ReferenceOutlivesReferent(_, a) => a, - CompareImplItemObligation { span, .. } => span, - AscribeUserTypeProvePredicate(span) => span, - CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), + SubregionOrigin::Subtype(ref a) => a.span(), + SubregionOrigin::RelateObjectBound(a) => a, + SubregionOrigin::RelateParamBound(a, ..) => a, + SubregionOrigin::RelateRegionParamBound(a, _) => a, + SubregionOrigin::Reborrow(a) => a, + SubregionOrigin::ReferenceOutlivesReferent(_, a) => a, + SubregionOrigin::CompareImplItemObligation { span, .. } => span, + SubregionOrigin::AscribeUserTypeProvePredicate(span) => span, + SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), } } @@ -1528,15 +1526,15 @@ impl<'tcx> SubregionOrigin<'tcx> { impl RegionVariableOrigin { pub fn span(&self) -> Span { match *self { - MiscVariable(a) - | PatternRegion(a) - | BorrowRegion(a) - | Autoref(a) - | Coercion(a) - | RegionParameterDefinition(a, ..) - | BoundRegion(a, ..) - | UpvarRegion(_, a) => a, - Nll(..) => bug!("NLL variable used with `span`"), + RegionVariableOrigin::Misc(a) + | RegionVariableOrigin::PatternRegion(a) + | RegionVariableOrigin::BorrowRegion(a) + | RegionVariableOrigin::Autoref(a) + | RegionVariableOrigin::Coercion(a) + | RegionVariableOrigin::RegionParameterDefinition(a, ..) + | RegionVariableOrigin::BoundRegion(a, ..) + | RegionVariableOrigin::UpvarRegion(_, a) => a, + RegionVariableOrigin::Nll(..) => bug!("NLL variable used with `span`"), } } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 220d5e9bda2d1..220e025c3f7d6 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -262,9 +262,7 @@ impl<'tcx> InferCtxt<'tcx> { .type_of_opaque_hir_typeck(opaque_type_key.def_id) .instantiate(self.tcx, opaque_type_key.args); let actual = ty::fold_regions(tcx, actual, |re, _dbi| match re.kind() { - ty::ReErased => { - self.next_region_var(RegionVariableOrigin::MiscVariable(span)) - } + ty::ReErased => self.next_region_var(RegionVariableOrigin::Misc(span)), _ => re, }); actual diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index db937b3e83eb4..f272052aaa544 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -141,7 +141,7 @@ impl<'tcx> InferCtxt<'tcx> { debug!(?sup_type, ?sub_region, ?cause); let origin = SubregionOrigin::from_obligation_cause(cause, || { - infer::RelateParamBound( + SubregionOrigin::RelateParamBound( cause.span, sup_type, match cause.code().peel_derives() { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 40e2e654b2ea7..f4cb73685d52d 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -14,7 +14,7 @@ use tracing::{debug, instrument}; use self::CombineMapType::*; use self::UndoLog::*; -use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin}; +use super::{RegionVariableOrigin, Rollback, SubregionOrigin}; use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot}; use crate::infer::unify_key::{RegionVariableValue, RegionVidKey}; @@ -580,7 +580,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { let a_universe = self.universe(a); let b_universe = self.universe(b); let c_universe = cmp::max(a_universe, b_universe); - let c = self.new_region_var(c_universe, MiscVariable(origin.span())); + let c = self.new_region_var(c_universe, RegionVariableOrigin::Misc(origin.span())); self.combine_map(t).insert(vars, c); self.undo_log.push(AddCombination(t, vars)); let new_r = ty::Region::new_var(tcx, c); diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 0e17b100276a2..9e451f16a9d8b 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -603,10 +603,9 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { } } - Ok(self.infcx.next_region_var_in_universe( - RegionVariableOrigin::MiscVariable(self.span), - self.for_universe, - )) + Ok(self + .infcx + .next_region_var_in_universe(RegionVariableOrigin::Misc(self.span), self.for_universe)) } #[instrument(level = "debug", skip(self, c2), ret)] diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index a95f24b5b95d0..13df23a39b967 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -5,6 +5,7 @@ use rustc_middle::ty::{ }; use super::{FixupError, FixupResult, InferCtxt}; +use crate::infer::TyOrConstInferVar; /////////////////////////////////////////////////////////////////////////// // OPPORTUNISTIC VAR RESOLVER @@ -144,13 +145,17 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { if !t.has_infer() { Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { - use super::TyOrConstInferVar::*; - let t = self.infcx.shallow_resolve(t); match *t.kind() { - ty::Infer(ty::TyVar(vid)) => Err(FixupError { unresolved: Ty(vid) }), - ty::Infer(ty::IntVar(vid)) => Err(FixupError { unresolved: TyInt(vid) }), - ty::Infer(ty::FloatVar(vid)) => Err(FixupError { unresolved: TyFloat(vid) }), + ty::Infer(ty::TyVar(vid)) => { + Err(FixupError { unresolved: TyOrConstInferVar::Ty(vid) }) + } + ty::Infer(ty::IntVar(vid)) => { + Err(FixupError { unresolved: TyOrConstInferVar::TyInt(vid) }) + } + ty::Infer(ty::FloatVar(vid)) => { + Err(FixupError { unresolved: TyOrConstInferVar::TyFloat(vid) }) + } ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); } diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 9e51a53ae95fa..9a66bd0574c9d 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -19,7 +19,8 @@ pub enum ScrubbedTraitError<'tcx> { TrueError, /// An ambiguity. This goal may hold if further inference is done. Ambiguity, - /// An old-solver-style cycle error, which will fatal. + /// An old-solver-style cycle error, which will fatal. This is not + /// returned by the new solver. Cycle(PredicateObligations<'tcx>), } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 6d5ad96e31c90..79a4859f286fb 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -20,8 +20,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::Span; use thin_vec::ThinVec; -pub use self::ImplSource::*; -pub use self::SelectionError::*; pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine}; pub(crate) use self::project::UndoLog; pub use self::project::{ diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5bbe69c8d65dc..172f3372483ae 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -977,9 +977,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { }; match it.kind { hir::ItemKind::Fn { generics, .. } => { - if let Some(attr_span) = attr::find_by_name(attrs, sym::export_name) - .map(|at| at.span()) - .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span)) + if let Some(attr_span) = + find_attr!(attrs, AttributeKind::ExportName {span, ..} => *span) + .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span)) { check_no_mangle_on_generic_fn(attr_span, None, generics, it.span); } @@ -1010,9 +1010,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { for it in *items { if let hir::AssocItemKind::Fn { .. } = it.kind { let attrs = cx.tcx.hir_attrs(it.id.hir_id()); - if let Some(attr_span) = attr::find_by_name(attrs, sym::export_name) - .map(|at| at.span()) - .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span)) + if let Some(attr_span) = + find_attr!(attrs, AttributeKind::ExportName {span, ..} => *span) + .or_else( + || find_attr!(attrs, AttributeKind::NoMangle(span) => *span), + ) { check_no_mangle_on_generic_fn( attr_span, diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 3d27e587b6cb4..0073deb18da29 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -78,6 +78,11 @@ middle_erroneous_constant = erroneous constant encountered middle_failed_writing_file = failed to write file {$path}: {$error}" +# Note: We only mention patterns here since the error can only occur with references, and those +# are forbidden in const generics. +middle_invalid_const_in_valtree = constant {$global_const_id} cannot be used as pattern + .note = constants that reference mutable or external memory cannot be used as pattern + middle_layout_cycle = a cycle occurred during layout computation @@ -95,6 +100,8 @@ middle_layout_too_generic = the type `{$ty}` does not have a fixed layout middle_layout_unknown = the type `{$ty}` has an unknown layout +middle_max_num_nodes_in_valtree = maximum number of nodes exceeded in constant {$global_const_id} + middle_opaque_hidden_type_mismatch = concrete type differs from previous defining opaque type use .label = expected `{$self_ty}`, got `{$other_ty}` diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 6c6b12fed674f..f36ae83165319 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -170,3 +170,20 @@ pub(crate) struct TypeLengthLimit { pub path: PathBuf, pub type_length: usize, } + +#[derive(Diagnostic)] +#[diag(middle_max_num_nodes_in_valtree)] +pub(crate) struct MaxNumNodesInValtree { + #[primary_span] + pub span: Span, + pub global_const_id: String, +} + +#[derive(Diagnostic)] +#[diag(middle_invalid_const_in_valtree)] +#[note] +pub(crate) struct InvalidConstInValtree { + #[primary_span] + pub span: Span, + pub global_const_id: String, +} diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 6ff3cac049b3a..41a166083d079 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -35,7 +35,7 @@ impl From for ErrorHandled { } impl ErrorHandled { - pub fn with_span(self, span: Span) -> Self { + pub(crate) fn with_span(self, span: Span) -> Self { match self { ErrorHandled::Reported(err, _span) => ErrorHandled::Reported(err, span), ErrorHandled::TooGeneric(_span) => ErrorHandled::TooGeneric(span), @@ -94,14 +94,51 @@ impl From for ErrorGuaranteed { } } +/// An error type for the `const_to_valtree` query. Some error should be reported with a "use-site span", +/// which means the query cannot emit the error, so those errors are represented as dedicated variants here. +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum ValTreeCreationError<'tcx> { + /// The constant is too big to be valtree'd. + NodesOverflow, + /// The constant references mutable or external memory, so it cannot be valtree'd. + InvalidConst, + /// Values of this type, or this particular value, are not supported as valtrees. + NonSupportedType(Ty<'tcx>), + /// The error has already been handled by const evaluation. + ErrorHandled(ErrorHandled), +} + +impl<'tcx> From for ValTreeCreationError<'tcx> { + fn from(err: ErrorHandled) -> Self { + ValTreeCreationError::ErrorHandled(err) + } +} + +impl<'tcx> From> for ValTreeCreationError<'tcx> { + fn from(err: InterpErrorInfo<'tcx>) -> Self { + // An error ocurred outside the const-eval query, as part of constructing the valtree. We + // don't currently preserve the details of this error, since `InterpErrorInfo` cannot be put + // into a query result and it can only be access of some mutable or external memory. + let (_kind, backtrace) = err.into_parts(); + backtrace.print_backtrace(); + ValTreeCreationError::InvalidConst + } +} + +impl<'tcx> ValTreeCreationError<'tcx> { + pub(crate) fn with_span(self, span: Span) -> Self { + use ValTreeCreationError::*; + match self { + ErrorHandled(handled) => ErrorHandled(handled.with_span(span)), + other => other, + } + } +} + pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled>; pub type EvalStaticInitializerRawResult<'tcx> = Result, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; -/// `Ok(Err(ty))` indicates the constant was fine, but the valtree couldn't be constructed -/// because the value contains something of type `ty` that is not valtree-compatible. -/// The caller can then show an appropriate error; the query does not have the -/// necessary context to give good user-facing errors for this case. -pub type EvalToValTreeResult<'tcx> = Result, Ty<'tcx>>, ErrorHandled>; +pub type EvalToValTreeResult<'tcx> = Result, ValTreeCreationError<'tcx>>; #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8); @@ -450,10 +487,9 @@ pub enum ValidationErrorKind<'tcx> { ptr_kind: PointerKind, ty: Ty<'tcx>, }, - ConstRefToMutable, - ConstRefToExtern, MutableRefToImmutable, UnsafeCellInImmutable, + MutableRefInConst, NullFnPtr, NeverVal, NullablePtrOutOfRange { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index c2438af6a1e19..ea2f84d46d7f7 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -38,8 +38,8 @@ pub use self::error::{ EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpErrorInfo, InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo, - ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo, - ValidationErrorKind, interp_ok, + ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValTreeCreationError, + ValidationErrorInfo, ValidationErrorKind, interp_ok, }; pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 97db45a70d7fe..e25f35c59c286 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -5,11 +5,11 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; use super::{ - ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId, - ReportedErrorInfo, + ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, GlobalId, ReportedErrorInfo, }; -use crate::mir; -use crate::ty::{self, GenericArgs, TyCtxt, TypeVisitableExt}; +use crate::mir::interpret::ValTreeCreationError; +use crate::ty::{self, ConstToValTreeResult, GenericArgs, TyCtxt, TypeVisitableExt}; +use crate::{error, mir}; impl<'tcx> TyCtxt<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts @@ -92,7 +92,7 @@ impl<'tcx> TyCtxt<'tcx> { typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, - ) -> EvalToValTreeResult<'tcx> { + ) -> ConstToValTreeResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference // variables. We reject those here since `resolve` // would fail otherwise. @@ -103,47 +103,54 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { - Ok(Some(instance)) => { - let cid = GlobalId { instance, promoted: None }; - self.const_eval_global_id_for_typeck(typing_env, cid, span).inspect(|_| { - // We are emitting the lint here instead of in `is_const_evaluatable` - // as we normalize obligations before checking them, and normalization - // uses this function to evaluate this constant. - // - // @lcnr believes that successfully evaluating even though there are - // used generic parameters is a bug of evaluation, so checking for it - // here does feel somewhat sensible. - if !self.features().generic_const_exprs() - && ct.args.has_non_region_param() - // We only FCW for anon consts as repeat expr counts with anon consts are the only place - // that we have a back compat hack for. We don't need to check this is a const argument - // as only anon consts as const args should get evaluated "for the type system". - // - // If we don't *only* FCW anon consts we can wind up incorrectly FCW'ing uses of assoc - // consts in pattern positions. #140447 - && self.def_kind(instance.def_id()) == DefKind::AnonConst - { - let mir_body = self.mir_for_ctfe(instance.def_id()); - if mir_body.is_polymorphic { - let Some(local_def_id) = ct.def.as_local() else { return }; - self.node_span_lint( - lint::builtin::CONST_EVALUATABLE_UNCHECKED, - self.local_def_id_to_hir_id(local_def_id), - self.def_span(ct.def), - |lint| { lint.primary_message("cannot use constants which depend on generic parameters in types"); }, - ) - } - } - }) - } + let cid = match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { + Ok(Some(instance)) => GlobalId { instance, promoted: None }, // For errors during resolution, we deliberately do not point at the usage site of the constant, // since for these errors the place the constant is used shouldn't matter. - Ok(None) => Err(ErrorHandled::TooGeneric(DUMMY_SP)), + Ok(None) => return Err(ErrorHandled::TooGeneric(DUMMY_SP).into()), Err(err) => { - Err(ErrorHandled::Reported(ReportedErrorInfo::non_const_eval_error(err), DUMMY_SP)) + return Err(ErrorHandled::Reported( + ReportedErrorInfo::non_const_eval_error(err), + DUMMY_SP, + ) + .into()); } - } + }; + + self.const_eval_global_id_for_typeck(typing_env, cid, span).inspect(|_| { + // We are emitting the lint here instead of in `is_const_evaluatable` + // as we normalize obligations before checking them, and normalization + // uses this function to evaluate this constant. + // + // @lcnr believes that successfully evaluating even though there are + // used generic parameters is a bug of evaluation, so checking for it + // here does feel somewhat sensible. + if !self.features().generic_const_exprs() + && ct.args.has_non_region_param() + // We only FCW for anon consts as repeat expr counts with anon consts are the only place + // that we have a back compat hack for. We don't need to check this is a const argument + // as only anon consts as const args should get evaluated "for the type system". + // + // If we don't *only* FCW anon consts we can wind up incorrectly FCW'ing uses of assoc + // consts in pattern positions. #140447 + && self.def_kind(cid.instance.def_id()) == DefKind::AnonConst + { + let mir_body = self.mir_for_ctfe(cid.instance.def_id()); + if mir_body.is_polymorphic { + let Some(local_def_id) = ct.def.as_local() else { return }; + self.node_span_lint( + lint::builtin::CONST_EVALUATABLE_UNCHECKED, + self.local_def_id_to_hir_id(local_def_id), + self.def_span(ct.def), + |lint| { + lint.primary_message( + "cannot use constants which depend on generic parameters in types", + ); + }, + ) + } + } + }) } pub fn const_eval_instance( @@ -182,17 +189,42 @@ impl<'tcx> TyCtxt<'tcx> { typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, span: Span, - ) -> EvalToValTreeResult<'tcx> { + ) -> ConstToValTreeResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.erase_regions(typing_env.with_post_analysis_normalized(self).as_query_input(cid)); debug!(?inputs); - if !span.is_dummy() { + let res = if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. self.at(span).eval_to_valtree(inputs).map_err(|e| e.with_span(span)) } else { self.eval_to_valtree(inputs) + }; + match res { + Ok(valtree) => Ok(Ok(valtree)), + Err(err) => { + match err { + // Let the caller decide how to handle this. + ValTreeCreationError::NonSupportedType(ty) => Ok(Err(ty)), + // Report the others. + ValTreeCreationError::NodesOverflow => { + let handled = self.dcx().emit_err(error::MaxNumNodesInValtree { + span, + global_const_id: cid.display(self), + }); + Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) + } + ValTreeCreationError::InvalidConst => { + let handled = self.dcx().emit_err(error::InvalidConstInValtree { + span, + global_const_id: cid.display(self), + }); + Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) + } + ValTreeCreationError::ErrorHandled(handled) => Err(handled), + } + } } } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 7c998761a9d44..26a31cb055ebe 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -4,6 +4,7 @@ use std::mem::MaybeUninit; use rustc_span::ErrorGuaranteed; +use crate::mir::interpret::EvalToValTreeResult; use crate::query::CyclePlaceholder; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; @@ -156,10 +157,8 @@ impl EraseType for Result, mir::interpret::ErrorHandled> { type Result = [u8; size_of::, mir::interpret::ErrorHandled>>()]; } -impl EraseType for Result, Ty<'_>>, mir::interpret::ErrorHandled> { - type Result = [u8; size_of::< - Result, Ty<'static>>, mir::interpret::ErrorHandled>, - >()]; +impl EraseType for EvalToValTreeResult<'_> { + type Result = [u8; size_of::>()]; } impl EraseType for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 2f21d19e03c70..d95006dcf4a62 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -5,7 +5,7 @@ use rustc_data_structures::intern::Interned; use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use super::ScalarInt; -use crate::mir::interpret::Scalar; +use crate::mir::interpret::{ErrorHandled, Scalar}; use crate::ty::{self, Ty, TyCtxt}; /// This datastructure is used to represent the value of constants used in the type system. @@ -124,6 +124,12 @@ impl fmt::Debug for ValTree<'_> { } } +/// `Ok(Err(ty))` indicates the constant was fine, but the valtree couldn't be constructed +/// because the value contains something of type `ty` that is not valtree-compatible. +/// The caller can then show an appropriate error; the query does not have the +/// necessary context to give good user-facing errors for this case. +pub type ConstToValTreeResult<'tcx> = Result, Ty<'tcx>>, ErrorHandled>; + /// A type-level constant value. /// /// Represents a typed, fully evaluated constant. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index aa5355551ce06..00e404a7098ef 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -698,14 +698,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.unsizing_params_for_adt(adt_def_id) } - fn find_const_ty_from_env( - self, - param_env: ty::ParamEnv<'tcx>, - placeholder: Self::PlaceholderConst, - ) -> Ty<'tcx> { - placeholder.find_const_ty_from_env(param_env) - } - fn anonymize_bound_vars>>( self, binder: ty::Binder<'tcx, T>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 97408e31854ae..8800afd79e717 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -75,8 +75,8 @@ pub use self::closure::{ place_to_string_for_capture, }; pub use self::consts::{ - AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, - UnevaluatedConst, ValTree, ValTreeKind, Value, + AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, + ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind, Value, }; pub use self::context::{ CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, @@ -907,30 +907,6 @@ pub struct Placeholder { pub universe: UniverseIndex, pub bound: T, } -impl Placeholder { - pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { - let mut candidates = env.caller_bounds().iter().filter_map(|clause| { - // `ConstArgHasType` are never desugared to be higher ranked. - match clause.kind().skip_binder() { - ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { - assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); - - match placeholder_ct.kind() { - ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { - Some(ty) - } - _ => None, - } - } - _ => None, - } - }); - - let ty = candidates.next().unwrap(); - assert!(candidates.next().is_none()); - ty - } -} pub type PlaceholderRegion = Placeholder; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 58829f72a72f0..83960847b261a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -346,7 +346,7 @@ impl ParamConst { } #[instrument(level = "debug")] - pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. match clause.kind().skip_binder() { @@ -362,8 +362,19 @@ impl ParamConst { } }); - let ty = candidates.next().unwrap(); - assert!(candidates.next().is_none()); + // N.B. it may be tempting to fix ICEs by making this function return + // `Option>` instead of `Ty<'tcx>`; however, this is generally + // considered to be a bandaid solution, since it hides more important + // underlying issues with how we construct generics and predicates of + // items. It's advised to fix the underlying issue rather than trying + // to modify this function. + let ty = candidates.next().unwrap_or_else(|| { + bug!("cannot find `{self:?}` in param-env: {env:#?}"); + }); + assert!( + candidates.next().is_none(), + "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}" + ); ty } } 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 f39d32260093c..4c649225359ab 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 @@ -326,11 +326,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable panic!("escaping bound vars in {:?}", ct), ty::ConstKind::Value(cv) => cv.ty(), ty::ConstKind::Placeholder(placeholder) => { - self.cx().find_const_ty_from_env(goal.param_env, placeholder) + placeholder.find_const_ty_from_env(goal.param_env) } }; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index f601d058b3301..e2995daadfe56 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -486,6 +486,11 @@ passes_missing_panic_handler = passes_missing_stability_attr = {$descr} has missing stability attribute +passes_mixed_export_name_and_no_mangle = `{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}` + .label = `{$no_mangle_attr}` is ignored + .note = `{$export_name_attr}` takes precedence + .suggestion = remove the `{$no_mangle_attr}` attribute + passes_multiple_rustc_main = multiple functions with a `#[rustc_main]` attribute .first = first `#[rustc_main]` function diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 99c220d946e5c..491b3699f4c32 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -30,11 +30,13 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; +use rustc_session::lint; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; +use rustc_span::edition::Edition; use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; @@ -169,6 +171,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::Cold(attr_span)) => { self.check_cold(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => { + self.check_export_name(hir_id, *attr_span, span, target) + } Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { self.check_align(span, target, *align, *repr_span) } @@ -223,7 +228,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &mut doc_aliases, ), [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), - [sym::export_name, ..] => self.check_export_name(hir_id, attr, span, target), [sym::rustc_layout_scalar_valid_range_start, ..] | [sym::rustc_layout_scalar_valid_range_end, ..] => { self.check_rustc_layout_scalar_valid_range(attr, span, target) @@ -401,6 +405,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_repr(attrs, span, target, item, hir_id); self.check_used(attrs, target, span); self.check_rustc_force_inline(hir_id, attrs, span, target); + self.check_mix_no_mangle_export(hir_id, attrs); } fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr_span: Span, sym: &str) { @@ -1653,7 +1658,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[export_name]` is applied to a function or static. - fn check_export_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_export_name(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Static | Target::Fn => {} Target::Method(..) if self.is_impl_item(hir_id) => {} @@ -1662,10 +1667,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "export_name"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "export_name"); } _ => { - self.dcx().emit_err(errors::ExportName { attr_span: attr.span(), span }); + self.dcx().emit_err(errors::ExportName { attr_span, span }); } } } @@ -2626,6 +2631,36 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + fn check_mix_no_mangle_export(&self, hir_id: HirId, attrs: &[Attribute]) { + if let Some(export_name_span) = find_attr!(attrs, AttributeKind::ExportName { span: export_name_span, .. } => *export_name_span) + && let Some(no_mangle_span) = + find_attr!(attrs, AttributeKind::NoMangle(no_mangle_span) => *no_mangle_span) + { + let no_mangle_attr = if no_mangle_span.edition() >= Edition::Edition2024 { + "#[unsafe(no_mangle)]" + } else { + "#[no_mangle]" + }; + let export_name_attr = if export_name_span.edition() >= Edition::Edition2024 { + "#[unsafe(export_name)]" + } else { + "#[export_name]" + }; + + self.tcx.emit_node_span_lint( + lint::builtin::UNUSED_ATTRIBUTES, + hir_id, + no_mangle_span, + errors::MixedExportNameAndNoMangle { + no_mangle_span, + export_name_span, + no_mangle_attr, + export_name_attr, + }, + ); + } + } + /// Checks if `#[autodiff]` is applied to an item other than a function item. fn check_autodiff(&self, _hir_id: HirId, _attr: &Attribute, span: Span, target: Target) { debug!("check_autodiff"); diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index d9ec167aae353..3286ccc94f210 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -49,6 +49,18 @@ pub(crate) struct ConstContinueAttr { pub node_span: Span, } +#[derive(LintDiagnostic)] +#[diag(passes_mixed_export_name_and_no_mangle)] +pub(crate) struct MixedExportNameAndNoMangle { + #[label] + #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + pub no_mangle_span: Span, + #[note] + pub export_name_span: Span, + pub no_mangle_attr: &'static str, + pub export_name_attr: &'static str, +} + #[derive(LintDiagnostic)] #[diag(passes_outer_crate_level_attr)] pub(crate) struct OuterCrateLevelAttr; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 11463ad354a96..368944ffd5cce 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1617,6 +1617,7 @@ symbols! { pie, pin, pin_ergonomics, + pin_macro, platform_intrinsics, plugin, plugin_registrar, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index bfef3340b323f..1db05ced8d2fb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -909,11 +909,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } (GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => { - use ty::InferConst::*; match (inner_ct.kind(), target_ct.kind()) { - (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => { - self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid) - } + ( + ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), + ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), + ) => self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid), _ => false, } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs index e456ba0eda5c3..c0b4bdab84945 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs @@ -5,7 +5,6 @@ use rustc_span::Span; use crate::error_reporting::TypeErrCtxt; use crate::infer::RegionResolutionError; -use crate::infer::RegionResolutionError::*; mod different_lifetimes; pub mod find_anon_type; @@ -83,8 +82,10 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { pub(super) fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { match (&self.error, self.regions) { - (Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), *sub, *sup)), - (Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => { + (Some(RegionResolutionError::ConcreteFailure(origin, sub, sup)), None) => { + Some((origin.span(), *sub, *sup)) + } + (Some(RegionResolutionError::SubSupConflict(_, _, origin, sub, _, sup, _)), None) => { Some((origin.span(), *sub, *sup)) } (None, Some((span, sub, sup))) => Some((span, sub, sup)), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index b66bd2c6ab787..f1237130c15ab 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -5,6 +5,7 @@ use rustc_hir::def::{Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{Visitor, walk_ty}; use rustc_hir::{self as hir, AmbigArg}; +use rustc_infer::infer::SubregionOrigin; use rustc_middle::hir::nested_filter; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::ExpectedFound; @@ -16,7 +17,7 @@ use tracing::debug; use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}; -use crate::infer::{RegionResolutionError, Subtype, ValuePairs}; +use crate::infer::{RegionResolutionError, ValuePairs}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. @@ -32,7 +33,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { _sup, _, ) = error.clone() - && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin) + && let (SubregionOrigin::Subtype(sup_trace), SubregionOrigin::Subtype(sub_trace)) = + (&sup_origin, &sub_origin) && let &ObligationCauseCode::CompareImplItem { trait_item_def_id, .. } = sub_trace.cause.code() && sub_trace.values == sup_trace.values diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 5c669678ccc0c..4fab67b01cb95 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -27,7 +27,10 @@ use crate::errors::{ }; use crate::fluent_generated as fluent; use crate::infer::region_constraints::GenericKind; -use crate::infer::{self, InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin}; +use crate::infer::{ + BoundRegionConversionTime, InferCtxt, RegionResolutionError, RegionVariableOrigin, + SubregionOrigin, +}; impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub fn report_region_errors( @@ -219,21 +222,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) { match *origin { - infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { + SubregionOrigin::Subtype(ref trace) => RegionOriginNote::WithRequirement { span: trace.cause.span, requirement: ObligationCauseAsDiagArg(trace.cause.clone()), expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()), } .add_to_diag(err), - infer::Reborrow(span) => { + SubregionOrigin::Reborrow(span) => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow } .add_to_diag(err) } - infer::RelateObjectBound(span) => { + SubregionOrigin::RelateObjectBound(span) => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound } .add_to_diag(err); } - infer::ReferenceOutlivesReferent(ty, span) => { + SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, msg: fluent::trait_selection_reference_outlives_referent, @@ -242,7 +245,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } .add_to_diag(err); } - infer::RelateParamBound(span, ty, opt_span) => { + SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, msg: fluent::trait_selection_relate_param_bound, @@ -258,24 +261,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err); } } - infer::RelateRegionParamBound(span, _) => { + SubregionOrigin::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_region_param_bound, } .add_to_diag(err); } - infer::CompareImplItemObligation { span, .. } => { + SubregionOrigin::CompareImplItemObligation { span, .. } => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_compare_impl_item_obligation, } .add_to_diag(err); } - infer::CheckAssociatedTypeBounds { ref parent, .. } => { + SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => { self.note_region_origin(err, parent); } - infer::AscribeUserTypeProvePredicate(span) => { + SubregionOrigin::AscribeUserTypeProvePredicate(span) => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_ascribe_user_type_prove_predicate, @@ -293,7 +296,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sup: Region<'tcx>, ) -> Diag<'a> { let mut err = match origin { - infer::Subtype(box trace) => { + SubregionOrigin::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let mut err = self.report_and_explain_type_error( trace, @@ -347,7 +350,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } err } - infer::Reborrow(span) => { + SubregionOrigin::Reborrow(span) => { let reference_valid = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -369,7 +372,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { notes: reference_valid.into_iter().chain(content_valid).collect(), }) } - infer::RelateObjectBound(span) => { + SubregionOrigin::RelateObjectBound(span) => { let object_valid = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -391,7 +394,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { notes: object_valid.into_iter().chain(pointer_valid).collect(), }) } - infer::RelateParamBound(span, ty, opt_span) => { + SubregionOrigin::RelateParamBound(span, ty, opt_span) => { let prefix = match sub.kind() { ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy, _ => note_and_explain::PrefixKind::TypeOutlive, @@ -415,7 +418,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note, }) } - infer::RelateRegionParamBound(span, ty) => { + SubregionOrigin::RelateRegionParamBound(span, ty) => { let param_instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -457,7 +460,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), }) } - infer::ReferenceOutlivesReferent(ty, span) => { + SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { let pointer_valid = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -480,7 +483,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { notes: pointer_valid.into_iter().chain(data_valid).collect(), }) } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { + SubregionOrigin::CompareImplItemObligation { + span, + impl_item_def_id, + trait_item_def_id, + } => { let mut err = self.report_extra_impl_obligation( span, impl_item_def_id, @@ -499,7 +506,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } err } - infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { + SubregionOrigin::CheckAssociatedTypeBounds { + impl_item_def_id, + trait_item_def_id, + parent, + } => { let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup); // Don't mention the item name if it's an RPITIT, since that'll just confuse @@ -520,7 +531,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); err } - infer::AscribeUserTypeProvePredicate(span) => { + SubregionOrigin::AscribeUserTypeProvePredicate(span) => { let instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -618,7 +629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // I can't think how to do better than this right now. -nikomatsakis debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); match placeholder_origin { - infer::Subtype(box ref trace) + SubregionOrigin::Subtype(box ref trace) if matches!( &trace.cause.code().peel_derives(), ObligationCauseCode::WhereClause(..) @@ -648,7 +659,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } } - infer::Subtype(box trace) => { + SubregionOrigin::Subtype(box trace) => { let terr = TypeError::RegionsPlaceholderMismatch; return self.report_and_explain_type_error( trace, @@ -945,8 +956,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); - if let infer::Subtype(ref sup_trace) = sup_origin - && let infer::Subtype(ref sub_trace) = sub_origin + if let SubregionOrigin::Subtype(ref sup_trace) = sup_origin + && let SubregionOrigin::Subtype(ref sub_trace) = sub_origin && let Some((sup_expected, sup_found)) = self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path()) && let Some((sub_expected, sub_found)) = @@ -1004,30 +1015,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { s }; let var_description = match var_origin { - infer::MiscVariable(_) => String::new(), - infer::PatternRegion(_) => " for pattern".to_string(), - infer::BorrowRegion(_) => " for borrow expression".to_string(), - infer::Autoref(_) => " for autoref".to_string(), - infer::Coercion(_) => " for automatic coercion".to_string(), - infer::BoundRegion(_, br, infer::FnCall) => { + RegionVariableOrigin::Misc(_) => String::new(), + RegionVariableOrigin::PatternRegion(_) => " for pattern".to_string(), + RegionVariableOrigin::BorrowRegion(_) => " for borrow expression".to_string(), + RegionVariableOrigin::Autoref(_) => " for autoref".to_string(), + RegionVariableOrigin::Coercion(_) => " for automatic coercion".to_string(), + RegionVariableOrigin::BoundRegion(_, br, BoundRegionConversionTime::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) } - infer::BoundRegion(_, br, infer::HigherRankedType) => { + RegionVariableOrigin::BoundRegion( + _, + br, + BoundRegionConversionTime::HigherRankedType, + ) => { format!(" for lifetime parameter {}in generic type", br_string(br)) } - infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( + RegionVariableOrigin::BoundRegion( + _, + br, + BoundRegionConversionTime::AssocTypeProjection(def_id), + ) => format!( " for lifetime parameter {}in trait containing associated type `{}`", br_string(br), self.tcx.associated_item(def_id).name() ), - infer::RegionParameterDefinition(_, name) => { + RegionVariableOrigin::RegionParameterDefinition(_, name) => { format!(" for lifetime parameter `{name}`") } - infer::UpvarRegion(ref upvar_id, _) => { + RegionVariableOrigin::UpvarRegion(ref upvar_id, _) => { let var_name = self.tcx.hir_name(upvar_id.var_path.hir_id); format!(" for capture of `{var_name}` by closure") } - infer::Nll(..) => bug!("NLL variable found in lexical phase"), + RegionVariableOrigin::Nll(..) => bug!("NLL variable found in lexical phase"), }; struct_span_code_err!( 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 0c88bd3dcbc54..65e31557bb628 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 @@ -47,8 +47,8 @@ use crate::infer::{self, InferCtxt, InferCtxtExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::{ MismatchedProjectionTypes, NormalizeExt, Obligation, ObligationCause, ObligationCauseCode, - ObligationCtxt, Overflow, PredicateObligation, SelectionContext, SelectionError, - SignatureMismatch, TraitDynIncompatible, elaborate, specialization_graph, + ObligationCtxt, PredicateObligation, SelectionContext, SelectionError, elaborate, + specialization_graph, }; impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { @@ -659,7 +659,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - SignatureMismatch(box SignatureMismatchData { + SelectionError::SignatureMismatch(box SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: terr @ TypeError::CyclicTy(_), @@ -669,7 +669,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_trait_ref, terr, ), - SignatureMismatch(box SignatureMismatchData { + SelectionError::SignatureMismatch(box SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: _, @@ -690,7 +690,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { def_id, ), - TraitDynIncompatible(did) => { + SelectionError::TraitDynIncompatible(did) => { let violations = self.tcx.dyn_compatibility_violations(did); report_dyn_incompatibility(self.tcx, span, None, did, violations) } @@ -710,12 +710,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Already reported in the query. SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) | // Already reported. - Overflow(OverflowError::Error(guar)) => { + SelectionError::Overflow(OverflowError::Error(guar)) => { self.set_tainted_by_errors(guar); return guar }, - Overflow(_) => { + SelectionError::Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index b247c2c2968b9..d37c954614b3a 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -154,7 +154,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< ) -> ty::GenericArg<'tcx> { match arg.kind() { ty::GenericArgKind::Lifetime(_) => { - self.next_region_var(RegionVariableOrigin::MiscVariable(span)).into() + self.next_region_var(RegionVariableOrigin::Misc(span)).into() } ty::GenericArgKind::Type(_) => self.next_ty_var(span).into(), ty::GenericArgKind::Const(_) => self.next_const_var(span).into(), diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index fe248b033bb9f..e31d1052d16c3 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -37,7 +37,9 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( ty::ConstKind::Unevaluated(uv) => { infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) } - ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env), + ty::ConstKind::Param(param_ct) => { + param_ct.find_const_ty_from_env(obligation.param_env) + } ty::ConstKind::Value(cv) => cv.ty, kind => span_bug!( obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 81893cdcc7e68..ce5a4edeaaa06 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -356,29 +356,38 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( return IntersectionHasImpossibleObligations::Yes; } - let ocx = ObligationCtxt::new_with_diagnostics(infcx); + let ocx = ObligationCtxt::new(infcx); ocx.register_obligations(obligations.iter().cloned()); + let hard_errors = ocx.select_where_possible(); + if !hard_errors.is_empty() { + assert!( + hard_errors.iter().all(|e| e.is_true_error()), + "should not have detected ambiguity during first pass" + ); + return IntersectionHasImpossibleObligations::Yes; + } + + // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer + // `FulfillmentError`. This is so that we can detect overflowing obligations + // without needing to run the `BestObligation` visitor on true errors. + let ambiguities = ocx.into_pending_obligations(); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); + ocx.register_obligations(ambiguities); let errors_and_ambiguities = ocx.select_all_or_error(); // We only care about the obligations that are *definitely* true errors. // Ambiguities do not prove the disjointness of two impls. let (errors, ambiguities): (Vec<_>, Vec<_>) = errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); - - if errors.is_empty() { - IntersectionHasImpossibleObligations::No { - overflowing_predicates: ambiguities - .into_iter() - .filter(|error| { - matches!( - error.code, - FulfillmentErrorCode::Ambiguity { overflow: Some(true) } - ) - }) - .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) - .collect(), - } - } else { - IntersectionHasImpossibleObligations::Yes + assert!(errors.is_empty(), "should not have ambiguities during second pass"); + + IntersectionHasImpossibleObligations::No { + overflowing_predicates: ambiguities + .into_iter() + .filter(|error| { + matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) + }) + .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) + .collect(), } } else { for obligation in obligations { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 951dfb879aed7..3ec286d17f735 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -20,7 +20,7 @@ use super::project::{self, ProjectAndUnifyResult}; use super::select::SelectionContext; use super::{ EvaluationResult, FulfillmentError, FulfillmentErrorCode, PredicateObligation, - ScrubbedTraitError, Unimplemented, const_evaluatable, wf, + ScrubbedTraitError, const_evaluatable, wf, }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::{InferCtxt, TyOrConstInferVar}; @@ -456,7 +456,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::DynCompatible(trait_def_id) => { if !self.selcx.tcx().is_dyn_compatible(trait_def_id) { - ProcessResult::Error(FulfillmentErrorCode::Select(Unimplemented)) + ProcessResult::Error(FulfillmentErrorCode::Select( + SelectionError::Unimplemented, + )) } else { ProcessResult::Changed(Default::default()) } @@ -507,7 +509,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), ty::ConstKind::Param(param_ct) => { - param_ct.find_ty_from_env(obligation.param_env) + param_ct.find_const_ty_from_env(obligation.param_env) } }; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 999ef97683ca8..43806d3977b94 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -36,8 +36,8 @@ use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Upcast, }; +use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; pub use self::coherence::{ @@ -644,7 +644,9 @@ pub fn try_evaluate_const<'tcx>( let erased_uv = tcx.erase_regions(uv); use rustc_middle::mir::interpret::ErrorHandled; - match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) { + // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at + // where it gets used as a const generic. + match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, tcx.def_span(uv.def)) { Ok(Ok(val)) => Ok(ty::Const::new_value( tcx, val, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6dd80551980f7..28b5b7cf391eb 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -84,9 +84,6 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { // was discarded -- this could be because of ambiguity, or because // a higher-priority candidate is already there. fn push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool { - use self::ProjectionCandidate::*; - use self::ProjectionCandidateSet::*; - // This wacky variable is just used to try and // make code readable and avoid confusing paths. // It is assigned a "value" of `()` only on those @@ -98,12 +95,12 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { let convert_to_ambiguous; match self { - None => { - *self = Single(candidate); + ProjectionCandidateSet::None => { + *self = ProjectionCandidateSet::Single(candidate); return true; } - Single(current) => { + ProjectionCandidateSet::Single(current) => { // Duplicates can happen inside ParamEnv. In the case, we // perform a lazy deduplication. if current == &candidate { @@ -118,16 +115,18 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { // clauses are the safer choice. See the comment on // `select::SelectionCandidate` and #21974 for more details. match (current, candidate) { - (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (), - (ParamEnv(..), _) => return false, - (_, ParamEnv(..)) => bug!( + (ProjectionCandidate::ParamEnv(..), ProjectionCandidate::ParamEnv(..)) => { + convert_to_ambiguous = () + } + (ProjectionCandidate::ParamEnv(..), _) => return false, + (_, ProjectionCandidate::ParamEnv(..)) => bug!( "should never prefer non-param-env candidates over param-env candidates" ), (_, _) => convert_to_ambiguous = (), } } - Ambiguous | Error(..) => { + ProjectionCandidateSet::Ambiguous | ProjectionCandidateSet::Error(..) => { return false; } } @@ -135,7 +134,7 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { // We only ever get here when we moved from a single candidate // to ambiguous. let () = convert_to_ambiguous; - *self = Ambiguous; + *self = ProjectionCandidateSet::Ambiguous; false } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 80f71c78993cc..3eca77b43a89a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -11,7 +11,7 @@ use std::ops::ControlFlow; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ @@ -28,8 +28,7 @@ use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::util::{self, closure_trait_ref_and_return_type}; use crate::traits::{ ImplSource, ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, - PolyTraitObligation, PredicateObligation, Selection, SelectionError, SignatureMismatch, - TraitDynIncompatible, TraitObligation, Unimplemented, + PolyTraitObligation, PredicateObligation, Selection, SelectionError, TraitObligation, }; impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { @@ -176,7 +175,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, - HigherRankedType, + BoundRegionConversionTime::HigherRankedType, candidate, ); let mut obligations = PredicateObligations::new(); @@ -194,7 +193,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) - .map_err(|_| Unimplemented)?, + .map_err(|_| SelectionError::Unimplemented)?, ); // FIXME(compiler-errors): I don't think this is needed. @@ -374,7 +373,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { assume = crate::traits::evaluate_const(self.infcx, assume, obligation.param_env) } let Some(assume) = rustc_transmute::Assume::from_const(self.infcx.tcx, assume) else { - return Err(Unimplemented); + return Err(SelectionError::Unimplemented); }; let dst = predicate.trait_ref.args.type_at(0); @@ -386,7 +385,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { transmute_env.is_transmutable(rustc_transmute::Types { dst, src }, assume); let fully_flattened = match maybe_transmutable { - Answer::No(_) => Err(Unimplemented)?, + Answer::No(_) => Err(SelectionError::Unimplemented)?, Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, cond, assume), Answer::Yes => PredicateObligations::new(), }; @@ -500,7 +499,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, - HigherRankedType, + BoundRegionConversionTime::HigherRankedType, object_trait_ref, ); let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty); @@ -513,7 +512,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let upcast_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, - HigherRankedType, + BoundRegionConversionTime::HigherRankedType, unnormalized_upcast_trait_ref, ); let upcast_trait_ref = normalize_with_depth_to( @@ -530,7 +529,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::No, trait_predicate.trait_ref, upcast_trait_ref) .map(|InferOk { obligations, .. }| obligations) - .map_err(|_| Unimplemented)?, + .map_err(|_| SelectionError::Unimplemented)?, ); // Check supertraits hold. This is so that their associated type bounds @@ -962,7 +961,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result, SelectionError<'tcx>> { let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, - HigherRankedType, + BoundRegionConversionTime::HigherRankedType, found_trait_ref, ); // Normalize the obligation and expected trait refs together, because why not @@ -986,7 +985,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations }) .map_err(|terr| { - SignatureMismatch(Box::new(SignatureMismatchData { + SelectionError::SignatureMismatch(Box::new(SignatureMismatchData { expected_trait_ref: obligation_trait_ref, found_trait_ref, terr, @@ -1090,7 +1089,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .at(&obligation.cause, obligation.param_env) .sup(DefineOpaqueTypes::Yes, target, source_trait) - .map_err(|_| Unimplemented)?; + .map_err(|_| SelectionError::Unimplemented)?; // Register one obligation for 'a: 'b. let outlives = ty::OutlivesPredicate(r_a, r_b); @@ -1109,7 +1108,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (_, &ty::Dynamic(data, r, ty::Dyn)) => { let mut object_dids = data.auto_traits().chain(data.principal_def_id()); if let Some(did) = object_dids.find(|did| !tcx.is_dyn_compatible(*did)) { - return Err(TraitDynIncompatible(did)); + return Err(SelectionError::TraitDynIncompatible(did)); } let predicate_to_obligation = |predicate| { @@ -1189,7 +1188,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::Yes, b, a) - .map_err(|_| Unimplemented)?; + .map_err(|_| SelectionError::Unimplemented)?; ImplSource::Builtin(BuiltinImplSource::Misc, obligations) } @@ -1198,7 +1197,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (&ty::Adt(def, args_a), &ty::Adt(_, args_b)) => { let unsizing_params = tcx.unsizing_params_for_adt(def.did()); if unsizing_params.is_empty() { - return Err(Unimplemented); + return Err(SelectionError::Unimplemented); } let tail_field = def.non_enum_variant().tail(); @@ -1237,7 +1236,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .at(&obligation.cause, obligation.param_env) .eq(DefineOpaqueTypes::Yes, target, new_struct) - .map_err(|_| Unimplemented)?; + .map_err(|_| SelectionError::Unimplemented)?; nested.extend(obligations); // Construct the nested `TailField: Unsize>` predicate. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9c0ccb26e53f6..0f1a29aafe47f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -39,7 +39,7 @@ use super::coherence::{self, Conflict}; use super::project::ProjectionTermObligation; use super::util::closure_trait_ref_and_return_type; use super::{ - ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, + ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult, TraitQueryMode, const_evaluatable, project, util, wf, }; @@ -48,9 +48,7 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::solve::InferCtxtSelectExt as _; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt}; -use crate::traits::{ - EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects, sizedness_fast_path, -}; +use crate::traits::{EvaluateConstErr, ProjectionCacheKey, effects, sizedness_fast_path}; mod _match; mod candidate_assembly; @@ -454,8 +452,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) } Ok(_) => Ok(None), - Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)), - Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))), + Err(OverflowError::Canonical) => { + Err(SelectionError::Overflow(OverflowError::Canonical)) + } + Err(OverflowError::Error(e)) => { + Err(SelectionError::Overflow(OverflowError::Error(e))) + } }) .flat_map(Result::transpose) .collect::, _>>()?; @@ -479,7 +481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous"); Ok(None) } else { - Err(Unimplemented) + Err(SelectionError::Unimplemented) } } else { let has_non_region_infer = stack.obligation.predicate.has_non_region_infer(); @@ -979,7 +981,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), ty::ConstKind::Param(param_ct) => { - param_ct.find_ty_from_env(obligation.param_env) + param_ct.find_const_ty_from_env(obligation.param_env) } }; @@ -1222,7 +1224,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), - Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), + Err(SelectionError::Overflow(OverflowError::Canonical)) => { + Err(OverflowError::Canonical) + } Err(..) => Ok(EvaluatedToErr), } } @@ -1536,7 +1540,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Some(res); } else if cfg!(debug_assertions) { match infcx.selection_cache.get(&(param_env, pred), tcx) { - None | Some(Err(Overflow(OverflowError::Canonical))) => {} + None | Some(Err(SelectionError::Overflow(OverflowError::Canonical))) => {} res => bug!("unexpected local cache result: {res:?}"), } } @@ -1592,7 +1596,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { - if let Err(Overflow(OverflowError::Canonical)) = candidate { + if let Err(SelectionError::Overflow(OverflowError::Canonical)) = candidate { // Don't cache overflow globally; we only produce this in certain modes. } else { debug!(?pred, ?candidate, "insert_candidate_cache global"); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 9452dca9a4f0f..19eb85506b6fb 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -273,8 +273,6 @@ impl<'tcx> Graph { // Descend the specialization tree, where `parent` is the current parent node. loop { - use self::Inserted::*; - let insert_result = self.children.entry(parent).or_default().insert( tcx, impl_def_id, @@ -283,11 +281,11 @@ impl<'tcx> Graph { )?; match insert_result { - BecameNewSibling(opt_lint) => { + Inserted::BecameNewSibling(opt_lint) => { last_lint = opt_lint; break; } - ReplaceChildren(grand_children_to_be) => { + Inserted::ReplaceChildren(grand_children_to_be) => { // We currently have // // P @@ -326,7 +324,7 @@ impl<'tcx> Graph { } break; } - ShouldRecurseOn(new_parent) => { + Inserted::ShouldRecurseOn(new_parent) => { parent = new_parent; } } diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index a0a1d4545564e..9d14401056183 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upc use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, - Unimplemented, sizedness_fast_path, + SelectionError, sizedness_fast_path, }; use tracing::debug; @@ -47,7 +47,7 @@ pub(crate) fn codegen_select_candidate<'tcx>( let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, Ok(None) => return Err(CodegenObligationError::Ambiguity), - Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), + Err(SelectionError::Unimplemented) => return Err(CodegenObligationError::Unimplemented), Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 608efc7515ca9..272fca5b026c5 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -12,7 +12,7 @@ use crate::elaborate::Elaboratable; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; use crate::solve::{AdtDestructorKind, SizedTraitKind}; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; +use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; pub trait Ty>: @@ -538,6 +538,45 @@ pub trait PlaceholderLike: Copy + Debug + Hash + Eq { fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self; } +pub trait PlaceholderConst: PlaceholderLike { + fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty; +} +impl PlaceholderConst for I::PlaceholderConst { + fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { + let mut candidates = env.caller_bounds().iter().filter_map(|clause| { + // `ConstArgHasType` are never desugared to be higher ranked. + match clause.kind().skip_binder() { + ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { + assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); + + match placeholder_ct.kind() { + ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { + Some(ty) + } + _ => None, + } + } + _ => None, + } + }); + + // N.B. it may be tempting to fix ICEs by making this function return + // `Option>` instead of `Ty<'tcx>`; however, this is generally + // considered to be a bandaid solution, since it hides more important + // underlying issues with how we construct generics and predicates of + // items. It's advised to fix the underlying issue rather than trying + // to modify this function. + let ty = candidates.next().unwrap_or_else(|| { + panic!("cannot find `{self:?}` in param-env: {env:#?}"); + }); + assert!( + candidates.next().is_none(), + "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}" + ); + ty + } +} + pub trait IntoKind { type Kind; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index ffc2903ad1cad..dd3cf1fc1811f 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -133,7 +133,7 @@ pub trait Interner: type Const: Const; type ParamConst: Copy + Debug + Hash + Eq + ParamLike; type BoundConst: BoundVarLike; - type PlaceholderConst: PlaceholderLike; + type PlaceholderConst: PlaceholderConst; type ValueConst: ValueConst; type ExprConst: ExprConst; type ValTree: Copy + Debug + Hash + Eq; @@ -348,12 +348,6 @@ pub trait Interner: type UnsizingParams: Deref>; fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams; - fn find_const_ty_from_env( - self, - param_env: Self::ParamEnv, - placeholder: Self::PlaceholderConst, - ) -> Self::Ty; - fn anonymize_bound_vars>( self, binder: ty::Binder, diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 4b8ea708e7e57..010d17f74762c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3004,7 +3004,6 @@ pub struct Weak< // `Weak::new` sets this to `usize::MAX` so that it doesn’t need // to allocate space on the heap. That's not a value a real pointer // will ever have because RcInner has alignment at least 2. - // This is only possible when `T: Sized`; unsized `T` never dangle. ptr: NonNull>, alloc: A, } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 17090925cfa0c..1e3c03977bd75 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -342,7 +342,6 @@ pub struct Weak< // `Weak::new` sets this to `usize::MAX` so that it doesn’t need // to allocate space on the heap. That's not a value a real pointer // will ever have because RcInner has alignment at least 2. - // This is only possible when `T: Sized`; unsized `T` never dangle. ptr: NonNull>, alloc: A, } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index a2c1ba835f366..7ce03e3d83198 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display}; use crate::marker::{PhantomData, PointerLike, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; +use crate::panic::const_panic; use crate::pin::PinCoerceUnsized; use crate::ptr::{self, NonNull}; @@ -781,16 +782,24 @@ impl Display for BorrowMutError { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[cold] -fn panic_already_borrowed(err: BorrowMutError) -> ! { - panic!("{err}") +const fn panic_already_borrowed(err: BorrowMutError) -> ! { + const_panic!( + "RefCell already borrowed", + "{err}", + err: BorrowMutError = err, + ) } // This ensures the panicking code is outlined from `borrow` for `RefCell`. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[cold] -fn panic_already_mutably_borrowed(err: BorrowError) -> ! { - panic!("{err}") +const fn panic_already_mutably_borrowed(err: BorrowError) -> ! { + const_panic!( + "RefCell already mutably borrowed", + "{err}", + err: BorrowError = err, + ) } // Positive values represent the number of `Ref` active. Negative values @@ -810,12 +819,12 @@ type BorrowCounter = isize; const UNUSED: BorrowCounter = 0; #[inline(always)] -fn is_writing(x: BorrowCounter) -> bool { +const fn is_writing(x: BorrowCounter) -> bool { x < UNUSED } #[inline(always)] -fn is_reading(x: BorrowCounter) -> bool { +const fn is_reading(x: BorrowCounter) -> bool { x > UNUSED } @@ -884,8 +893,9 @@ impl RefCell { #[stable(feature = "refcell_replace", since = "1.24.0")] #[track_caller] #[rustc_confusables("swap")] - pub fn replace(&self, t: T) -> T { - mem::replace(&mut *self.borrow_mut(), t) + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn replace(&self, t: T) -> T { + mem::replace(&mut self.borrow_mut(), t) } /// Replaces the wrapped value with a new one computed from `f`, returning @@ -935,7 +945,8 @@ impl RefCell { /// ``` #[inline] #[stable(feature = "refcell_swap", since = "1.24.0")] - pub fn swap(&self, other: &Self) { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn swap(&self, other: &Self) { mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut()) } } @@ -975,7 +986,8 @@ impl RefCell { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] - pub fn borrow(&self) -> Ref<'_, T> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn borrow(&self) -> Ref<'_, T> { match self.try_borrow() { Ok(b) => b, Err(err) => panic_already_mutably_borrowed(err), @@ -1010,14 +1022,15 @@ impl RefCell { #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] #[cfg_attr(feature = "debug_refcell", track_caller)] - pub fn try_borrow(&self) -> Result, BorrowError> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn try_borrow(&self) -> Result, BorrowError> { match BorrowRef::new(&self.borrow) { Some(b) => { #[cfg(feature = "debug_refcell")] { // `borrowed_at` is always the *first* active borrow if b.borrow.get() == 1 { - self.borrowed_at.set(Some(crate::panic::Location::caller())); + self.borrowed_at.replace(Some(crate::panic::Location::caller())); } } @@ -1071,7 +1084,8 @@ impl RefCell { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] - pub fn borrow_mut(&self) -> RefMut<'_, T> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn borrow_mut(&self) -> RefMut<'_, T> { match self.try_borrow_mut() { Ok(b) => b, Err(err) => panic_already_borrowed(err), @@ -1103,12 +1117,13 @@ impl RefCell { #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] #[cfg_attr(feature = "debug_refcell", track_caller)] - pub fn try_borrow_mut(&self) -> Result, BorrowMutError> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn try_borrow_mut(&self) -> Result, BorrowMutError> { match BorrowRefMut::new(&self.borrow) { Some(b) => { #[cfg(feature = "debug_refcell")] { - self.borrowed_at.set(Some(crate::panic::Location::caller())); + self.borrowed_at.replace(Some(crate::panic::Location::caller())); } // SAFETY: `BorrowRefMut` guarantees unique access. @@ -1139,7 +1154,8 @@ impl RefCell { #[stable(feature = "cell_as_ptr", since = "1.12.0")] #[rustc_as_ptr] #[rustc_never_returns_null_ptr] - pub fn as_ptr(&self) -> *mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn as_ptr(&self) -> *mut T { self.value.get() } @@ -1176,7 +1192,8 @@ impl RefCell { /// ``` #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn get_mut(&mut self) -> &mut T { self.value.get_mut() } @@ -1202,7 +1219,8 @@ impl RefCell { /// assert!(c.try_borrow().is_ok()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn undo_leak(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn undo_leak(&mut self) -> &mut T { *self.borrow.get_mut() = UNUSED; self.get_mut() } @@ -1236,7 +1254,8 @@ impl RefCell { /// ``` #[stable(feature = "borrow_state", since = "1.37.0")] #[inline] - pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { if !is_writing(self.borrow.get()) { // SAFETY: We check that nobody is actively writing now, but it is // the caller's responsibility to ensure that nobody writes until @@ -1400,7 +1419,7 @@ struct BorrowRef<'b> { impl<'b> BorrowRef<'b> { #[inline] - fn new(borrow: &'b Cell) -> Option> { + const fn new(borrow: &'b Cell) -> Option> { let b = borrow.get().wrapping_add(1); if !is_reading(b) { // Incrementing borrow can result in a non-reading value (<= 0) in these cases: @@ -1417,22 +1436,24 @@ impl<'b> BorrowRef<'b> { // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize // is large enough to represent having one more read borrow - borrow.set(b); + borrow.replace(b); Some(BorrowRef { borrow }) } } } -impl Drop for BorrowRef<'_> { +#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] +impl const Drop for BorrowRef<'_> { #[inline] fn drop(&mut self) { let borrow = self.borrow.get(); debug_assert!(is_reading(borrow)); - self.borrow.set(borrow - 1); + self.borrow.replace(borrow - 1); } } -impl Clone for BorrowRef<'_> { +#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] +impl const Clone for BorrowRef<'_> { #[inline] fn clone(&self) -> Self { // Since this Ref exists, we know the borrow flag @@ -1442,7 +1463,7 @@ impl Clone for BorrowRef<'_> { // Prevent the borrow counter from overflowing into // a writing borrow. assert!(borrow != BorrowCounter::MAX); - self.borrow.set(borrow + 1); + self.borrow.replace(borrow + 1); BorrowRef { borrow: self.borrow } } } @@ -1463,7 +1484,8 @@ pub struct Ref<'b, T: ?Sized + 'b> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for Ref<'_, T> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for Ref<'_, T> { type Target = T; #[inline] @@ -1488,7 +1510,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { #[stable(feature = "cell_extras", since = "1.15.0")] #[must_use] #[inline] - pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { Ref { value: orig.value, borrow: orig.borrow.clone() } } @@ -1610,7 +1633,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// assert!(cell.try_borrow_mut().is_err()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn leak(orig: Ref<'b, T>) -> &'b T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn leak(orig: Ref<'b, T>) -> &'b T { // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a // unique reference to the borrowed RefCell. No further mutable references can be created @@ -1776,7 +1800,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// assert!(cell.try_borrow_mut().is_err()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn leak(mut orig: RefMut<'b, T>) -> &'b mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn leak(mut orig: RefMut<'b, T>) -> &'b mut T { // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would // require a unique reference to the borrowed RefCell. No further references can be created @@ -1792,25 +1817,26 @@ struct BorrowRefMut<'b> { borrow: &'b Cell, } -impl Drop for BorrowRefMut<'_> { +#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] +impl const Drop for BorrowRefMut<'_> { #[inline] fn drop(&mut self) { let borrow = self.borrow.get(); debug_assert!(is_writing(borrow)); - self.borrow.set(borrow + 1); + self.borrow.replace(borrow + 1); } } impl<'b> BorrowRefMut<'b> { #[inline] - fn new(borrow: &'b Cell) -> Option> { + const fn new(borrow: &'b Cell) -> Option> { // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial // mutable reference, and so there must currently be no existing // references. Thus, while clone increments the mutable refcount, here // we explicitly only allow going from UNUSED to UNUSED - 1. match borrow.get() { UNUSED => { - borrow.set(UNUSED - 1); + borrow.replace(UNUSED - 1); Some(BorrowRefMut { borrow }) } _ => None, @@ -1849,7 +1875,8 @@ pub struct RefMut<'b, T: ?Sized + 'b> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for RefMut<'_, T> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for RefMut<'_, T> { type Target = T; #[inline] @@ -1860,7 +1887,8 @@ impl Deref for RefMut<'_, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl DerefMut for RefMut<'_, T> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const DerefMut for RefMut<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut T { // SAFETY: the value is accessible as long as we hold our borrow. diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index c97a59b614f9d..843479e2a27a7 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -223,7 +223,16 @@ where { let mut accum = init; - let first = if started { next_item.take() } else { iter.next() }; + let first = if started { + next_item.take() + } else { + let n = iter.next(); + // skip invoking fold() for empty iterators + if n.is_none() { + return accum; + } + n + }; if let Some(x) = first { accum = f(accum, x); } diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index b85841295dab1..7ca41d224a0a6 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -420,7 +420,7 @@ pub use self::adapters::{Intersperse, IntersperseWith}; issue = "42168" )] pub use self::range::Step; -#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")] +#[unstable(feature = "iter_macro", issue = "142269", reason = "generators are unstable")] pub use self::sources::iter; #[stable(feature = "iter_empty", since = "1.2.0")] pub use self::sources::{Empty, empty}; diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs index fd9330201ff4e..8e27edb73c995 100644 --- a/library/core/src/iter/sources.rs +++ b/library/core/src/iter/sources.rs @@ -19,7 +19,7 @@ pub use self::empty::{Empty, empty}; pub use self::from_coroutine::{FromCoroutine, from_coroutine}; #[stable(feature = "iter_from_fn", since = "1.34.0")] pub use self::from_fn::{FromFn, from_fn}; -#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")] +#[unstable(feature = "iter_macro", issue = "142269", reason = "generators are unstable")] pub use self::generator::iter; #[stable(feature = "iter_once", since = "1.2.0")] pub use self::once::{Once, once}; diff --git a/library/core/src/iter/sources/generator.rs b/library/core/src/iter/sources/generator.rs index 0846974d526a9..94d501de033be 100644 --- a/library/core/src/iter/sources/generator.rs +++ b/library/core/src/iter/sources/generator.rs @@ -18,7 +18,7 @@ /// let v: Vec<_> = it.collect(); /// assert_eq!(v, [1, 2, 3]); /// ``` -#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")] +#[unstable(feature = "iter_macro", issue = "142269", reason = "generators are unstable")] #[allow_internal_unstable(coroutines, iter_from_coroutine)] #[rustc_builtin_macro] pub macro iter($($t:tt)*) { diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index ba687434bf102..b6d5f848ef039 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1935,6 +1935,7 @@ unsafe impl PinCoerceUnsized for *mut T {} #[stable(feature = "pin_macro", since = "1.68.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(super_let)] +#[rustc_diagnostic_item = "pin_macro"] // `super` gets removed by rustfmt #[rustfmt::skip] pub macro pin($value:expr $(,)?) { diff --git a/library/coretests/tests/cell.rs b/library/coretests/tests/cell.rs index 781a46c3744f5..c0ac66e5d2bae 100644 --- a/library/coretests/tests/cell.rs +++ b/library/coretests/tests/cell.rs @@ -1,4 +1,5 @@ use core::cell::*; +use core::mem::forget; #[test] fn smoketest_unsafe_cell() { @@ -477,3 +478,74 @@ fn const_cells() { const _: i32 = CELL.into_inner(); */ } + +#[test] +fn refcell_borrow() { + // Check that `borrow` is usable at compile-time + const { + let a = RefCell::new(0); + assert!(a.try_borrow().is_ok()); + assert!(a.try_borrow_mut().is_ok()); + let a_ref = a.borrow(); + assert!(*a_ref == 0); + assert!(a.try_borrow().is_ok()); + assert!(a.try_borrow_mut().is_err()); + } +} + +#[test] +fn refcell_borrow_mut() { + // Check that `borrow_mut` is usable at compile-time + const { + let mut a = RefCell::new(0); + { + assert!(a.try_borrow().is_ok()); + assert!(a.try_borrow_mut().is_ok()); + let mut a_ref = a.borrow_mut(); + assert!(*a_ref == 0); + *a_ref = 10; + assert!(*a_ref == 10); + assert!(a.try_borrow().is_err()); + assert!(a.try_borrow_mut().is_err()); + } + assert!(*a.get_mut() == 10); + }; +} +struct NeverDrop; +impl Drop for NeverDrop { + fn drop(&mut self) { + panic!("should never be called"); + } +} + +#[test] +fn refcell_replace() { + // Check that `replace` is usable at compile-time + const { + let a = RefCell::new(0); + assert!(a.replace(10) == 0); + let a = a.into_inner(); + assert!(a == 10); + + let b = RefCell::new(NeverDrop); + forget(b.replace(NeverDrop)); + forget(b) + }; +} + +#[test] +fn refcell_swap() { + // Check that `swap` is usable at compile-time + const { + let (a, b) = (RefCell::new(31), RefCell::new(41)); + a.swap(&b); + let (a, b) = (a.into_inner(), b.into_inner()); + assert!(a == 41); + assert!(b == 31); + + let c = RefCell::new(NeverDrop); + let d = RefCell::new(NeverDrop); + c.swap(&d); + forget((c, d)); + }; +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 5449132413b54..b629888378447 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -15,8 +15,11 @@ #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_max_len)] #![feature(clone_to_uninit)] +#![feature(const_deref)] +#![feature(const_destruct)] #![feature(const_eval_select)] #![feature(const_float_round_methods)] +#![feature(const_ref_cell)] #![feature(const_trait_impl)] #![feature(core_float_math)] #![feature(core_intrinsics)] diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index a060e2ea57a7b..934a173425a81 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -481,7 +481,7 @@ impl RwLock { /// in the returned error. /// /// This function will return the [`WouldBlock`] error if the `RwLock` could - /// not be acquired because it was already locked exclusively. + /// not be acquired because it was already locked. /// /// [`Poisoned`]: TryLockError::Poisoned /// [`WouldBlock`]: TryLockError::WouldBlock diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 9ce81ff9a229f..37fc85518e0ea 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -272,7 +272,7 @@ fn rustup_installed(builder: &Builder<'_>) -> bool { let mut rustup = command("rustup"); rustup.arg("--version"); - rustup.allow_failure().run_always().run_capture_stdout(builder).is_success() + rustup.allow_failure().run_in_dry_run().run_capture_stdout(builder).is_success() } fn stage_dir_exists(stage_path: &str) -> bool { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index d7decaa8a9804..b2754a5ad32c2 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -809,7 +809,7 @@ impl Config { config.initial_sysroot = t!(PathBuf::from_str( command(&config.initial_rustc) .args(["--print", "sysroot"]) - .run_always() + .run_in_dry_run() .run_capture_stdout(&config) .stdout() .trim() @@ -1391,11 +1391,11 @@ impl Config { // all the git commands below are actually executed, because some follow-up code // in bootstrap might depend on the submodules being checked out. Furthermore, not all // the command executions below work with an empty output (produced during dry run). - // Therefore, all commands below are marked with `run_always()`, so that they also run in + // Therefore, all commands below are marked with `run_in_dry_run()`, so that they also run in // dry run mode. let submodule_git = || { let mut cmd = helpers::git(Some(&absolute_path)); - cmd.run_always(); + cmd.run_in_dry_run(); cmd }; @@ -1405,7 +1405,7 @@ impl Config { let checked_out_hash = checked_out_hash.trim_end(); // Determine commit that the submodule *should* have. let recorded = helpers::git(Some(&self.src)) - .run_always() + .run_in_dry_run() .args(["ls-tree", "HEAD"]) .arg(relative_path) .run_capture_stdout(self) @@ -1425,7 +1425,7 @@ impl Config { helpers::git(Some(&self.src)) .allow_failure() - .run_always() + .run_in_dry_run() .args(["submodule", "-q", "sync"]) .arg(relative_path) .run(self); @@ -1436,12 +1436,12 @@ impl Config { // even though that has no relation to the upstream for the submodule. let current_branch = helpers::git(Some(&self.src)) .allow_failure() - .run_always() + .run_in_dry_run() .args(["symbolic-ref", "--short", "HEAD"]) .run_capture(self); let mut git = helpers::git(Some(&self.src)).allow_failure(); - git.run_always(); + git.run_in_dry_run(); if current_branch.is_success() { // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. // This syntax isn't accepted by `branch.{branch}`. Strip it. diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 2706aba5ffc8d..c79fbbeb55cc1 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -88,7 +88,7 @@ fn workspace_members(build: &Build) -> Vec { .arg("--no-deps") .arg("--manifest-path") .arg(build.src.join(manifest_path)); - let metadata_output = cargo.run_always().run_capture_stdout(build).stdout(); + let metadata_output = cargo.run_in_dry_run().run_capture_stdout(build).stdout(); let Output { packages, .. } = t!(serde_json::from_str(&metadata_output)); packages }; diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 493f73b21fe15..958058d982bac 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -202,7 +202,7 @@ than building it. let stage0_supported_target_list: HashSet = command(&build.config.initial_rustc) .args(["--print", "target-list"]) - .run_always() + .run_in_dry_run() .run_capture_stdout(&build) .stdout() .lines() @@ -366,7 +366,7 @@ than building it. // Cygwin. The Cygwin build does not have generators for Visual // Studio, so detect that here and error. let out = - command("cmake").arg("--help").run_always().run_capture_stdout(&build).stdout(); + command("cmake").arg("--help").run_in_dry_run().run_capture_stdout(&build).stdout(); if !out.contains("Visual Studio") { panic!( " diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index cfa42f61d01db..26fac6b3b603f 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -383,7 +383,7 @@ impl Build { let in_tree_gcc_info = config.in_tree_gcc_info.clone(); let initial_target_libdir = command(&config.initial_rustc) - .run_always() + .run_in_dry_run() .args(["--print", "target-libdir"]) .run_capture_stdout(&config) .stdout() @@ -490,7 +490,7 @@ impl Build { // If local-rust is the same major.minor as the current version, then force a // local-rebuild let local_version_verbose = command(&build.initial_rustc) - .run_always() + .run_in_dry_run() .args(["--version", "--verbose"]) .run_capture_stdout(&build) .stdout(); @@ -949,7 +949,7 @@ impl Build { static SYSROOT_CACHE: OnceLock = OnceLock::new(); SYSROOT_CACHE.get_or_init(|| { command(&self.initial_rustc) - .run_always() + .run_in_dry_run() .args(["--print", "sysroot"]) .run_capture_stdout(self) .stdout() @@ -1512,7 +1512,7 @@ impl Build { "refs/remotes/origin/{}..HEAD", self.config.stage0_metadata.config.nightly_branch )) - .run_always() + .run_in_dry_run() .run_capture(self) .stdout() }); diff --git a/src/bootstrap/src/utils/channel.rs b/src/bootstrap/src/utils/channel.rs index b28ab57377408..16aa9ba0585b2 100644 --- a/src/bootstrap/src/utils/channel.rs +++ b/src/bootstrap/src/utils/channel.rs @@ -66,19 +66,22 @@ impl GitInfo { .arg("-1") .arg("--date=short") .arg("--pretty=format:%cd") - .run_always() + .run_in_dry_run() .start_capture_stdout(&exec_ctx); let mut git_hash_cmd = helpers::git(Some(dir)); - let ver_hash = - git_hash_cmd.arg("rev-parse").arg("HEAD").run_always().start_capture_stdout(&exec_ctx); + let ver_hash = git_hash_cmd + .arg("rev-parse") + .arg("HEAD") + .run_in_dry_run() + .start_capture_stdout(&exec_ctx); let mut git_short_hash_cmd = helpers::git(Some(dir)); let short_ver_hash = git_short_hash_cmd .arg("rev-parse") .arg("--short=9") .arg("HEAD") - .run_always() + .run_in_dry_run() .start_capture_stdout(&exec_ctx); GitInfo::Present(Some(Info { diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 78b28ac182823..a7b92441d747e 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -66,7 +66,7 @@ pub struct BootstrapCommand { command: Command, pub failure_behavior: BehaviorOnFailure, // Run the command even during dry run - pub run_always: bool, + pub run_in_dry_run: bool, // This field makes sure that each command is executed (or disarmed) before it is dropped, // to avoid forgetting to execute a command. drop_bomb: DropBomb, @@ -138,8 +138,8 @@ impl<'a> BootstrapCommand { Self { failure_behavior: BehaviorOnFailure::Ignore, ..self } } - pub fn run_always(&mut self) -> &mut Self { - self.run_always = true; + pub fn run_in_dry_run(&mut self) -> &mut Self { + self.run_in_dry_run = true; self } @@ -228,7 +228,7 @@ impl From for BootstrapCommand { Self { command, failure_behavior: BehaviorOnFailure::Exit, - run_always: false, + run_in_dry_run: false, drop_bomb: DropBomb::arm(program), } } diff --git a/src/bootstrap/src/utils/execution_context.rs b/src/bootstrap/src/utils/execution_context.rs index 5b9fef3f8248b..66a4be9252e4e 100644 --- a/src/bootstrap/src/utils/execution_context.rs +++ b/src/bootstrap/src/utils/execution_context.rs @@ -93,7 +93,7 @@ impl ExecutionContext { let created_at = command.get_created_location(); let executed_at = std::panic::Location::caller(); - if self.dry_run() && !command.run_always { + if self.dry_run() && !command.run_in_dry_run { return DeferredCommand { process: None, stdout, stderr, command, executed_at }; } diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index e15121e0f3162..f8d54d445576b 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.20.6 \ No newline at end of file +0.20.7 \ No newline at end of file diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 69899539b4523..3cac55493f00a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -755,8 +755,11 @@ impl Item { .filter_map(|attr| { // NoMangle is special cased, as it appears in HTML output, and we want to show it in source form, not HIR printing. // It is also used by cargo-semver-checks. - if matches!(attr, hir::Attribute::Parsed(AttributeKind::NoMangle(..))) { + if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr { Some("#[no_mangle]".to_string()) + } else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr + { + Some(format!("#[export_name = \"{name}\"]")) } else if is_json { match attr { // rustdoc-json stores this in `Item::deprecation`, so we diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index e774c5e2047c8..0c4ef36828a0f 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -40,9 +40,9 @@ pub(crate) fn run_tests(config: &Config, tests: Vec) -> bool { // In that case, the tests will effectively be run serially anyway. loop { // Spawn new test threads, up to the concurrency limit. - // FIXME(let_chains): Use a let-chain here when stable in bootstrap. - 'spawn: while running_tests.len() < concurrency { - let Some((id, test)) = fresh_tests.next() else { break 'spawn }; + while running_tests.len() < concurrency + && let Some((id, test)) = fresh_tests.next() + { listener.test_started(test); deadline_queue.push(id, test); let join_handle = spawn_test_thread(id, test, completion_tx.clone()); diff --git a/tests/crashes/139905.rs b/tests/crashes/139905.rs deleted file mode 100644 index 7da622aaabac6..0000000000000 --- a/tests/crashes/139905.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #139905 -trait a {} -impl a<{}> for () {} -trait c {} -impl c for () where (): a {} -impl c for () {} diff --git a/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs b/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs new file mode 100644 index 0000000000000..4b6de6f56d558 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs @@ -0,0 +1,17 @@ +// The impl of lint `const_evaluatable_unchecked` used to wrongly assume and `assert!` that +// successfully evaluating a type-system constant that has non-region args had to be an anon const. +// In the case below however we have a type-system assoc const (here: `<() as TraitA>::K`). +// +// issue: +//@ check-pass +#![feature(associated_const_equality)] + +pub trait TraitA { const K: u8 = 0; } +pub trait TraitB {} + +impl TraitA for () {} +impl TraitB for () where (): TraitA {} + +fn check() where (): TraitB {} + +fn main() {} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle.fixed b/tests/ui/attributes/mixed_export_name_and_no_mangle.fixed index d8b5235c52fbe..55c196f6decaa 100644 --- a/tests/ui/attributes/mixed_export_name_and_no_mangle.fixed +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle.fixed @@ -3,11 +3,11 @@ //@ check-pass #![warn(unused_attributes)] -//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]` [unused_attributes] +//~^ WARN `#[no_mangle]` attribute may not be used in combination with `#[export_name]` [unused_attributes] #[export_name = "foo"] pub fn bar() {} -//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]` [unused_attributes] +//~^ WARN `#[no_mangle]` attribute may not be used in combination with `#[export_name]` [unused_attributes] #[export_name = "baz"] pub fn bak() {} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle.rs b/tests/ui/attributes/mixed_export_name_and_no_mangle.rs index 83a673a7d1328..79f1e5c19c544 100644 --- a/tests/ui/attributes/mixed_export_name_and_no_mangle.rs +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle.rs @@ -4,12 +4,12 @@ #![warn(unused_attributes)] #[no_mangle] -//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]` [unused_attributes] +//~^ WARN `#[no_mangle]` attribute may not be used in combination with `#[export_name]` [unused_attributes] #[export_name = "foo"] pub fn bar() {} #[unsafe(no_mangle)] -//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]` [unused_attributes] +//~^ WARN `#[no_mangle]` attribute may not be used in combination with `#[export_name]` [unused_attributes] #[export_name = "baz"] pub fn bak() {} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr b/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr index c760d27db2513..1dcaa636800be 100644 --- a/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr @@ -1,8 +1,8 @@ -warning: `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]` +warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]` --> $DIR/mixed_export_name_and_no_mangle.rs:6:1 | LL | #[no_mangle] - | ^^^^^^^^^^^^ `#[unsafe(no_mangle)]` is ignored + | ^^^^^^^^^^^^ `#[no_mangle]` is ignored | note: `#[export_name]` takes precedence --> $DIR/mixed_export_name_and_no_mangle.rs:8:1 @@ -14,23 +14,23 @@ note: the lint level is defined here | LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -help: remove the `#[unsafe(no_mangle)]` attribute +help: remove the `#[no_mangle]` attribute | LL - #[no_mangle] | -warning: `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]` +warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]` --> $DIR/mixed_export_name_and_no_mangle.rs:11:1 | LL | #[unsafe(no_mangle)] - | ^^^^^^^^^^^^^^^^^^^^ `#[unsafe(no_mangle)]` is ignored + | ^^^^^^^^^^^^^^^^^^^^ `#[no_mangle]` is ignored | note: `#[export_name]` takes precedence --> $DIR/mixed_export_name_and_no_mangle.rs:13:1 | LL | #[export_name = "baz"] | ^^^^^^^^^^^^^^^^^^^^^^ -help: remove the `#[unsafe(no_mangle)]` attribute +help: remove the `#[no_mangle]` attribute | LL - #[unsafe(no_mangle)] | diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.fixed b/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.fixed new file mode 100644 index 0000000000000..581cb200770ab --- /dev/null +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.fixed @@ -0,0 +1,15 @@ +// issue: rust-lang/rust#47446 +//@ run-rustfix +//@ check-pass +//@ edition:2024 + +#![warn(unused_attributes)] +//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[unsafe(export_name)]` [unused_attributes] +#[unsafe(export_name = "foo")] +pub fn bar() {} + +//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[unsafe(export_name)]` [unused_attributes] +#[unsafe(export_name = "baz")] +pub fn bak() {} + +fn main() {} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.rs b/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.rs new file mode 100644 index 0000000000000..1e4a06132f299 --- /dev/null +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.rs @@ -0,0 +1,17 @@ +// issue: rust-lang/rust#47446 +//@ run-rustfix +//@ check-pass +//@ edition:2024 + +#![warn(unused_attributes)] +#[unsafe(no_mangle)] +//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[unsafe(export_name)]` [unused_attributes] +#[unsafe(export_name = "foo")] +pub fn bar() {} + +#[unsafe(no_mangle)] +//~^ WARN `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[unsafe(export_name)]` [unused_attributes] +#[unsafe(export_name = "baz")] +pub fn bak() {} + +fn main() {} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.stderr b/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.stderr new file mode 100644 index 0000000000000..09804f9f92b68 --- /dev/null +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle_2024.stderr @@ -0,0 +1,39 @@ +warning: `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[unsafe(export_name)]` + --> $DIR/mixed_export_name_and_no_mangle_2024.rs:7:1 + | +LL | #[unsafe(no_mangle)] + | ^^^^^^^^^^^^^^^^^^^^ `#[unsafe(no_mangle)]` is ignored + | +note: `#[unsafe(export_name)]` takes precedence + --> $DIR/mixed_export_name_and_no_mangle_2024.rs:9:1 + | +LL | #[unsafe(export_name = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/mixed_export_name_and_no_mangle_2024.rs:6:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ +help: remove the `#[unsafe(no_mangle)]` attribute + | +LL - #[unsafe(no_mangle)] + | + +warning: `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[unsafe(export_name)]` + --> $DIR/mixed_export_name_and_no_mangle_2024.rs:12:1 + | +LL | #[unsafe(no_mangle)] + | ^^^^^^^^^^^^^^^^^^^^ `#[unsafe(no_mangle)]` is ignored + | +note: `#[unsafe(export_name)]` takes precedence + --> $DIR/mixed_export_name_and_no_mangle_2024.rs:14:1 + | +LL | #[unsafe(export_name = "baz")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove the `#[unsafe(no_mangle)]` attribute + | +LL - #[unsafe(no_mangle)] + | + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index a55be99fc0be5..02a95ed3e9082 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -28,6 +28,10 @@ mod v20 { impl v17 { //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} pub const fn v21() -> v18 { //~^ ERROR cannot find type `v18` in this scope v18 { _p: () } diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index b73611c79b291..cf0bdd0e9a150 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:38:15 + --> $DIR/unevaluated-const-ice-119731.rs:42:15 | LL | pub use v20::{v13, v17}; | ^^^ @@ -23,7 +23,7 @@ LL | pub const fn v21() -> v18 {} | ^^^ help: a type alias with a similar name exists: `v11` error[E0412]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:31:31 + --> $DIR/unevaluated-const-ice-119731.rs:35:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -32,7 +32,7 @@ LL | pub const fn v21() -> v18 { | ^^^ help: a type alias with a similar name exists: `v11` error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:33:13 + --> $DIR/unevaluated-const-ice-119731.rs:37:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -86,6 +86,38 @@ LL | impl v17 { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0592]: duplicate definitions with name `v21` --> $DIR/unevaluated-const-ice-119731.rs:23:9 | @@ -95,7 +127,7 @@ LL | pub const fn v21() -> v18 {} LL | pub const fn v21() -> v18 { | ------------------------- other definition for `v21` -error: aborting due to 10 previous errors; 2 warnings emitted +error: aborting due to 14 previous errors; 2 warnings emitted Some errors have detailed explanations: E0412, E0422, E0425, E0432, E0592. For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.rs b/tests/ui/consts/const-mut-refs/issue-76510.rs index 6ebbd4e50f6df..3b248d77a6b9a 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.rs +++ b/tests/ui/consts/const-mut-refs/issue-76510.rs @@ -1,7 +1,7 @@ use std::mem::{transmute, ManuallyDrop}; const S: &'static mut str = &mut " hello "; -//~^ ERROR: mutable references are not allowed in the final value of constants +//~^ ERROR: mutable borrows of lifetime-extended temporaries const fn trigger() -> [(); unsafe { let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); diff --git a/tests/ui/consts/const-mut-refs/issue-76510.stderr b/tests/ui/consts/const-mut-refs/issue-76510.stderr index aff86e83578d7..6d5dac268e532 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.stderr +++ b/tests/ui/consts/const-mut-refs/issue-76510.stderr @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in the final value of constants +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/issue-76510.rs:3:29 | LL | const S: &'static mut str = &mut " hello "; diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs index 28facc1888600..2af92bd1b9d9d 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -12,13 +12,13 @@ const A: *const i32 = &4; // It could be made sound to allow it to compile, // but we do not want to allow this to compile, // as that would be an enormous footgun in oli-obk's opinion. -const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed +const B: *mut i32 = &mut 4; //~ ERROR mutable borrows of lifetime-extended temporaries // Ok, no actual mutable allocation exists const B2: Option<&mut i32> = None; // Not ok, can't prove that no mutable allocation ends up in final value -const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR mutable references are not allowed +const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR mutable borrows of lifetime-extended temporaries const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) } const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed @@ -26,8 +26,10 @@ const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped // Not ok, since it points to read-only memory. const IMMUT_MUT_REF: &mut u16 = unsafe { mem::transmute(&13) }; //~^ ERROR pointing to read-only memory +static IMMUT_MUT_REF_STATIC: &mut u16 = unsafe { mem::transmute(&13) }; +//~^ ERROR pointing to read-only memory -// Ok, because no references to mutable data exist here, since the `{}` moves +// Ok, because no borrows of mutable data exist here, since the `{}` moves // its value and then takes a reference to that. const C: *const i32 = &{ let mut x = 42; @@ -67,13 +69,13 @@ unsafe impl Sync for SyncPtr {} // (This relies on `SyncPtr` being a curly brace struct.) // However, we intern the inner memory as read-only, so this must be rejected. static RAW_MUT_CAST_S: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; -//~^ ERROR mutable references are not allowed +//~^ ERROR mutable borrows of lifetime-extended temporaries static RAW_MUT_COERCE_S: SyncPtr = SyncPtr { x: &mut 0 }; -//~^ ERROR mutable references are not allowed +//~^ ERROR mutable borrows of lifetime-extended temporaries const RAW_MUT_CAST_C: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; -//~^ ERROR mutable references are not allowed +//~^ ERROR mutable borrows of lifetime-extended temporaries const RAW_MUT_COERCE_C: SyncPtr = SyncPtr { x: &mut 0 }; -//~^ ERROR mutable references are not allowed +//~^ ERROR mutable borrows of lifetime-extended temporaries fn main() { println!("{}", unsafe { *A }); diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 122e5c1bdf0ae..a55ccf71bc4e9 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -1,10 +1,10 @@ -error[E0764]: mutable references are not allowed in the final value of constants +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/mut_ref_in_final.rs:15:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ -error[E0764]: mutable references are not allowed in the final value of constants +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/mut_ref_in_final.rs:21:35 | LL | const B3: Option<&mut i32> = Some(&mut 42); @@ -31,8 +31,19 @@ LL | const IMMUT_MUT_REF: &mut u16 = unsafe { mem::transmute(&13) }; HEX_DUMP } +error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory + --> $DIR/mut_ref_in_final.rs:29:1 + | +LL | static IMMUT_MUT_REF_STATIC: &mut u16 = unsafe { mem::transmute(&13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:50:65 + --> $DIR/mut_ref_in_final.rs:52:65 | LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -42,7 +53,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:53:67 + --> $DIR/mut_ref_in_final.rs:55:67 | LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -52,7 +63,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:56:71 + --> $DIR/mut_ref_in_final.rs:58:71 | LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -61,31 +72,31 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` -error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/mut_ref_in_final.rs:69:53 +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed + --> $DIR/mut_ref_in_final.rs:71:53 | LL | static RAW_MUT_CAST_S: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ -error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/mut_ref_in_final.rs:71:54 +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed + --> $DIR/mut_ref_in_final.rs:73:54 | LL | static RAW_MUT_COERCE_S: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:73:52 +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed + --> $DIR/mut_ref_in_final.rs:75:52 | LL | const RAW_MUT_CAST_C: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ -error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:75:53 +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed + --> $DIR/mut_ref_in_final.rs:77:53 | LL | const RAW_MUT_COERCE_C: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0080, E0716, E0764. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 2707e8a14ec38..1ae901f1653a8 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -16,7 +16,7 @@ static mut BUFFER: i32 = 42; const fn helper() -> Option<&'static mut i32> { unsafe { Some(&mut *std::ptr::addr_of_mut!(BUFFER)) } } -const MUT: Option<&mut i32> = helper(); //~ ERROR encountered reference to mutable +const MUT: Option<&mut i32> = helper(); //~ ERROR encountered mutable reference const fn helper_int2ptr() -> Option<&'static mut i32> { unsafe { // Undefined behaviour (integer as pointer), who doesn't love tests like this. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index 6456587b77a48..302e342bce61a 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,4 +1,4 @@ -error[E0080]: constructing invalid value at ..0: encountered reference to mutable memory in `const` +error[E0080]: constructing invalid value at ..0: encountered mutable reference in `const` value --> $DIR/mut_ref_in_final_dynamic_check.rs:19:1 | LL | const MUT: Option<&mut i32> = helper(); diff --git a/tests/ui/consts/const-promoted-opaque.atomic.stderr b/tests/ui/consts/const-promoted-opaque.atomic.stderr index 9c0c969d586ce..337bfa4137a9e 100644 --- a/tests/ui/consts/const-promoted-opaque.atomic.stderr +++ b/tests/ui/consts/const-promoted-opaque.atomic.stderr @@ -7,11 +7,11 @@ LL | LL | }; | - value is dropped here -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/const-promoted-opaque.rs:36:19 | LL | const BAZ: &Foo = &FOO; - | ^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary error[E0716]: temporary value dropped while borrowed --> $DIR/const-promoted-opaque.rs:40:26 diff --git a/tests/ui/consts/const-promoted-opaque.rs b/tests/ui/consts/const-promoted-opaque.rs index 188dacd100343..9ad2b108ca78a 100644 --- a/tests/ui/consts/const-promoted-opaque.rs +++ b/tests/ui/consts/const-promoted-opaque.rs @@ -34,7 +34,7 @@ const BAR: () = { }; const BAZ: &Foo = &FOO; -//[atomic]~^ ERROR: constants cannot refer to interior mutable data +//[atomic]~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries fn main() { let _: &'static _ = &FOO; diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr index bf17d76a092bf..b127f83d8853c 100644 --- a/tests/ui/consts/const-size_of-cycle.stderr +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -11,13 +11,17 @@ LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires computing layout of `[u8; std::mem::size_of::()]`... - = note: ...which requires normalizing `[u8; std::mem::size_of::()]`... +note: ...which requires normalizing `[u8; std::mem::size_of::()]`... + --> $DIR/const-size_of-cycle.rs:2:17 + | +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `Foo` is well-formed - --> $DIR/const-size_of-cycle.rs:1:1 + --> $DIR/const-size_of-cycle.rs:2:17 | -LL | struct Foo { - | ^^^^^^^^^^ +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_refs_to_static.rs b/tests/ui/consts/const_refs_to_static.rs index 3c59697e8eda4..187fab86a8948 100644 --- a/tests/ui/consts/const_refs_to_static.rs +++ b/tests/ui/consts/const_refs_to_static.rs @@ -1,4 +1,5 @@ //@ run-pass +use std::sync::atomic::AtomicU32; static S: i32 = 0; static mut S_MUT: i32 = 0; @@ -10,9 +11,13 @@ const C1_READ: () = { }; const C2: *const i32 = std::ptr::addr_of!(S_MUT); +static FOO: AtomicU32 = AtomicU32::new(0); +const NOT_VALID_AS_PATTERN: &'static AtomicU32 = &FOO; + fn main() { assert_eq!(*C1, 0); assert_eq!(unsafe { *C2 }, 0); // Computing this pattern will read from an immutable static. That's fine. assert!(matches!(&0, C1)); + let _val = NOT_VALID_AS_PATTERN; } diff --git a/tests/ui/consts/const_refs_to_static_fail.rs b/tests/ui/consts/const_refs_to_static_fail.rs index b8bab91e005db..5bb9ca0a65e39 100644 --- a/tests/ui/consts/const_refs_to_static_fail.rs +++ b/tests/ui/consts/const_refs_to_static_fail.rs @@ -9,13 +9,23 @@ use std::cell::SyncUnsafeCell; static S: SyncUnsafeCell = SyncUnsafeCell::new(0); static mut S_MUT: i32 = 0; -const C1: &SyncUnsafeCell = &S; //~ERROR encountered reference to mutable memory +const C1: &SyncUnsafeCell = &S; const C1_READ: () = unsafe { - assert!(*C1.get() == 0); + assert!(*C1.get() == 0); //~ERROR constant accesses mutable global memory }; const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) }; const C2_READ: () = unsafe { assert!(*C2 == 0); //~ERROR constant accesses mutable global memory }; -fn main() {} +const BAD_PATTERN: &i32 = { + static mut S: i32 = 0; + unsafe { &mut S } +}; + +fn main() { + match &0 { + BAD_PATTERN => {}, //~ ERROR cannot be used as pattern + _ => {}, + } +} diff --git a/tests/ui/consts/const_refs_to_static_fail.stderr b/tests/ui/consts/const_refs_to_static_fail.stderr index 86d6c11dc0c31..c567b3e0ce1f4 100644 --- a/tests/ui/consts/const_refs_to_static_fail.stderr +++ b/tests/ui/consts/const_refs_to_static_fail.stderr @@ -1,19 +1,8 @@ -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/const_refs_to_static_fail.rs:12:1 - | -LL | const C1: &SyncUnsafeCell = &S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - -note: erroneous constant encountered - --> $DIR/const_refs_to_static_fail.rs:14:14 +error[E0080]: constant accesses mutable global memory + --> $DIR/const_refs_to_static_fail.rs:14:13 | LL | assert!(*C1.get() == 0); - | ^^ + | ^^^^^^^^^ evaluation of `C1_READ` failed here error[E0080]: constant accesses mutable global memory --> $DIR/const_refs_to_static_fail.rs:18:13 @@ -21,6 +10,14 @@ error[E0080]: constant accesses mutable global memory LL | assert!(*C2 == 0); | ^^^ evaluation of `C2_READ` failed here -error: aborting due to 2 previous errors +error: constant BAD_PATTERN cannot be used as pattern + --> $DIR/const_refs_to_static_fail.rs:28:9 + | +LL | BAD_PATTERN => {}, + | ^^^^^^^^^^^ + | + = note: constants that reference mutable or external memory cannot be used as pattern + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.rs b/tests/ui/consts/const_refs_to_static_fail_invalid.rs index 34ed8540f3fdc..229b9fdcc6027 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.rs +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.rs @@ -23,11 +23,10 @@ fn extern_() { } const C: &i8 = unsafe { &S }; - //~^ERROR: `extern` static // This must be rejected here (or earlier), since the pattern cannot be read. match &0 { - C => {} // ok, `const` already emitted an error + C => {} //~ ERROR cannot be used as pattern _ => {} } } @@ -36,12 +35,11 @@ fn mutable() { static mut S_MUT: i32 = 0; const C: &i32 = unsafe { &S_MUT }; - //~^ERROR: encountered reference to mutable memory // This *must not build*, the constant we are matching against // could change its value! match &42 { - C => {} // ok, `const` already emitted an error + C => {} //~ ERROR cannot be used as pattern _ => {} } } diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr index 8a034aa00bc56..8be8b4bc50f50 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr @@ -9,27 +9,21 @@ LL | const C: &bool = unsafe { std::mem::transmute(&S) }; HEX_DUMP } -error[E0080]: constructing invalid value: encountered reference to `extern` static in `const` - --> $DIR/const_refs_to_static_fail_invalid.rs:25:5 +error: constant extern_::C cannot be used as pattern + --> $DIR/const_refs_to_static_fail_invalid.rs:29:9 | -LL | const C: &i8 = unsafe { &S }; - | ^^^^^^^^^^^^ it is undefined behavior to use this value +LL | C => {} + | ^ | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + = note: constants that reference mutable or external memory cannot be used as pattern -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/const_refs_to_static_fail_invalid.rs:38:5 +error: constant mutable::C cannot be used as pattern + --> $DIR/const_refs_to_static_fail_invalid.rs:42:9 | -LL | const C: &i32 = unsafe { &S_MUT }; - | ^^^^^^^^^^^^^ it is undefined behavior to use this value +LL | C => {} + | ^ | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + = note: constants that reference mutable or external memory cannot be used as pattern error: aborting due to 3 previous errors diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs index 40fc02cf64466..ae101927fd4e7 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.rs +++ b/tests/ui/consts/issue-17718-const-bad-values.rs @@ -5,10 +5,10 @@ #![allow(static_mut_refs)] const C1: &'static mut [usize] = &mut []; -//~^ ERROR: mutable references are not allowed +//~^ ERROR: mutable borrows of lifetime-extended temporaries static mut S: i32 = 3; const C2: &'static mut i32 = unsafe { &mut S }; -//~^ ERROR: reference to mutable memory +//~^ ERROR: encountered mutable reference fn main() {} diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr index effb614b15bce..f0b02bdbc4554 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.stderr +++ b/tests/ui/consts/issue-17718-const-bad-values.stderr @@ -1,10 +1,10 @@ -error[E0764]: mutable references are not allowed in the final value of constants +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/issue-17718-const-bad-values.rs:7:34 | LL | const C1: &'static mut [usize] = &mut []; | ^^^^^^^ -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` +error[E0080]: constructing invalid value: encountered mutable reference in `const` value --> $DIR/issue-17718-const-bad-values.rs:11:1 | LL | const C2: &'static mut i32 = unsafe { &mut S }; diff --git a/tests/ui/consts/issue-17718-const-borrow.rs b/tests/ui/consts/issue-17718-const-borrow.rs index 89316dbd5c41a..541d27965f249 100644 --- a/tests/ui/consts/issue-17718-const-borrow.rs +++ b/tests/ui/consts/issue-17718-const-borrow.rs @@ -2,13 +2,13 @@ use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); const B: &'static UnsafeCell = &A; -//~^ ERROR: cannot refer to interior mutable +//~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries struct C { a: UnsafeCell } const D: C = C { a: UnsafeCell::new(1) }; const E: &'static UnsafeCell = &D.a; -//~^ ERROR: cannot refer to interior mutable +//~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries const F: &'static C = &D; -//~^ ERROR: cannot refer to interior mutable +//~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries fn main() {} diff --git a/tests/ui/consts/issue-17718-const-borrow.stderr b/tests/ui/consts/issue-17718-const-borrow.stderr index e3ff6c923ad7f..962a81e70b3e8 100644 --- a/tests/ui/consts/issue-17718-const-borrow.stderr +++ b/tests/ui/consts/issue-17718-const-borrow.stderr @@ -1,20 +1,20 @@ -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/issue-17718-const-borrow.rs:4:39 | LL | const B: &'static UnsafeCell = &A; - | ^^ this borrow of an interior mutable value may end up in the final value + | ^^ this borrow of an interior mutable value refers to a lifetime-extended temporary -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/issue-17718-const-borrow.rs:9:39 | LL | const E: &'static UnsafeCell = &D.a; - | ^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/issue-17718-const-borrow.rs:11:23 | LL | const F: &'static C = &D; - | ^^ this borrow of an interior mutable value may end up in the final value + | ^^ this borrow of an interior mutable value refers to a lifetime-extended temporary error: aborting due to 3 previous errors diff --git a/tests/ui/consts/issue-44415.stderr b/tests/ui/consts/issue-44415.stderr index 641945fce9fd4..0e3f2e6199f76 100644 --- a/tests/ui/consts/issue-44415.stderr +++ b/tests/ui/consts/issue-44415.stderr @@ -11,13 +11,17 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires computing layout of `[u8; unsafe { intrinsics::size_of::() }]`... - = note: ...which requires normalizing `[u8; unsafe { intrinsics::size_of::() }]`... +note: ...which requires normalizing `[u8; unsafe { intrinsics::size_of::() }]`... + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `Foo` is well-formed - --> $DIR/issue-44415.rs:5:1 + --> $DIR/issue-44415.rs:6:17 | -LL | struct Foo { - | ^^^^^^^^^^ +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs index 6cc670943463b..eb78b5335cba9 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -20,7 +20,7 @@ static mut MUTABLE: u32 = 0; const READ_MUT: u32 = unsafe { MUTABLE }; //~ERROR constant accesses mutable global memory // Evaluating this does not read anything mutable, but validation does, so this should error. -const REF_INTERIOR_MUT: &usize = { //~ ERROR encountered reference to mutable memory +const REF_INTERIOR_MUT: &usize = { static FOO: AtomicUsize = AtomicUsize::new(0); unsafe { &*(&FOO as *const _ as *const usize) } }; @@ -30,6 +30,13 @@ static MY_STATIC: u8 = 4; const REF_IMMUT: &u8 = &MY_STATIC; const READ_IMMUT: u8 = *REF_IMMUT; +fn foo() { + match &0 { + REF_INTERIOR_MUT => {}, //~ ERROR cannot be used as pattern + _ => {}, + } +} + fn main() {} //~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr index eed3b4d906596..6b70a211a72cc 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -16,16 +16,13 @@ error[E0080]: constant accesses mutable global memory LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ evaluation of `READ_MUT` failed here -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/const_refers_to_static.rs:23:1 +error: constant REF_INTERIOR_MUT cannot be used as pattern + --> $DIR/const_refers_to_static.rs:35:9 | -LL | const REF_INTERIOR_MUT: &usize = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value +LL | REF_INTERIOR_MUT => {}, + | ^^^^^^^^^^^^^^^^ | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + = note: constants that reference mutable or external memory cannot be used as pattern warning: skipping const checks | diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index 6c7e78356616c..cb093305429d4 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -11,18 +11,15 @@ extern crate static_cross_crate; // Sneaky: reference to a mutable static. // Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking! const SLICE_MUT: &[u8; 1] = { - //~^ ERROR encountered reference to mutable memory unsafe { &static_cross_crate::ZERO } }; const U8_MUT: &u8 = { - //~^ ERROR encountered reference to mutable memory unsafe { &static_cross_crate::ZERO[0] } }; // Also test indirection that reads from other static. const U8_MUT2: &u8 = { - //~^ ERROR encountered reference to mutable memory unsafe { &(*static_cross_crate::ZERO_REF)[0] } }; const U8_MUT3: &u8 = { @@ -37,14 +34,14 @@ const U8_MUT3: &u8 = { pub fn test(x: &[u8; 1]) -> bool { match x { - SLICE_MUT => true, // ok, `const` error already emitted + SLICE_MUT => true, //~ ERROR cannot be used as pattern &[1..] => false, } } pub fn test2(x: &u8) -> bool { match x { - U8_MUT => true, // ok, `const` error already emitted + U8_MUT => true, //~ ERROR cannot be used as pattern &(1..) => false, } } @@ -53,7 +50,7 @@ pub fn test2(x: &u8) -> bool { // the errors above otherwise stop compilation too early? pub fn test3(x: &u8) -> bool { match x { - U8_MUT2 => true, // ok, `const` error already emitted + U8_MUT2 => true, //~ ERROR cannot be used as pattern &(1..) => false, } } diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index 8af3a1948f0f3..d753506cc94e3 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -1,41 +1,32 @@ -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/const_refers_to_static_cross_crate.rs:13:1 - | -LL | const SLICE_MUT: &[u8; 1] = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value +error[E0080]: constant accesses mutable global memory + --> $DIR/const_refers_to_static_cross_crate.rs:27:15 | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } +LL | match static_cross_crate::OPT_ZERO { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `U8_MUT3` failed here -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/const_refers_to_static_cross_crate.rs:18:1 +error: constant SLICE_MUT cannot be used as pattern + --> $DIR/const_refers_to_static_cross_crate.rs:37:9 | -LL | const U8_MUT: &u8 = { - | ^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value +LL | SLICE_MUT => true, + | ^^^^^^^^^ | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + = note: constants that reference mutable or external memory cannot be used as pattern -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/const_refers_to_static_cross_crate.rs:24:1 +error: constant U8_MUT cannot be used as pattern + --> $DIR/const_refers_to_static_cross_crate.rs:44:9 | -LL | const U8_MUT2: &u8 = { - | ^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value +LL | U8_MUT => true, + | ^^^^^^ | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } + = note: constants that reference mutable or external memory cannot be used as pattern -error[E0080]: constant accesses mutable global memory - --> $DIR/const_refers_to_static_cross_crate.rs:30:15 +error: constant U8_MUT2 cannot be used as pattern + --> $DIR/const_refers_to_static_cross_crate.rs:53:9 | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `U8_MUT3` failed here +LL | U8_MUT2 => true, + | ^^^^^^^ + | + = note: constants that reference mutable or external memory cannot be used as pattern error: aborting due to 4 previous errors diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index 63d243f892cd0..2e95393ccbf56 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -26,7 +26,7 @@ const BLUNT: &mut i32 = &mut 42; //~^ ERROR: pointing to read-only memory const SUBTLE: &mut i32 = unsafe { - //~^ ERROR: constructing invalid value: encountered reference to mutable memory in `const` + //~^ ERROR: encountered mutable reference static mut STATIC: i32 = 0; &mut STATIC }; @@ -65,7 +65,10 @@ static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as // # Check for consts pointing to mutable memory static mut MUTABLE: i32 = 42; -const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; //~ ERROR encountered reference to mutable memory +const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; // OK, as long as it is not used as a pattern. + +// This fails since `&*MUTABLE_REF` is basically a copy of `MUTABLE_REF`, but we +// can't read from that static as it is mutable. static mut MUTABLE_REF: &mut i32 = &mut 42; const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; //~^ ERROR accesses mutable global memory diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 22860e4f6d9b0..137efde44b312 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -43,7 +43,7 @@ LL | const BLUNT: &mut i32 = &mut 42; HEX_DUMP } -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` +error[E0080]: constructing invalid value: encountered mutable reference in `const` value --> $DIR/mutable_references.rs:28:1 | LL | const SUBTLE: &mut i32 = unsafe { @@ -98,49 +98,38 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const HEX_DUMP } -error[E0080]: constructing invalid value: encountered reference to mutable memory in `const` - --> $DIR/mutable_references.rs:68:1 - | -LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - error[E0080]: constant accesses mutable global memory - --> $DIR/mutable_references.rs:70:43 + --> $DIR/mutable_references.rs:73:43 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^^^ evaluation of `POINTS_TO_MUTABLE2` failed here error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:73:1 + --> $DIR/mutable_references.rs:76:1 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:76:1 + --> $DIR/mutable_references.rs:79:1 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:96:1 + --> $DIR/mutable_references.rs:99:1 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:99:1 + --> $DIR/mutable_references.rs:102:1 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:106:5 + --> $DIR/mutable_references.rs:109:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -188,37 +177,37 @@ help: skipping check that does not even have a feature gate LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:73:45 + --> $DIR/mutable_references.rs:76:45 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:76:46 + --> $DIR/mutable_references.rs:79:46 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:81:47 + --> $DIR/mutable_references.rs:84:47 | LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:93:51 + --> $DIR/mutable_references.rs:96:51 | LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:96:49 + --> $DIR/mutable_references.rs:99:49 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:99:51 + --> $DIR/mutable_references.rs:102:51 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 17 previous errors; 1 warning emitted +error: aborting due to 16 previous errors; 1 warning emitted Some errors have detailed explanations: E0080, E0594. For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/partial_qualif.rs b/tests/ui/consts/partial_qualif.rs index 7c28b8b8a628e..6770e138eca0f 100644 --- a/tests/ui/consts/partial_qualif.rs +++ b/tests/ui/consts/partial_qualif.rs @@ -3,7 +3,7 @@ use std::cell::Cell; const FOO: &(Cell, bool) = { let mut a = (Cell::new(0), false); a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)` - &{a} //~ ERROR cannot refer to interior mutable + &{a} //~ ERROR interior mutable shared borrows of lifetime-extended temporaries }; fn main() {} diff --git a/tests/ui/consts/partial_qualif.stderr b/tests/ui/consts/partial_qualif.stderr index 05e0eeee13329..eb1a388ddee90 100644 --- a/tests/ui/consts/partial_qualif.stderr +++ b/tests/ui/consts/partial_qualif.stderr @@ -1,8 +1,8 @@ -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/partial_qualif.rs:6:5 | LL | &{a} - | ^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary error: aborting due to 1 previous error diff --git a/tests/ui/consts/qualif_overwrite.rs b/tests/ui/consts/qualif_overwrite.rs index aae4e41ffd7ee..3b494caa2c118 100644 --- a/tests/ui/consts/qualif_overwrite.rs +++ b/tests/ui/consts/qualif_overwrite.rs @@ -7,7 +7,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = Some(Cell::new(0)); a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a} //~ ERROR cannot refer to interior mutable + &{a} //~ ERROR interior mutable shared borrows of lifetime-extended temporaries }; fn main() {} diff --git a/tests/ui/consts/qualif_overwrite.stderr b/tests/ui/consts/qualif_overwrite.stderr index 976cf7bd79ebb..92430a89b9ed8 100644 --- a/tests/ui/consts/qualif_overwrite.stderr +++ b/tests/ui/consts/qualif_overwrite.stderr @@ -1,8 +1,8 @@ -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/qualif_overwrite.rs:10:5 | LL | &{a} - | ^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary error: aborting due to 1 previous error diff --git a/tests/ui/consts/qualif_overwrite_2.rs b/tests/ui/consts/qualif_overwrite_2.rs index 1819d9a6d203d..e06fd3225539d 100644 --- a/tests/ui/consts/qualif_overwrite_2.rs +++ b/tests/ui/consts/qualif_overwrite_2.rs @@ -5,7 +5,7 @@ use std::cell::Cell; const FOO: &Option> = { let mut a = (Some(Cell::new(0)),); a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` - &{a.0} //~ ERROR cannot refer to interior mutable + &{a.0} //~ ERROR interior mutable shared borrows of lifetime-extended temporaries }; fn main() {} diff --git a/tests/ui/consts/qualif_overwrite_2.stderr b/tests/ui/consts/qualif_overwrite_2.stderr index a107c4a5c6dbf..a994ab61ea7b3 100644 --- a/tests/ui/consts/qualif_overwrite_2.stderr +++ b/tests/ui/consts/qualif_overwrite_2.stderr @@ -1,8 +1,8 @@ -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/qualif_overwrite_2.rs:8:5 | LL | &{a.0} - | ^^^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary error: aborting due to 1 previous error diff --git a/tests/ui/consts/refs-to-cell-in-final.rs b/tests/ui/consts/refs-to-cell-in-final.rs index 844b140cff2b5..28a26f8690919 100644 --- a/tests/ui/consts/refs-to-cell-in-final.rs +++ b/tests/ui/consts/refs-to-cell-in-final.rs @@ -11,9 +11,9 @@ unsafe impl Sync for SyncPtr {} // The resulting constant would pass all validation checks, so it is crucial that this gets rejected // by static const checks! static RAW_SYNC_S: SyncPtr> = SyncPtr { x: &Cell::new(42) }; -//~^ ERROR: cannot refer to interior mutable data +//~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; -//~^ ERROR: cannot refer to interior mutable data +//~^ ERROR: interior mutable shared borrows of lifetime-extended temporaries // This one does not get promoted because of `Drop`, and then enters interesting codepaths because // as a value it has no interior mutability, but as a type it does. See @@ -39,7 +39,7 @@ const NONE_EXPLICIT_PROMOTED: &'static Option> = { // Not okay, since we are borrowing something with interior mutability. const INTERIOR_MUT_VARIANT: &Option> = &{ - //~^ERROR: cannot refer to interior mutable data + //~^ERROR: interior mutable shared borrows of lifetime-extended temporaries let mut x = None; assert!(x.is_none()); x = Some(UnsafeCell::new(false)); diff --git a/tests/ui/consts/refs-to-cell-in-final.stderr b/tests/ui/consts/refs-to-cell-in-final.stderr index 8d82d94f4126f..41f7a23852cad 100644 --- a/tests/ui/consts/refs-to-cell-in-final.stderr +++ b/tests/ui/consts/refs-to-cell-in-final.stderr @@ -1,18 +1,18 @@ -error[E0492]: statics cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed --> $DIR/refs-to-cell-in-final.rs:13:54 | LL | static RAW_SYNC_S: SyncPtr> = SyncPtr { x: &Cell::new(42) }; - | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^^^^^^^^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary | = help: to fix this, the value can be extracted to a separate `static` item and then referenced -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/refs-to-cell-in-final.rs:15:53 | LL | const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; - | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value + | ^^^^^^^^^^^^^^ this borrow of an interior mutable value refers to a lifetime-extended temporary -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/refs-to-cell-in-final.rs:41:57 | LL | const INTERIOR_MUT_VARIANT: &Option> = &{ @@ -23,7 +23,7 @@ LL | | assert!(x.is_none()); LL | | x = Some(UnsafeCell::new(false)); LL | | x LL | | }; - | |_^ this borrow of an interior mutable value may end up in the final value + | |_^ this borrow of an interior mutable value refers to a lifetime-extended temporary error: aborting due to 3 previous errors diff --git a/tests/ui/consts/write_to_static_via_mut_ref.rs b/tests/ui/consts/write_to_static_via_mut_ref.rs index 82ac85bd2509a..6d3ddf01a2d21 100644 --- a/tests/ui/consts/write_to_static_via_mut_ref.rs +++ b/tests/ui/consts/write_to_static_via_mut_ref.rs @@ -1,4 +1,4 @@ -static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable references are not allowed +static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable borrows of lifetime-extended temporaries fn main() { assert_eq!(*OH_NO, 42); *OH_NO = 43; //~ ERROR cannot assign to `*OH_NO`, as `OH_NO` is an immutable static diff --git a/tests/ui/consts/write_to_static_via_mut_ref.stderr b/tests/ui/consts/write_to_static_via_mut_ref.stderr index 63ef788032f3c..76926e6949177 100644 --- a/tests/ui/consts/write_to_static_via_mut_ref.stderr +++ b/tests/ui/consts/write_to_static_via_mut_ref.stderr @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in the final value of statics +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed --> $DIR/write_to_static_via_mut_ref.rs:1:26 | LL | static OH_NO: &mut i32 = &mut 42; diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs index 8c685aad0308b..52b81c8a09d55 100644 --- a/tests/ui/error-codes/E0017.rs +++ b/tests/ui/error-codes/E0017.rs @@ -5,12 +5,12 @@ static X: i32 = 1; const C: i32 = 2; static mut M: i32 = 3; -const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed +const CR: &'static mut i32 = &mut C; //~ ERROR mutable borrows of lifetime-extended temporaries //~| WARN taking a mutable static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow immutable static item `X` as mutable -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable borrows of lifetime-extended temporaries //~| WARN taking a mutable fn main() {} diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr index 285d363592f8b..b1a94ca3e9da0 100644 --- a/tests/ui/error-codes/E0017.stderr +++ b/tests/ui/error-codes/E0017.stderr @@ -13,7 +13,7 @@ LL | const C: i32 = 2; | ^^^^^^^^^^^^ = note: `#[warn(const_item_mutation)]` on by default -error[E0764]: mutable references are not allowed in the final value of constants +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/E0017.rs:8:30 | LL | const CR: &'static mut i32 = &mut C; @@ -39,7 +39,7 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in the final value of statics +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed --> $DIR/E0017.rs:13:38 | LL | static CONST_REF: &'static mut i32 = &mut C; diff --git a/tests/ui/error-codes/E0492.stderr b/tests/ui/error-codes/E0492.stderr index 557c977e87d9c..fbbcf8f7d9285 100644 --- a/tests/ui/error-codes/E0492.stderr +++ b/tests/ui/error-codes/E0492.stderr @@ -1,14 +1,14 @@ -error[E0492]: constants cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a constant are not allowed --> $DIR/E0492.rs:4:33 | LL | const B: &'static AtomicUsize = &A; - | ^^ this borrow of an interior mutable value may end up in the final value + | ^^ this borrow of an interior mutable value refers to a lifetime-extended temporary -error[E0492]: statics cannot refer to interior mutable data +error[E0492]: interior mutable shared borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed --> $DIR/E0492.rs:5:34 | LL | static C: &'static AtomicUsize = &A; - | ^^ this borrow of an interior mutable value may end up in the final value + | ^^ this borrow of an interior mutable value refers to a lifetime-extended temporary | = help: to fix this, the value can be extracted to a separate `static` item and then referenced diff --git a/tests/ui/generic-const-items/assoc-const-AnonConst-ice-108220.rs b/tests/ui/generic-const-items/assoc-const-AnonConst-ice-108220.rs deleted file mode 100644 index f5babb67b5639..0000000000000 --- a/tests/ui/generic-const-items/assoc-const-AnonConst-ice-108220.rs +++ /dev/null @@ -1,35 +0,0 @@ -// ICE assertion failed: matches!(self.def_kind(ct.def.did), DefKind :: AnonConst) -// issue: rust-lang/rust#108220 -//@ check-pass - -#![feature(associated_const_equality)] -#![allow(unused)] - -use std::marker::PhantomData; - -pub struct NoPin; - -pub trait SetAlternate {} - -impl SetAlternate<0> for NoPin {} - -pub trait PinA { - const A: u8; -} - -impl PinA for NoPin { - const A: u8 = 0; -} - -pub trait Pins {} - -impl Pins for T where - T: PinA + SetAlternate -{ -} - -struct Serial(PhantomData); - -impl Serial where NoPin: Pins {} - -fn main() {} diff --git a/tests/ui/issues/issue-46604.rs b/tests/ui/issues/issue-46604.rs index 6ec6e7bdcb81e..03960941b2e5f 100644 --- a/tests/ui/issues/issue-46604.rs +++ b/tests/ui/issues/issue-46604.rs @@ -1,4 +1,4 @@ -static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR mutable references are not allowed +static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR mutable borrows of lifetime-extended temporaries fn write>(buffer: T) { } fn main() { diff --git a/tests/ui/issues/issue-46604.stderr b/tests/ui/issues/issue-46604.stderr index 7faa2d79ba483..f00f3f0d23fe6 100644 --- a/tests/ui/issues/issue-46604.stderr +++ b/tests/ui/issues/issue-46604.stderr @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in the final value of statics +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed --> $DIR/issue-46604.rs:1:25 | LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index df6cada6b06f5..3a520ffcb3df1 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -89,19 +89,6 @@ note: attribute also specified here LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:92:1 - | -LL | #[export_name = "exported_symbol_name"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:94:1 - | -LL | #[export_name = "exported_symbol_name2"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - error: unused attribute --> $DIR/unused-attr-duplicate.rs:102:1 | @@ -277,6 +264,19 @@ note: attribute also specified here LL | #[track_caller] | ^^^^^^^^^^^^^^^ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:92:1 + | +LL | #[export_name = "exported_symbol_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:94:1 + | +LL | #[export_name = "exported_symbol_name2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + error: unused attribute --> $DIR/unused-attr-duplicate.rs:98:1 | diff --git a/tests/ui/statics/check-immutable-mut-slices.rs b/tests/ui/statics/check-immutable-mut-slices.rs index 8f9680778aa03..9e5ca5059d6a8 100644 --- a/tests/ui/statics/check-immutable-mut-slices.rs +++ b/tests/ui/statics/check-immutable-mut-slices.rs @@ -1,6 +1,6 @@ // Checks that immutable static items can't have mutable slices static TEST: &'static mut [isize] = &mut []; -//~^ ERROR mutable references are not allowed +//~^ ERROR mutable borrows of lifetime-extended temporaries pub fn main() { } diff --git a/tests/ui/statics/check-immutable-mut-slices.stderr b/tests/ui/statics/check-immutable-mut-slices.stderr index 5cb35a7c21eb6..3552175565040 100644 --- a/tests/ui/statics/check-immutable-mut-slices.stderr +++ b/tests/ui/statics/check-immutable-mut-slices.stderr @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in the final value of statics +error[E0764]: mutable borrows of lifetime-extended temporaries in the top-level scope of a static are not allowed --> $DIR/check-immutable-mut-slices.rs:3:37 | LL | static TEST: &'static mut [isize] = &mut []; diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index 03e26615d7edc..f5cadc9f1830f 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -64,10 +64,10 @@ LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `accept0` is well-formed - --> $DIR/unsatisfied-const-trait-bound.rs:29:1 + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 | LL | fn accept0(_: Container<{ T::make() }>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0391]: cycle detected when caching mir of `accept1::{constant#0}` for CTFE