Auto merge of #143074 - compiler-errors:rollup-cv64hdh, r=compiler-errors
Rollup of 18 pull requests Successful merges: - rust-lang/rust#137843 (make RefCell unstably const) - rust-lang/rust#140942 (const-eval: allow constants to refer to mutable/external memory, but reject such constants as patterns) - rust-lang/rust#142549 (small iter.intersperse.fold() optimization) - rust-lang/rust#142637 (Remove some glob imports from the type system) - rust-lang/rust#142647 ([perf] Compute hard errors without diagnostics in impl_intersection_has_impossible_obligation) - rust-lang/rust#142700 (Remove incorrect comments in `Weak`) - rust-lang/rust#142927 (Add note to `find_const_ty_from_env`) - rust-lang/rust#142967 (Fix RwLock::try_write documentation for WouldBlock condition) - rust-lang/rust#142986 (Port `#[export_name]` to the new attribute parsing infrastructure) - rust-lang/rust#143001 (Rename run always ) - rust-lang/rust#143010 (Update `browser-ui-test` version to `0.20.7`) - rust-lang/rust#143015 (Add `sym::macro_pin` diagnostic item for `core::pin::pin!()`) - rust-lang/rust#143033 (Expand const-stabilized API links in relnotes) - rust-lang/rust#143041 (Remove cache for citool) - rust-lang/rust#143056 (Move an ACE test out of the GCI directory) - rust-lang/rust#143059 (Fix 1.88 relnotes) - rust-lang/rust#143067 (Tracking issue number for `iter_macro`) - rust-lang/rust#143073 (Fix some fixmes that were waiting for let chains) Failed merges: - rust-lang/rust#143020 (codegen_fn_attrs: make comment more precise) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e61dd437f3
158 changed files with 1249 additions and 916 deletions
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
|
|
@ -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.
|
||||
|
|
|
|||
20
RELEASES.md
20
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<T>::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)
|
||||
|
||||
|
||||
<a id="1.88.0-Cargo"></a>
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ impl AttributeKind {
|
|||
ConstStabilityIndirect => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DocComment { .. } => Yes,
|
||||
ExportName { .. } => Yes,
|
||||
Inline(..) => No,
|
||||
MacroTransparency(..) => Yes,
|
||||
Repr(..) => No,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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<S: Stage> SingleAttributeParser<S> for ColdParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ExportNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::export_name];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
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<Span>,
|
||||
|
|
|
|||
|
|
@ -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<ConstContinueParser>,
|
||||
Single<ConstStabilityIndirectParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<ExportNameParser>,
|
||||
Single<InlineParser>,
|
||||
Single<LoopMatchParser>,
|
||||
Single<MayDangleParser>,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Span>,
|
||||
hir_id: Option<HirId>,
|
||||
no_mangle: Option<Span>,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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,34 +208,24 @@ 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_borrow_escaping =
|
||||
mutable borrows of lifetime-extended temporaries in the top-level scope of a {const_eval_const_context} are not allowed
|
||||
.teach_note =
|
||||
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_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
|
||||
.teach_note =
|
||||
Pointers 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_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_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
|
||||
|
||||
const_eval_non_const_await =
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ty::ValTree<'tcx>, ValTreeCreationError<'tcx>>;
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
|
|||
|
|
@ -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<VariantIdx>,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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<Span>,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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()])
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
MatchExpressionArmCause, Obligation, PredicateObligation, PredicateObligations, SelectionError,
|
||||
};
|
||||
|
|
@ -430,7 +430,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
|
||||
}
|
||||
|
|
@ -548,7 +548,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
|
||||
|
|
@ -671,7 +671,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TyCtxt<'tcx>> + 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) =
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }) => {
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -603,10 +603,9 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> 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)]
|
||||
|
|
|
|||
|
|
@ -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<TyCtxt<'tcx>> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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}`
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl From<ReportedErrorInfo> 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<ReportedErrorInfo> 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<ErrorHandled> for ValTreeCreationError<'tcx> {
|
||||
fn from(err: ErrorHandled) -> Self {
|
||||
ValTreeCreationError::ErrorHandled(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> From<InterpErrorInfo<'tcx>> 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<ConstAlloc<'tcx>, ErrorHandled>;
|
||||
pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
|
||||
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, 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<Result<ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>;
|
||||
pub type EvalToValTreeResult<'tcx> = Result<ValTree<'tcx>, 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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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::ConstValue<'_>, mir::interpret::ErrorHandled> {
|
|||
type Result = [u8; size_of::<Result<mir::ConstValue<'static>, mir::interpret::ErrorHandled>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<Result<ty::ValTree<'_>, Ty<'_>>, mir::interpret::ErrorHandled> {
|
||||
type Result = [u8; size_of::<
|
||||
Result<Result<ty::ValTree<'static>, Ty<'static>>, mir::interpret::ErrorHandled>,
|
||||
>()];
|
||||
impl EraseType for EvalToValTreeResult<'_> {
|
||||
type Result = [u8; size_of::<EvalToValTreeResult<'static>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
|
||||
|
|
|
|||
|
|
@ -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<Result<ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>;
|
||||
|
||||
/// A type-level constant value.
|
||||
///
|
||||
/// Represents a typed, fully evaluated constant.
|
||||
|
|
|
|||
|
|
@ -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<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
binder: ty::Binder<'tcx, T>,
|
||||
|
|
|
|||
|
|
@ -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<T> {
|
|||
pub universe: UniverseIndex,
|
||||
pub bound: T,
|
||||
}
|
||||
impl Placeholder<BoundVar> {
|
||||
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<BoundRegion>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Ty<'tcx>>` 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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,11 +326,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
let kind_ty = args.kind_ty();
|
||||
let sig = args.coroutine_closure_sig().skip_binder();
|
||||
|
||||
// FIXME: let_chains
|
||||
let kind = kind_ty.to_opt_closure_kind();
|
||||
let coroutine_ty = if kind.is_some() && !args.tupled_upvars_ty().is_ty_var() {
|
||||
let closure_kind = kind.unwrap();
|
||||
if !closure_kind.extends(goal_kind) {
|
||||
let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
|
||||
&& !args.tupled_upvars_ty().is_ty_var()
|
||||
{
|
||||
if !kind.extends(goal_kind) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
|
@ -435,10 +434,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
let sig = args.coroutine_closure_sig().skip_binder();
|
||||
let mut nested = vec![];
|
||||
|
||||
// FIXME: let_chains
|
||||
let kind = kind_ty.to_opt_closure_kind();
|
||||
let coroutine_ty = if kind.is_some() && !args.tupled_upvars_ty().is_ty_var() {
|
||||
if !kind.unwrap().extends(goal_kind) {
|
||||
let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
|
||||
&& !args.tupled_upvars_ty().is_ty_var()
|
||||
{
|
||||
if !kind.extends(goal_kind) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ where
|
|||
ty::ConstKind::Bound(_, _) => 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)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1617,6 +1617,7 @@ symbols! {
|
|||
pie,
|
||||
pin,
|
||||
pin_ergonomics,
|
||||
pin_macro,
|
||||
platform_intrinsics,
|
||||
plugin,
|
||||
plugin_registrar,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
assert!(errors.is_empty(), "should not have ambiguities during second pass");
|
||||
|
||||
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
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<PredicateObligations<'tcx>, 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<T>: Unsize<TailField<U>>` predicate.
|
||||
|
|
|
|||
|
|
@ -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::<Result<Vec<_>, _>>()?;
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<I: Interner<Ty = Self>>:
|
||||
|
|
@ -538,6 +538,45 @@ pub trait PlaceholderLike<I: Interner>: Copy + Debug + Hash + Eq {
|
|||
fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
|
||||
}
|
||||
|
||||
pub trait PlaceholderConst<I: Interner>: PlaceholderLike<I, Bound = I::BoundConst> {
|
||||
fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty;
|
||||
}
|
||||
impl<I: Interner> PlaceholderConst<I> 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<Ty<'tcx>>` 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ pub trait Interner:
|
|||
type Const: Const<Self>;
|
||||
type ParamConst: Copy + Debug + Hash + Eq + ParamLike;
|
||||
type BoundConst: BoundVarLike<Self>;
|
||||
type PlaceholderConst: PlaceholderLike<Self, Bound = Self::BoundConst>;
|
||||
type PlaceholderConst: PlaceholderConst<Self>;
|
||||
type ValueConst: ValueConst<Self>;
|
||||
type ExprConst: ExprConst<Self>;
|
||||
type ValTree: Copy + Debug + Hash + Eq;
|
||||
|
|
@ -348,12 +348,6 @@ pub trait Interner:
|
|||
type UnsizingParams: Deref<Target = DenseBitSet<u32>>;
|
||||
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<T: TypeFoldable<Self>>(
|
||||
self,
|
||||
binder: ty::Binder<Self, T>,
|
||||
|
|
|
|||
|
|
@ -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<RcInner<T>>,
|
||||
alloc: A,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ArcInner<T>>,
|
||||
alloc: A,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T> RefCell<T> {
|
|||
#[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<T> RefCell<T> {
|
|||
/// ```
|
||||
#[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<T: ?Sized> RefCell<T> {
|
|||
#[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<T: ?Sized> RefCell<T> {
|
|||
#[stable(feature = "try_borrow", since = "1.13.0")]
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "debug_refcell", track_caller)]
|
||||
pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
|
||||
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
|
||||
pub const fn try_borrow(&self) -> Result<Ref<'_, T>, 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<T: ?Sized> RefCell<T> {
|
|||
#[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<T: ?Sized> RefCell<T> {
|
|||
#[stable(feature = "try_borrow", since = "1.13.0")]
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "debug_refcell", track_caller)]
|
||||
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
|
||||
#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
|
||||
pub const fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, 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<T: ?Sized> RefCell<T> {
|
|||
#[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<T: ?Sized> RefCell<T> {
|
|||
/// ```
|
||||
#[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<T: ?Sized> RefCell<T> {
|
|||
/// 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<T: ?Sized> RefCell<T> {
|
|||
/// ```
|
||||
#[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<BorrowCounter>) -> Option<BorrowRef<'b>> {
|
||||
const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> {
|
||||
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<T: ?Sized> Deref for Ref<'_, T> {
|
||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||
impl<T: ?Sized> 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<BorrowCounter>,
|
||||
}
|
||||
|
||||
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<BorrowCounter>) -> Option<BorrowRefMut<'b>> {
|
||||
const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRefMut<'b>> {
|
||||
// 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<T: ?Sized> Deref for RefMut<'_, T> {
|
||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||
impl<T: ?Sized> const Deref for RefMut<'_, T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
|
|
@ -1860,7 +1887,8 @@ impl<T: ?Sized> Deref for RefMut<'_, T> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> DerefMut for RefMut<'_, T> {
|
||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||
impl<T: ?Sized> 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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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)*) {
|
||||
|
|
|
|||
|
|
@ -1935,6 +1935,7 @@ unsafe impl<T: ?Sized> 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 $(,)?) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ impl<T: ?Sized> RwLock<T> {
|
|||
/// 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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ fn workspace_members(build: &Build) -> Vec<Package> {
|
|||
.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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ than building it.
|
|||
|
||||
let stage0_supported_target_list: HashSet<String> = 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!(
|
||||
"
|
||||
|
|
|
|||
|
|
@ -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<PathBuf> = 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()
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<Command> for BootstrapCommand {
|
|||
Self {
|
||||
command,
|
||||
failure_behavior: BehaviorOnFailure::Exit,
|
||||
run_always: false,
|
||||
run_in_dry_run: false,
|
||||
drop_bomb: DropBomb::arm(program),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue