commit
79c30b69e4
499 changed files with 5929 additions and 6216 deletions
|
|
@ -92,9 +92,6 @@ ast_passes_fn_body_extern = incorrect function inside `extern` block
|
|||
ast_passes_fn_param_c_var_args_not_last =
|
||||
`...` must be the last argument of a C-variadic function
|
||||
|
||||
ast_passes_fn_param_c_var_args_only =
|
||||
C-variadic function must be declared with at least one named argument
|
||||
|
||||
ast_passes_fn_param_doc_comment =
|
||||
documentation comments cannot be applied to function parameters
|
||||
.label = doc comments are not allowed here
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ impl<'a> AstValidator<'a> {
|
|||
|
||||
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
|
||||
self.check_decl_num_args(fn_decl);
|
||||
self.check_decl_cvaradic_pos(fn_decl);
|
||||
self.check_decl_cvariadic_pos(fn_decl);
|
||||
self.check_decl_attrs(fn_decl);
|
||||
self.check_decl_self_param(fn_decl, self_semantic);
|
||||
}
|
||||
|
|
@ -379,13 +379,11 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
|
||||
/// Emits an error if a function declaration has a variadic parameter in the
|
||||
/// beginning or middle of parameter list.
|
||||
/// Example: `fn foo(..., x: i32)` will emit an error.
|
||||
fn check_decl_cvariadic_pos(&self, fn_decl: &FnDecl) {
|
||||
match &*fn_decl.inputs {
|
||||
[Param { ty, span, .. }] => {
|
||||
if let TyKind::CVarArgs = ty.kind {
|
||||
self.dcx().emit_err(errors::FnParamCVarArgsOnly { span: *span });
|
||||
}
|
||||
}
|
||||
[ps @ .., _] => {
|
||||
for Param { ty, span, .. } in ps {
|
||||
if let TyKind::CVarArgs = ty.kind {
|
||||
|
|
|
|||
|
|
@ -92,13 +92,6 @@ pub struct FnParamTooMany {
|
|||
pub max_num_args: usize,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_fn_param_c_var_args_only)]
|
||||
pub struct FnParamCVarArgsOnly {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_fn_param_c_var_args_not_last)]
|
||||
pub struct FnParamCVarArgsNotLast {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_errors::Diag;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_infer::infer::canonical::Canonical;
|
||||
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use rustc_infer::infer::region_constraints::Constraint;
|
||||
|
|
@ -241,7 +242,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
|||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_prove_predicate_with_cause(&ocx, key, cause);
|
||||
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -287,7 +288,7 @@ where
|
|||
let (param_env, value) = key.into_parts();
|
||||
let _ = ocx.normalize(&cause, param_env, value.value);
|
||||
|
||||
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -318,7 +319,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
|||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
|
||||
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -342,6 +343,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
|||
) -> Option<Diag<'tcx>> {
|
||||
try_extract_error_from_region_constraints(
|
||||
mbcx.infcx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
self.region_constraints.as_ref().unwrap(),
|
||||
|
|
@ -358,6 +360,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
|||
#[instrument(skip(ocx), level = "debug")]
|
||||
fn try_extract_error_from_fulfill_cx<'tcx>(
|
||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
|
|
@ -368,6 +371,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||
let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
|
||||
try_extract_error_from_region_constraints(
|
||||
ocx.infcx,
|
||||
generic_param_scope,
|
||||
placeholder_region,
|
||||
error_region,
|
||||
®ion_constraints,
|
||||
|
|
@ -379,6 +383,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||
#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
|
||||
fn try_extract_error_from_region_constraints<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
region_constraints: &RegionConstraintData<'tcx>,
|
||||
|
|
@ -452,15 +457,18 @@ fn try_extract_error_from_region_constraints<'tcx>(
|
|||
RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
|
||||
}
|
||||
};
|
||||
NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
|
||||
if let SubregionOrigin::Subtype(trace) = cause {
|
||||
Some(
|
||||
infcx
|
||||
.err_ctxt()
|
||||
.report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
NiceRegionError::new(&infcx.err_ctxt(), generic_param_scope, error)
|
||||
.try_report_from_nll()
|
||||
.or_else(|| {
|
||||
if let SubregionOrigin::Subtype(trace) = cause {
|
||||
Some(
|
||||
infcx.err_ctxt().report_and_explain_type_error(
|
||||
*trace,
|
||||
TypeError::RegionsPlaceholderMismatch,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -361,6 +361,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
let diag = unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
self.mir_def_id(),
|
||||
span,
|
||||
named_ty,
|
||||
named_region,
|
||||
|
|
@ -453,7 +454,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// Check if we can use one of the "nice region errors".
|
||||
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
|
||||
let infer_err = self.infcx.err_ctxt();
|
||||
let nice = NiceRegionError::new_from_span(&infer_err, cause.span, o, f);
|
||||
let nice =
|
||||
NiceRegionError::new_from_span(&infer_err, self.mir_def_id(), cause.span, o, f);
|
||||
if let Some(diag) = nice.try_report_from_nll() {
|
||||
self.buffer_error(diag);
|
||||
return;
|
||||
|
|
@ -843,14 +845,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if *outlived_f != ty::ReStatic {
|
||||
return;
|
||||
}
|
||||
let suitable_region = self.infcx.tcx.is_suitable_region(f);
|
||||
let suitable_region = self.infcx.tcx.is_suitable_region(self.mir_def_id(), f);
|
||||
let Some(suitable_region) = suitable_region else {
|
||||
return;
|
||||
};
|
||||
|
||||
let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id);
|
||||
|
||||
let param = if let Some(param) = find_param_with_region(self.infcx.tcx, f, outlived_f) {
|
||||
let param = if let Some(param) =
|
||||
find_param_with_region(self.infcx.tcx, self.mir_def_id(), f, outlived_f)
|
||||
{
|
||||
param
|
||||
} else {
|
||||
return;
|
||||
|
|
@ -959,7 +963,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
let param = match find_param_with_region(tcx, f, o) {
|
||||
let param = match find_param_with_region(tcx, self.mir_def_id(), f, o) {
|
||||
Some(param) => param,
|
||||
None => return,
|
||||
};
|
||||
|
|
@ -1022,25 +1026,30 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
let Some((ty_sub, _)) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.is_suitable_region(sub)
|
||||
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region))
|
||||
let Some((ty_sub, _)) =
|
||||
self.infcx.tcx.is_suitable_region(self.mir_def_id(), sub).and_then(|anon_reg| {
|
||||
find_anon_type(self.infcx.tcx, self.mir_def_id(), sub, &anon_reg.bound_region)
|
||||
})
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some((ty_sup, _)) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.is_suitable_region(sup)
|
||||
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region))
|
||||
let Some((ty_sup, _)) =
|
||||
self.infcx.tcx.is_suitable_region(self.mir_def_id(), sup).and_then(|anon_reg| {
|
||||
find_anon_type(self.infcx.tcx, self.mir_def_id(), sup, &anon_reg.bound_region)
|
||||
})
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
|
||||
suggest_adding_lifetime_params(
|
||||
self.infcx.tcx,
|
||||
diag,
|
||||
self.mir_def_id(),
|
||||
sub,
|
||||
ty_sup,
|
||||
ty_sub,
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
|
|
|
|||
|
|
@ -289,7 +289,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
debug!("give_region_a_name: error_region = {:?}", error_region);
|
||||
match *error_region {
|
||||
ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
|
||||
let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
|
||||
let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id;
|
||||
let span = tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
|
||||
RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) }
|
||||
}),
|
||||
|
||||
|
|
@ -912,7 +913,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
};
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
let region_parent = tcx.parent(region.def_id);
|
||||
let region_def = tcx.generics_of(self.mir_def_id()).region_param(region, tcx).def_id;
|
||||
let region_parent = tcx.parent(region_def);
|
||||
let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
|
||||
return None;
|
||||
};
|
||||
|
|
@ -925,7 +927,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
Some(RegionName {
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::AnonRegionFromImplSignature(
|
||||
tcx.def_span(region.def_id),
|
||||
tcx.def_span(region_def),
|
||||
// FIXME(compiler-errors): Does this ever actually show up
|
||||
// anywhere other than the self type? I couldn't create an
|
||||
// example of a `'_` in the impl's trait being referenceable.
|
||||
|
|
|
|||
|
|
@ -327,6 +327,18 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
} else {
|
||||
codegen_fn_attrs.linkage = linkage;
|
||||
}
|
||||
if tcx.is_mutable_static(did.into()) {
|
||||
let mut diag = tcx.dcx().struct_span_err(
|
||||
attr.span,
|
||||
"mutable statics are not allowed with `#[linkage]`",
|
||||
);
|
||||
diag.note(
|
||||
"making the static mutable would allow changing which symbol the \
|
||||
static references rather than make the target of the symbol \
|
||||
mutable",
|
||||
);
|
||||
diag.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
sym::link_section => {
|
||||
|
|
@ -564,8 +576,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
lint::builtin::INLINE_NO_SANITIZE,
|
||||
hir_id,
|
||||
no_sanitize_span,
|
||||
"`no_sanitize` will have no effect after inlining",
|
||||
|lint| {
|
||||
lint.primary_message("`no_sanitize` will have no effect after inlining");
|
||||
lint.span_note(inline_span, "inlining requested here");
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
|||
}
|
||||
|
||||
if let ConstContext::Static(_) = ccx.const_kind() {
|
||||
err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
|
||||
err.note("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`");
|
||||
}
|
||||
|
||||
err
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ impl HasStaticRootDefId for DummyMachine {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
||||
interpret::compile_time_machine!(<'mir, 'tcx>);
|
||||
impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
|
||||
interpret::compile_time_machine!(<'tcx>);
|
||||
type MemoryKind = !;
|
||||
const PANIC_ON_ALLOC_FAIL: bool = true;
|
||||
|
||||
|
|
@ -53,11 +53,11 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|||
const ALL_CONSTS_ARE_PRECHECKED: bool = false;
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
fn enforce_alignment(_ecx: &InterpCx<'tcx, Self>) -> bool {
|
||||
false // no reason to enforce alignment
|
||||
}
|
||||
|
||||
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
|
||||
fn enforce_validity(_ecx: &InterpCx<'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
|
|
@ -83,26 +83,26 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|||
}
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_abi: rustc_target::spec::abi::Abi,
|
||||
_args: &[interpret::FnArg<'tcx, Self::Provenance>],
|
||||
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
|
||||
_target: Option<BasicBlock>,
|
||||
_unwind: UnwindAction,
|
||||
) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
) -> interpret::InterpResult<'tcx, Option<(&'tcx Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn panic_nounwind(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_msg: &str,
|
||||
) -> interpret::InterpResult<'tcx> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn call_intrinsic(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_args: &[interpret::OpTy<'tcx, Self::Provenance>],
|
||||
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
|
||||
|
|
@ -113,7 +113,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|||
}
|
||||
|
||||
fn assert_panic(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
|
||||
_unwind: UnwindAction,
|
||||
) -> interpret::InterpResult<'tcx> {
|
||||
|
|
@ -121,7 +121,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|||
}
|
||||
|
||||
fn binary_ptr_op(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
bin_op: BinOp,
|
||||
left: &interpret::ImmTy<'tcx, Self::Provenance>,
|
||||
right: &interpret::ImmTy<'tcx, Self::Provenance>,
|
||||
|
|
@ -168,32 +168,30 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|||
}
|
||||
|
||||
fn expose_ptr(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_ptr: interpret::Pointer<Self::Provenance>,
|
||||
) -> interpret::InterpResult<'tcx> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn init_frame_extra(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_frame: interpret::Frame<'mir, 'tcx, Self::Provenance>,
|
||||
) -> interpret::InterpResult<
|
||||
'tcx,
|
||||
interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
||||
> {
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_frame: interpret::Frame<'tcx, Self::Provenance>,
|
||||
) -> interpret::InterpResult<'tcx, interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>>
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stack<'a>(
|
||||
_ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a [interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||
_ecx: &'a InterpCx<'tcx, Self>,
|
||||
) -> &'a [interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||
// Return an empty stack instead of panicking, as `cur_span` uses it to evaluate constants.
|
||||
&[]
|
||||
}
|
||||
|
||||
fn stack_mut<'a>(
|
||||
_ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a mut Vec<interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||
_ecx: &'a mut InterpCx<'tcx, Self>,
|
||||
) -> &'a mut Vec<interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,13 +58,10 @@ impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_span_and_frames<'tcx, 'mir>(
|
||||
pub fn get_span_and_frames<'tcx>(
|
||||
tcx: TyCtxtAt<'tcx>,
|
||||
stack: &[Frame<'mir, 'tcx, impl Provenance, impl Sized>],
|
||||
) -> (Span, Vec<errors::FrameNote>)
|
||||
where
|
||||
'tcx: 'mir,
|
||||
{
|
||||
stack: &[Frame<'tcx, impl Provenance, impl Sized>],
|
||||
) -> (Span, Vec<errors::FrameNote>) {
|
||||
let mut stacktrace = Frame::generate_stacktrace_from_stack(stack);
|
||||
// Filter out `requires_caller_location` frames.
|
||||
stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*tcx));
|
||||
|
|
@ -161,9 +158,9 @@ where
|
|||
|
||||
/// Emit a lint from a const-eval situation.
|
||||
// Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future!
|
||||
pub(super) fn lint<'tcx, 'mir, L>(
|
||||
pub(super) fn lint<'tcx, L>(
|
||||
tcx: TyCtxtAt<'tcx>,
|
||||
machine: &CompileTimeInterpreter<'mir, 'tcx>,
|
||||
machine: &CompileTimeInterpreter<'tcx>,
|
||||
lint: &'static rustc_session::lint::Lint,
|
||||
decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
|
||||
) where
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ use crate::CTRL_C_RECEIVED;
|
|||
|
||||
// Returns a pointer to where the result lives
|
||||
#[instrument(level = "trace", skip(ecx, body))]
|
||||
fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
|
||||
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
|
||||
fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
cid: GlobalId<'tcx>,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
body: &'tcx mir::Body<'tcx>,
|
||||
) -> InterpResult<'tcx, R> {
|
||||
trace!(?ecx.param_env);
|
||||
let tcx = *ecx.tcx;
|
||||
|
|
@ -134,12 +134,12 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
|
|||
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
|
||||
/// of a function's generic parameter will require knowledge about the bounds on the generic
|
||||
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
|
||||
pub(crate) fn mk_eval_cx_to_read_const_val<'mir, 'tcx>(
|
||||
pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
can_access_mut_global: CanAccessMutGlobal,
|
||||
) -> CompileTimeEvalContext<'mir, 'tcx> {
|
||||
) -> CompileTimeEvalContext<'tcx> {
|
||||
debug!("mk_eval_cx: {:?}", param_env);
|
||||
InterpCx::new(
|
||||
tcx,
|
||||
|
|
@ -151,12 +151,12 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'mir, 'tcx>(
|
|||
|
||||
/// Create an interpreter context to inspect the given `ConstValue`.
|
||||
/// Returns both the context and an `OpTy` that represents the constant.
|
||||
pub fn mk_eval_cx_for_const_val<'mir, 'tcx>(
|
||||
pub fn mk_eval_cx_for_const_val<'tcx>(
|
||||
tcx: TyCtxtAt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
val: mir::ConstValue<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<(CompileTimeEvalContext<'mir, 'tcx>, OpTy<'tcx>)> {
|
||||
) -> Option<(CompileTimeEvalContext<'tcx>, OpTy<'tcx>)> {
|
||||
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
|
||||
let op = ecx.const_val_to_op(val, ty, None).ok()?;
|
||||
Some((ecx, op))
|
||||
|
|
@ -170,7 +170,7 @@ pub fn mk_eval_cx_for_const_val<'mir, 'tcx>(
|
|||
/// encounter an `Indirect` they cannot handle.
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
pub(super) fn op_to_const<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'_, 'tcx>,
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
op: &OpTy<'tcx>,
|
||||
for_diagnostics: bool,
|
||||
) -> ConstValue<'tcx> {
|
||||
|
|
@ -326,16 +326,16 @@ pub trait InterpretationResult<'tcx> {
|
|||
/// This function takes the place where the result of the evaluation is stored
|
||||
/// and prepares it for returning it in the appropriate format needed by the specific
|
||||
/// evaluation query.
|
||||
fn make_result<'mir>(
|
||||
fn make_result(
|
||||
mplace: MPlaceTy<'tcx>,
|
||||
ecx: &mut InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
||||
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
|
||||
fn make_result<'mir>(
|
||||
fn make_result(
|
||||
mplace: MPlaceTy<'tcx>,
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
||||
_ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
) -> Self {
|
||||
ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
|
||||
}
|
||||
|
|
@ -416,8 +416,8 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn const_validate_mplace<'mir, 'tcx>(
|
||||
ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
||||
fn const_validate_mplace<'tcx>(
|
||||
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
mplace: &MPlaceTy<'tcx>,
|
||||
cid: GlobalId<'tcx>,
|
||||
) -> Result<(), ErrorHandled> {
|
||||
|
|
@ -446,8 +446,8 @@ fn const_validate_mplace<'mir, 'tcx>(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn report_validation_error<'mir, 'tcx>(
|
||||
ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
||||
fn report_validation_error<'tcx>(
|
||||
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
error: InterpErrorInfo<'tcx>,
|
||||
alloc_id: AllocId,
|
||||
) -> ErrorHandled {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
|
|||
const PROGRESS_INDICATOR_START: usize = 4_000_000;
|
||||
|
||||
/// Extra machine state for CTFE, and the Machine instance
|
||||
pub struct CompileTimeInterpreter<'mir, 'tcx> {
|
||||
pub struct CompileTimeInterpreter<'tcx> {
|
||||
/// The number of terminators that have been evaluated.
|
||||
///
|
||||
/// This is used to produce lints informing the user that the compiler is not stuck.
|
||||
|
|
@ -53,7 +53,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
|
|||
pub(super) num_evaluated_steps: usize,
|
||||
|
||||
/// The virtual call stack.
|
||||
pub(super) stack: Vec<Frame<'mir, 'tcx>>,
|
||||
pub(super) stack: Vec<Frame<'tcx>>,
|
||||
|
||||
/// Pattern matching on consts with references would be unsound if those references
|
||||
/// could point to anything mutable. Therefore, when evaluating consts and when constructing valtrees,
|
||||
|
|
@ -90,7 +90,7 @@ impl From<bool> for CanAccessMutGlobal {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
|
||||
impl<'tcx> CompileTimeInterpreter<'tcx> {
|
||||
pub(crate) fn new(
|
||||
can_access_mut_global: CanAccessMutGlobal,
|
||||
check_alignment: CheckAlignment,
|
||||
|
|
@ -164,8 +164,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type CompileTimeEvalContext<'mir, 'tcx> =
|
||||
InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
|
||||
pub(crate) type CompileTimeEvalContext<'tcx> = InterpCx<'tcx, CompileTimeInterpreter<'tcx>>;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum MemoryKind {
|
||||
|
|
@ -197,7 +196,7 @@ impl interpret::MayLeak for ! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
||||
impl<'tcx> CompileTimeEvalContext<'tcx> {
|
||||
fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
|
||||
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
|
||||
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
|
|
@ -371,25 +370,25 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
|
||||
compile_time_machine!(<'mir, 'tcx>);
|
||||
impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
|
||||
compile_time_machine!(<'tcx>);
|
||||
|
||||
type MemoryKind = MemoryKind;
|
||||
|
||||
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool {
|
||||
matches!(ecx.machine.check_alignment, CheckAlignment::Error)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool {
|
||||
fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool {
|
||||
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks || layout.abi.is_uninhabited()
|
||||
}
|
||||
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
match instance {
|
||||
|
|
@ -410,14 +409,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
orig_instance: ty::Instance<'tcx>,
|
||||
_abi: CallAbi,
|
||||
args: &[FnArg<'tcx>],
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
_unwind: mir::UnwindAction, // unwinding is not supported in consts
|
||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
debug!("find_mir_or_eval_fn: {:?}", orig_instance);
|
||||
|
||||
// Replace some functions.
|
||||
|
|
@ -448,7 +447,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
|
||||
}
|
||||
|
||||
fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
|
||||
fn panic_nounwind(ecx: &mut InterpCx<'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
|
||||
let msg = Symbol::intern(msg);
|
||||
let span = ecx.find_closest_untracked_caller_location();
|
||||
let (file, line, col) = ecx.location_triple_for_span(span);
|
||||
|
|
@ -456,7 +455,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
|
||||
fn call_intrinsic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: &MPlaceTy<'tcx, Self::Provenance>,
|
||||
|
|
@ -555,7 +554,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
|
||||
fn assert_panic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
msg: &AssertMessage<'tcx>,
|
||||
_unwind: mir::UnwindAction,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
|
@ -586,7 +585,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
|
||||
fn binary_ptr_op(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &InterpCx<'tcx, Self>,
|
||||
_bin_op: mir::BinOp,
|
||||
_left: &ImmTy<'tcx>,
|
||||
_right: &ImmTy<'tcx>,
|
||||
|
|
@ -594,7 +593,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
|
||||
}
|
||||
|
||||
fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
|
||||
fn increment_const_eval_counter(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
|
||||
// The step limit has already been hit in a previous call to `increment_const_eval_counter`.
|
||||
|
||||
if let Some(new_steps) = ecx.machine.num_evaluated_steps.checked_add(1) {
|
||||
|
|
@ -650,16 +649,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn expose_ptr(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> {
|
||||
fn expose_ptr(_ecx: &mut InterpCx<'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> {
|
||||
// This is only reachable with -Zunleash-the-miri-inside-of-you.
|
||||
throw_unsup_format!("exposing pointers is not possible at compile-time")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn init_frame_extra(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
frame: Frame<'mir, 'tcx>,
|
||||
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
frame: Frame<'tcx>,
|
||||
) -> InterpResult<'tcx, Frame<'tcx>> {
|
||||
// Enforce stack size limit. Add 1 because this is run before the new frame is pushed.
|
||||
if !ecx.recursion_limit.value_within_limit(ecx.stack().len() + 1) {
|
||||
throw_exhaust!(StackFrameLimitReached)
|
||||
|
|
@ -670,15 +669,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
|
||||
#[inline(always)]
|
||||
fn stack<'a>(
|
||||
ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||
ecx: &'a InterpCx<'tcx, Self>,
|
||||
) -> &'a [Frame<'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||
&ecx.machine.stack
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn stack_mut<'a>(
|
||||
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||
ecx: &'a mut InterpCx<'tcx, Self>,
|
||||
) -> &'a mut Vec<Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||
&mut ecx.machine.stack
|
||||
}
|
||||
|
||||
|
|
@ -715,7 +714,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
}
|
||||
|
||||
fn retag_ptr_value(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
_kind: mir::RetagKind,
|
||||
val: &ImmTy<'tcx, CtfeProvenance>,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> {
|
||||
|
|
@ -756,10 +755,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn before_alloc_read(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
alloc_id: AllocId,
|
||||
) -> InterpResult<'tcx> {
|
||||
fn before_alloc_read(ecx: &InterpCx<'tcx, Self>, alloc_id: AllocId) -> InterpResult<'tcx> {
|
||||
// Check if this is the currently evaluated static.
|
||||
if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) {
|
||||
return Err(ConstEvalErrKind::RecursiveStatic.into());
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use crate::interpret::{
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn branches<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
n: usize,
|
||||
variant: Option<VariantIdx>,
|
||||
|
|
@ -59,7 +59,7 @@ fn branches<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn slice_branches<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
num_nodes: &mut usize,
|
||||
) -> ValTreeCreationResult<'tcx> {
|
||||
|
|
@ -77,7 +77,7 @@ fn slice_branches<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn const_to_valtree_inner<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
num_nodes: &mut usize,
|
||||
) -> ValTreeCreationResult<'tcx> {
|
||||
|
|
@ -219,7 +219,7 @@ fn reconstruct_place_meta<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug", ret)]
|
||||
fn create_valtree_place<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
valtree: ty::ValTree<'tcx>,
|
||||
) -> MPlaceTy<'tcx> {
|
||||
|
|
@ -364,7 +364,7 @@ pub fn valtree_to_const_value<'tcx>(
|
|||
|
||||
/// Put a valtree into memory and return a reference to that.
|
||||
fn valtree_to_ref<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
valtree: ty::ValTree<'tcx>,
|
||||
pointee_ty: Ty<'tcx>,
|
||||
) -> Immediate {
|
||||
|
|
@ -380,7 +380,7 @@ fn valtree_to_ref<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn valtree_into_mplace<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
valtree: ty::ValTree<'tcx>,
|
||||
) {
|
||||
|
|
@ -457,6 +457,6 @@ fn valtree_into_mplace<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: &MPlaceTy<'tcx>) {
|
||||
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx>, place: &MPlaceTy<'tcx>) {
|
||||
trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone())));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use super::{
|
|||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
pub fn cast(
|
||||
&mut self,
|
||||
src: &OpTy<'tcx, M::Provenance>,
|
||||
|
|
@ -324,13 +324,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
use rustc_type_ir::TyKind::*;
|
||||
|
||||
fn adjust_nan<
|
||||
'mir,
|
||||
'tcx: 'mir,
|
||||
M: Machine<'mir, 'tcx>,
|
||||
'tcx,
|
||||
M: Machine<'tcx>,
|
||||
F1: rustc_apfloat::Float + FloatConvert<F2>,
|
||||
F2: rustc_apfloat::Float,
|
||||
>(
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
f1: F1,
|
||||
f2: F2,
|
||||
) -> F2 {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use super::{
|
|||
err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
|
||||
};
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Writes the discriminant of the given variant.
|
||||
///
|
||||
/// If the variant is uninhabited, this is UB.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ use crate::errors;
|
|||
use crate::util;
|
||||
use crate::{fluent_generated as fluent, ReportErrorExt};
|
||||
|
||||
pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
pub struct InterpCx<'tcx, M: Machine<'tcx>> {
|
||||
/// Stores the `Machine` instance.
|
||||
///
|
||||
/// Note: the stack is provided by the machine.
|
||||
|
|
@ -49,7 +49,7 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
|||
pub(crate) param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
/// The virtual memory system.
|
||||
pub memory: Memory<'mir, 'tcx, M>,
|
||||
pub memory: Memory<'tcx, M>,
|
||||
|
||||
/// The recursion limit (cached from `tcx.recursion_limit(())`)
|
||||
pub recursion_limit: Limit,
|
||||
|
|
@ -90,12 +90,12 @@ impl Drop for SpanGuard {
|
|||
}
|
||||
|
||||
/// A stack frame.
|
||||
pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
|
||||
pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Function and callsite information
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The MIR for the function called on this frame.
|
||||
pub body: &'mir mir::Body<'tcx>,
|
||||
pub body: &'tcx mir::Body<'tcx>,
|
||||
|
||||
/// The def_id and args of the current function.
|
||||
pub instance: ty::Instance<'tcx>,
|
||||
|
|
@ -232,8 +232,8 @@ impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, Prov: Provenance> Frame<'mir, 'tcx, Prov> {
|
||||
pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'mir, 'tcx, Prov, Extra> {
|
||||
impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
|
||||
pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'tcx, Prov, Extra> {
|
||||
Frame {
|
||||
body: self.body,
|
||||
instance: self.instance,
|
||||
|
|
@ -247,7 +247,7 @@ impl<'mir, 'tcx, Prov: Provenance> Frame<'mir, 'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
|
||||
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
|
||||
/// Get the current location within the Frame.
|
||||
///
|
||||
/// If this is `Left`, we are not currently executing any particular statement in
|
||||
|
|
@ -345,16 +345,16 @@ impl<'tcx> FrameInfo<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> HasDataLayout for InterpCx<'tcx, M> {
|
||||
#[inline]
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.tcx.data_layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpCx<'mir, 'tcx, M>
|
||||
impl<'tcx, M> layout::HasTyCtxt<'tcx> for InterpCx<'tcx, M>
|
||||
where
|
||||
M: Machine<'mir, 'tcx>,
|
||||
M: Machine<'tcx>,
|
||||
{
|
||||
#[inline]
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
|
|
@ -362,16 +362,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'mir, 'tcx, M>
|
||||
impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M>
|
||||
where
|
||||
M: Machine<'mir, 'tcx>,
|
||||
M: Machine<'tcx>,
|
||||
{
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
|
||||
type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
|
||||
|
||||
#[inline]
|
||||
|
|
@ -391,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpC
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
|
||||
type FnAbiOfResult = InterpResult<'tcx, &'tcx FnAbi<'tcx, Ty<'tcx>>>;
|
||||
|
||||
fn handle_fn_abi_err(
|
||||
|
|
@ -484,7 +484,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St
|
|||
s
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_span: Span,
|
||||
|
|
@ -517,14 +517,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
|
||||
pub(crate) fn stack(&self) -> &[Frame<'tcx, M::Provenance, M::FrameExtra>] {
|
||||
M::stack(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn stack_mut(
|
||||
&mut self,
|
||||
) -> &mut Vec<Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>> {
|
||||
pub(crate) fn stack_mut(&mut self) -> &mut Vec<Frame<'tcx, M::Provenance, M::FrameExtra>> {
|
||||
M::stack_mut(self)
|
||||
}
|
||||
|
||||
|
|
@ -536,17 +534,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn frame(&self) -> &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra> {
|
||||
pub fn frame(&self) -> &Frame<'tcx, M::Provenance, M::FrameExtra> {
|
||||
self.stack().last().expect("no call frames exist")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::Provenance, M::FrameExtra> {
|
||||
pub fn frame_mut(&mut self) -> &mut Frame<'tcx, M::Provenance, M::FrameExtra> {
|
||||
self.stack_mut().last_mut().expect("no call frames exist")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn body(&self) -> &'mir mir::Body<'tcx> {
|
||||
pub fn body(&self) -> &'tcx mir::Body<'tcx> {
|
||||
self.frame().body
|
||||
}
|
||||
|
||||
|
|
@ -602,7 +600,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
>(
|
||||
&self,
|
||||
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
|
||||
frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
|
||||
value: T,
|
||||
) -> Result<T, ErrorHandled> {
|
||||
frame
|
||||
|
|
@ -680,7 +678,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
#[inline(always)]
|
||||
pub(super) fn layout_of_local(
|
||||
&self,
|
||||
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
|
||||
frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
|
||||
local: mir::Local,
|
||||
layout: Option<TyAndLayout<'tcx>>,
|
||||
) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
||||
|
|
@ -803,7 +801,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
pub fn push_stack_frame(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
body: &'tcx mir::Body<'tcx>,
|
||||
return_place: &MPlaceTy<'tcx, M::Provenance>,
|
||||
return_to_block: StackPopCleanup,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
|
@ -1205,10 +1203,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn dump_place(
|
||||
&self,
|
||||
place: &PlaceTy<'tcx, M::Provenance>,
|
||||
) -> PlacePrinter<'_, 'mir, 'tcx, M> {
|
||||
pub fn dump_place(&self, place: &PlaceTy<'tcx, M::Provenance>) -> PlacePrinter<'_, 'tcx, M> {
|
||||
PlacePrinter { ecx: self, place: *place.place() }
|
||||
}
|
||||
|
||||
|
|
@ -1220,14 +1215,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
#[doc(hidden)]
|
||||
/// Helper struct for the `dump_place` function.
|
||||
pub struct PlacePrinter<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
ecx: &'a InterpCx<'mir, 'tcx, M>,
|
||||
pub struct PlacePrinter<'a, 'tcx, M: Machine<'tcx>> {
|
||||
ecx: &'a InterpCx<'tcx, M>,
|
||||
place: Place<M::Provenance>,
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
|
||||
for PlacePrinter<'a, 'mir, 'tcx, M>
|
||||
{
|
||||
impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for PlacePrinter<'a, 'tcx, M> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.place {
|
||||
Place::Local { local, offset, locals_addr } => {
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ use super::{err_ub, AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind
|
|||
use crate::const_eval;
|
||||
use crate::errors::NestedStaticInThreadLocal;
|
||||
|
||||
pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
|
||||
'mir,
|
||||
pub trait CompileTimeMachine<'tcx, T> = Machine<
|
||||
'tcx,
|
||||
MemoryKind = T,
|
||||
Provenance = CtfeProvenance,
|
||||
|
|
@ -46,7 +45,7 @@ pub trait HasStaticRootDefId {
|
|||
fn static_def_id(&self) -> Option<LocalDefId>;
|
||||
}
|
||||
|
||||
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> {
|
||||
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_> {
|
||||
fn static_def_id(&self) -> Option<LocalDefId> {
|
||||
Some(self.static_root_ids?.1)
|
||||
}
|
||||
|
|
@ -59,8 +58,8 @@ impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> {
|
|||
/// already mutable (as a sanity check).
|
||||
///
|
||||
/// Returns an iterator over all relocations referred to by this allocation.
|
||||
fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>(
|
||||
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||
fn intern_shallow<'rt, 'tcx, T, M: CompileTimeMachine<'tcx, T>>(
|
||||
ecx: &'rt mut InterpCx<'tcx, M>,
|
||||
alloc_id: AllocId,
|
||||
mutability: Mutability,
|
||||
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> {
|
||||
|
|
@ -146,12 +145,8 @@ pub enum InternResult {
|
|||
///
|
||||
/// For `InternKind::Static` the root allocation will not be interned, but must be handled by the caller.
|
||||
#[instrument(level = "debug", skip(ecx))]
|
||||
pub fn intern_const_alloc_recursive<
|
||||
'mir,
|
||||
'tcx: 'mir,
|
||||
M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>,
|
||||
>(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval::MemoryKind>>(
|
||||
ecx: &mut InterpCx<'tcx, M>,
|
||||
intern_kind: InternKind,
|
||||
ret: &MPlaceTy<'tcx>,
|
||||
) -> Result<(), InternResult> {
|
||||
|
|
@ -290,13 +285,8 @@ pub fn intern_const_alloc_recursive<
|
|||
|
||||
/// Intern `ret`. This function assumes that `ret` references no other allocation.
|
||||
#[instrument(level = "debug", skip(ecx))]
|
||||
pub fn intern_const_alloc_for_constprop<
|
||||
'mir,
|
||||
'tcx: 'mir,
|
||||
T,
|
||||
M: CompileTimeMachine<'mir, 'tcx, T>,
|
||||
>(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
|
||||
ecx: &mut InterpCx<'tcx, M>,
|
||||
alloc_id: AllocId,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
|
||||
|
|
@ -315,19 +305,14 @@ pub fn intern_const_alloc_for_constprop<
|
|||
Ok(())
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
||||
InterpCx<'mir, 'tcx, M>
|
||||
{
|
||||
impl<'tcx, M: super::intern::CompileTimeMachine<'tcx, !>> InterpCx<'tcx, M> {
|
||||
/// A helper function that allocates memory for the layout given and gives you access to mutate
|
||||
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
||||
/// current `Memory` and interned as read-only into the global memory.
|
||||
pub fn intern_with_temp_alloc(
|
||||
&mut self,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
f: impl FnOnce(
|
||||
&mut InterpCx<'mir, 'tcx, M>,
|
||||
&PlaceTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, ()>,
|
||||
f: impl FnOnce(&mut InterpCx<'tcx, M>, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, ()>,
|
||||
) -> InterpResult<'tcx, AllocId> {
|
||||
// `allocate` picks a fresh AllocId that we will associate with its data below.
|
||||
let dest = self.allocate(layout, MemoryKind::Stack)?;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
|||
})
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Returns `true` if emulation happened.
|
||||
/// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
|
||||
/// intrinsic handling.
|
||||
|
|
@ -605,9 +605,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.
|
||||
pub(crate) fn copy_intrinsic(
|
||||
&mut self,
|
||||
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
src: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_target_usize(count)?;
|
||||
|
|
@ -634,8 +634,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
/// Does a *typed* swap of `*left` and `*right`.
|
||||
fn typed_swap_intrinsic(
|
||||
&mut self,
|
||||
left: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
right: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
left: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
right: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let left = self.deref_pointer(left)?;
|
||||
let right = self.deref_pointer(right)?;
|
||||
|
|
@ -651,9 +651,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
pub(crate) fn write_bytes_intrinsic(
|
||||
&mut self,
|
||||
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
byte: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
byte: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
|
||||
|
||||
|
|
@ -673,9 +673,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
pub(crate) fn compare_bytes_intrinsic(
|
||||
&mut self,
|
||||
left: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
right: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
byte_count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
left: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
right: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
byte_count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
|
||||
let left = self.read_pointer(left)?;
|
||||
let right = self.read_pointer(right)?;
|
||||
|
|
@ -691,14 +691,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
pub(crate) fn raw_eq_intrinsic(
|
||||
&mut self,
|
||||
lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
lhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
rhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
|
||||
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
|
||||
assert!(layout.is_sized());
|
||||
|
||||
let get_bytes = |this: &InterpCx<'mir, 'tcx, M>,
|
||||
op: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
let get_bytes = |this: &InterpCx<'tcx, M>,
|
||||
op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
||||
size|
|
||||
-> InterpResult<'tcx, &[u8]> {
|
||||
let ptr = this.read_pointer(op)?;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ pub trait AllocMap<K: Hash + Eq, V> {
|
|||
|
||||
/// Methods of this trait signifies a point where CTFE evaluation would fail
|
||||
/// and some use case dependent behaviour can instead be applied.
|
||||
pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||
pub trait Machine<'tcx>: Sized {
|
||||
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
|
||||
type MemoryKind: Debug + std::fmt::Display + MayLeak + Eq + 'static;
|
||||
|
||||
|
|
@ -145,12 +145,12 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
const ALL_CONSTS_ARE_PRECHECKED: bool = true;
|
||||
|
||||
/// Whether memory accesses should be alignment-checked.
|
||||
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool;
|
||||
|
||||
/// Gives the machine a chance to detect more misalignment than the built-in checks would catch.
|
||||
#[inline(always)]
|
||||
fn alignment_check(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &InterpCx<'tcx, Self>,
|
||||
_alloc_id: AllocId,
|
||||
_alloc_align: Align,
|
||||
_alloc_kind: AllocKind,
|
||||
|
|
@ -161,22 +161,22 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
}
|
||||
|
||||
/// Whether to enforce the validity invariant for a specific layout.
|
||||
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool;
|
||||
fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool;
|
||||
|
||||
/// Whether function calls should be [ABI](CallAbi)-checked.
|
||||
fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||
fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually
|
||||
/// check for overflow.
|
||||
fn ignore_optional_overflow_checks(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
fn ignore_optional_overflow_checks(_ecx: &InterpCx<'tcx, Self>) -> bool;
|
||||
|
||||
/// Entry point for obtaining the MIR of anything that should get evaluated.
|
||||
/// So not just functions and shims, but also const/static initializers, anonymous
|
||||
/// constants, ...
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
Ok(ecx.tcx.instance_mir(instance))
|
||||
|
|
@ -193,19 +193,19 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
|
||||
/// was used.
|
||||
fn find_mir_or_eval_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
abi: CallAbi,
|
||||
args: &[FnArg<'tcx, Self::Provenance>],
|
||||
destination: &MPlaceTy<'tcx, Self::Provenance>,
|
||||
target: Option<mir::BasicBlock>,
|
||||
unwind: mir::UnwindAction,
|
||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
|
||||
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>>;
|
||||
|
||||
/// Execute `fn_val`. It is the hook's responsibility to advance the instruction
|
||||
/// pointer as appropriate.
|
||||
fn call_extra_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
fn_val: Self::ExtraFnVal,
|
||||
abi: CallAbi,
|
||||
args: &[FnArg<'tcx, Self::Provenance>],
|
||||
|
|
@ -220,7 +220,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// Returns `None` if the intrinsic was fully handled.
|
||||
/// Otherwise, returns an `Instance` of the function that implements the intrinsic.
|
||||
fn call_intrinsic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Self::Provenance>],
|
||||
destination: &MPlaceTy<'tcx, Self::Provenance>,
|
||||
|
|
@ -230,17 +230,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
|
||||
/// Called to evaluate `Assert` MIR terminators that trigger a panic.
|
||||
fn assert_panic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
msg: &mir::AssertMessage<'tcx>,
|
||||
unwind: mir::UnwindAction,
|
||||
) -> InterpResult<'tcx>;
|
||||
|
||||
/// Called to trigger a non-unwinding panic.
|
||||
fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
|
||||
fn panic_nounwind(_ecx: &mut InterpCx<'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
|
||||
|
||||
/// Called when unwinding reached a state where execution should be terminated.
|
||||
fn unwind_terminate(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
reason: mir::UnwindTerminateReason,
|
||||
) -> InterpResult<'tcx>;
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
///
|
||||
/// Returns a (value, overflowed) pair if the operation succeeded
|
||||
fn binary_ptr_op(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
bin_op: mir::BinOp,
|
||||
left: &ImmTy<'tcx, Self::Provenance>,
|
||||
right: &ImmTy<'tcx, Self::Provenance>,
|
||||
|
|
@ -257,7 +257,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// Generate the NaN returned by a float operation, given the list of inputs.
|
||||
/// (This is all inputs, not just NaN inputs!)
|
||||
fn generate_nan<F1: Float + FloatConvert<F2>, F2: Float>(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &InterpCx<'tcx, Self>,
|
||||
_inputs: &[F1],
|
||||
) -> F2 {
|
||||
// By default we always return the preferred NaN.
|
||||
|
|
@ -266,14 +266,14 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
|
||||
/// Called before a basic block terminator is executed.
|
||||
#[inline]
|
||||
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
|
||||
fn before_terminator(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction.
|
||||
/// You can use this to detect long or endlessly running programs.
|
||||
#[inline]
|
||||
fn increment_const_eval_counter(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
|
||||
fn increment_const_eval_counter(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
|
||||
/// Return the `AllocId` for the given thread-local static in the current thread.
|
||||
fn thread_local_static_pointer(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
def_id: DefId,
|
||||
) -> InterpResult<'tcx, Pointer<Self::Provenance>> {
|
||||
throw_unsup!(ThreadLocalStatic(def_id))
|
||||
|
|
@ -301,20 +301,20 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
|
||||
/// Return the `AllocId` for the given `extern static`.
|
||||
fn extern_static_pointer(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
def_id: DefId,
|
||||
) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
|
||||
|
||||
/// "Int-to-pointer cast"
|
||||
fn ptr_from_addr_cast(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
addr: u64,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>;
|
||||
|
||||
/// Marks a pointer as exposed, allowing it's provenance
|
||||
/// to be recovered. "Pointer-to-int cast"
|
||||
fn expose_ptr(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
ptr: Pointer<Self::Provenance>,
|
||||
) -> InterpResult<'tcx>;
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
///
|
||||
/// When this fails, that means the pointer does not point to a live allocation.
|
||||
fn ptr_get_alloc(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
ptr: Pointer<Self::Provenance>,
|
||||
) -> Option<(AllocId, Size, Self::ProvenanceExtra)>;
|
||||
|
||||
|
|
@ -345,7 +345,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
|
||||
/// owned allocation to the map even when the map is shared.)
|
||||
fn adjust_allocation<'b>(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
|
|
@ -359,7 +359,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// `kind` is the kind of the allocation the pointer points to; it can be `None` when
|
||||
/// it's a global and `GLOBAL_KIND` is `None`.
|
||||
fn adjust_alloc_root_pointer(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
ptr: Pointer,
|
||||
kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
|
||||
|
|
@ -370,7 +370,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
|
||||
/// `InlineAsmOptions::NORETURN` being set.
|
||||
fn eval_inline_asm(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_template: &'tcx [InlineAsmTemplatePiece],
|
||||
_operands: &[mir::InlineAsmOperand<'tcx>],
|
||||
_options: InlineAsmOptions,
|
||||
|
|
@ -406,10 +406,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
///
|
||||
/// Used to prevent statics from self-initializing by reading from their own memory
|
||||
/// as it is being initialized.
|
||||
fn before_alloc_read(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_alloc_id: AllocId,
|
||||
) -> InterpResult<'tcx> {
|
||||
fn before_alloc_read(_ecx: &InterpCx<'tcx, Self>, _alloc_id: AllocId) -> InterpResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -444,7 +441,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// Returns the possibly adjusted pointer.
|
||||
#[inline]
|
||||
fn retag_ptr_value(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_kind: mir::RetagKind,
|
||||
val: &ImmTy<'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
|
||||
|
|
@ -455,7 +452,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// Replaces all pointers stored in the given place.
|
||||
#[inline]
|
||||
fn retag_place_contents(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_kind: mir::RetagKind,
|
||||
_place: &PlaceTy<'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
|
@ -467,7 +464,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// These places need to be protected to make sure the program cannot tell whether the
|
||||
/// argument/return value was actually copied or passed in-place..
|
||||
fn protect_in_place_function_argument(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
mplace: &MPlaceTy<'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// Without an aliasing model, all we can do is put `Uninit` into the place.
|
||||
|
|
@ -477,29 +474,29 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
|
||||
/// Called immediately before a new stack frame gets pushed.
|
||||
fn init_frame_extra(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
frame: Frame<'mir, 'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>>;
|
||||
ecx: &mut InterpCx<'tcx, Self>,
|
||||
frame: Frame<'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx, Frame<'tcx, Self::Provenance, Self::FrameExtra>>;
|
||||
|
||||
/// Borrow the current thread's stack.
|
||||
fn stack<'a>(
|
||||
ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>];
|
||||
ecx: &'a InterpCx<'tcx, Self>,
|
||||
) -> &'a [Frame<'tcx, Self::Provenance, Self::FrameExtra>];
|
||||
|
||||
/// Mutably borrow the current thread's stack.
|
||||
fn stack_mut<'a>(
|
||||
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>>;
|
||||
ecx: &'a mut InterpCx<'tcx, Self>,
|
||||
) -> &'a mut Vec<Frame<'tcx, Self::Provenance, Self::FrameExtra>>;
|
||||
|
||||
/// Called immediately after a stack frame got pushed and its locals got initialized.
|
||||
fn after_stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
|
||||
fn after_stack_push(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Called just before the return value is copied to the caller-provided return place.
|
||||
fn before_stack_pop(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
||||
_ecx: &InterpCx<'tcx, Self>,
|
||||
_frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>,
|
||||
) -> InterpResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -508,8 +505,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// The `locals` have already been destroyed!
|
||||
#[inline(always)]
|
||||
fn after_stack_pop(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_frame: Frame<'tcx, Self::Provenance, Self::FrameExtra>,
|
||||
unwinding: bool,
|
||||
) -> InterpResult<'tcx, StackPopJump> {
|
||||
// By default, we do not support unwinding from panics
|
||||
|
|
@ -521,7 +518,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// but before the local's stack frame is updated to point to that memory.
|
||||
#[inline(always)]
|
||||
fn after_local_allocated(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpCx<'tcx, Self>,
|
||||
_local: mir::Local,
|
||||
_mplace: &MPlaceTy<'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
|
@ -532,7 +529,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
/// but this hook has the chance to do some pre/postprocessing.
|
||||
#[inline(always)]
|
||||
fn eval_mir_constant<F>(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
val: mir::Const<'tcx>,
|
||||
span: Span,
|
||||
layout: Option<TyAndLayout<'tcx>>,
|
||||
|
|
@ -540,7 +537,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>
|
||||
where
|
||||
F: Fn(
|
||||
&InterpCx<'mir, 'tcx, Self>,
|
||||
&InterpCx<'tcx, Self>,
|
||||
mir::Const<'tcx>,
|
||||
Span,
|
||||
Option<TyAndLayout<'tcx>>,
|
||||
|
|
@ -552,7 +549,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
|||
|
||||
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
|
||||
/// (CTFE and ConstProp) use the same instance. Here, we share that code.
|
||||
pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||
pub macro compile_time_machine(<$tcx: lifetime>) {
|
||||
type Provenance = CtfeProvenance;
|
||||
type ProvenanceExtra = bool; // the "immutable" flag
|
||||
|
||||
|
|
@ -567,13 +564,13 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
type Bytes = Box<[u8]>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
|
||||
fn ignore_optional_overflow_checks(_ecx: &InterpCx<$tcx, Self>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn unwind_terminate(
|
||||
_ecx: &mut InterpCx<$mir, $tcx, Self>,
|
||||
_ecx: &mut InterpCx<$tcx, Self>,
|
||||
_reason: mir::UnwindTerminateReason,
|
||||
) -> InterpResult<$tcx> {
|
||||
unreachable!("unwinding cannot happen during compile-time evaluation")
|
||||
|
|
@ -581,7 +578,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
|
||||
#[inline(always)]
|
||||
fn call_extra_fn(
|
||||
_ecx: &mut InterpCx<$mir, $tcx, Self>,
|
||||
_ecx: &mut InterpCx<$tcx, Self>,
|
||||
fn_val: !,
|
||||
_abi: CallAbi,
|
||||
_args: &[FnArg<$tcx>],
|
||||
|
|
@ -594,7 +591,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
|
||||
#[inline(always)]
|
||||
fn adjust_allocation<'b>(
|
||||
_ecx: &InterpCx<$mir, $tcx, Self>,
|
||||
_ecx: &InterpCx<$tcx, Self>,
|
||||
_id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
|
|
@ -603,7 +600,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
}
|
||||
|
||||
fn extern_static_pointer(
|
||||
ecx: &InterpCx<$mir, $tcx, Self>,
|
||||
ecx: &InterpCx<$tcx, Self>,
|
||||
def_id: DefId,
|
||||
) -> InterpResult<$tcx, Pointer> {
|
||||
// Use the `AllocId` associated with the `DefId`. Any actual *access* will fail.
|
||||
|
|
@ -612,7 +609,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
|
||||
#[inline(always)]
|
||||
fn adjust_alloc_root_pointer(
|
||||
_ecx: &InterpCx<$mir, $tcx, Self>,
|
||||
_ecx: &InterpCx<$tcx, Self>,
|
||||
ptr: Pointer<CtfeProvenance>,
|
||||
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
) -> InterpResult<$tcx, Pointer<CtfeProvenance>> {
|
||||
|
|
@ -621,7 +618,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
|
||||
#[inline(always)]
|
||||
fn ptr_from_addr_cast(
|
||||
_ecx: &InterpCx<$mir, $tcx, Self>,
|
||||
_ecx: &InterpCx<$tcx, Self>,
|
||||
addr: u64,
|
||||
) -> InterpResult<$tcx, Pointer<Option<CtfeProvenance>>> {
|
||||
// Allow these casts, but make the pointer not dereferenceable.
|
||||
|
|
@ -632,7 +629,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
|
||||
#[inline(always)]
|
||||
fn ptr_get_alloc(
|
||||
_ecx: &InterpCx<$mir, $tcx, Self>,
|
||||
_ecx: &InterpCx<$tcx, Self>,
|
||||
ptr: Pointer<CtfeProvenance>,
|
||||
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
|
||||
// We know `offset` is relative to the allocation, so we can use `into_parts`.
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ impl<'tcx, Other> FnVal<'tcx, Other> {
|
|||
|
||||
// `Memory` has to depend on the `Machine` because some of its operations
|
||||
// (e.g., `get`) call a `Machine` hook.
|
||||
pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
pub struct Memory<'tcx, M: Machine<'tcx>> {
|
||||
/// Allocations local to this instance of the interpreter. The kind
|
||||
/// helps ensure that the same mechanism is used for allocation and
|
||||
/// deallocation. When an allocation is not found here, it is a
|
||||
|
|
@ -142,7 +142,7 @@ pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Bo
|
|||
alloc_id: AllocId,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
|
||||
pub fn new() -> Self {
|
||||
Memory {
|
||||
alloc_map: M::MemoryMap::default(),
|
||||
|
|
@ -158,7 +158,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Call this to turn untagged "global" pointers (obtained via `tcx`) into
|
||||
/// the machine pointer to the allocation. Must never be used
|
||||
/// for any other pointers, nor for TLS statics.
|
||||
|
|
@ -524,7 +524,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// This function is used by Miri's provenance GC to remove unreachable entries from the dead_alloc_map.
|
||||
pub fn remove_unreachable_allocs(&mut self, reachable_allocs: &FxHashSet<AllocId>) {
|
||||
// Unlike all the other GC helpers where we check if an `AllocId` is found in the interpreter or
|
||||
|
|
@ -536,7 +536,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
/// Allocation accessors
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Helper function to obtain a global (tcx) allocation.
|
||||
/// This attempts to return a reference to an existing allocation if
|
||||
/// one can be found in `tcx`. That, however, is only possible if `tcx` and
|
||||
|
|
@ -888,14 +888,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
/// Create a lazy debug printer that prints the given allocation and all allocations it points
|
||||
/// to, recursively.
|
||||
#[must_use]
|
||||
pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M> {
|
||||
pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'tcx, M> {
|
||||
self.dump_allocs(vec![id])
|
||||
}
|
||||
|
||||
/// Create a lazy debug printer for a list of allocations and all allocations they point to,
|
||||
/// recursively.
|
||||
#[must_use]
|
||||
pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'mir, 'tcx, M> {
|
||||
pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'tcx, M> {
|
||||
allocs.sort();
|
||||
allocs.dedup();
|
||||
DumpAllocs { ecx: self, allocs }
|
||||
|
|
@ -975,12 +975,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
#[doc(hidden)]
|
||||
/// There's no way to use this directly, it's just a helper struct for the `dump_alloc(s)` methods.
|
||||
pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
ecx: &'a InterpCx<'mir, 'tcx, M>,
|
||||
pub struct DumpAllocs<'a, 'tcx, M: Machine<'tcx>> {
|
||||
ecx: &'a InterpCx<'tcx, M>,
|
||||
allocs: Vec<AllocId>,
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// Cannot be a closure because it is generic in `Prov`, `Extra`.
|
||||
fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
|
||||
|
|
@ -1125,7 +1125,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Pr
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Reads the given number of bytes from memory, and strips their provenance if possible.
|
||||
/// Returns them as a slice.
|
||||
///
|
||||
|
|
@ -1338,7 +1338,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
/// Machine pointer introspection.
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Test if this value might be null.
|
||||
/// If the machine does not support ptr-to-int casts, this is conservative.
|
||||
pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<'tcx, bool> {
|
||||
|
|
|
|||
|
|
@ -374,21 +374,21 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> {
|
|||
MemPlaceMeta::None
|
||||
}
|
||||
|
||||
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
offset: Size,
|
||||
_mode: OffsetMode,
|
||||
meta: MemPlaceMeta<Prov>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
assert_matches!(meta, MemPlaceMeta::None); // we can't store this anywhere anyway
|
||||
Ok(self.offset_(offset, layout, ecx))
|
||||
}
|
||||
|
||||
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
_ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
_ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||
Ok(self.clone().into())
|
||||
}
|
||||
|
|
@ -457,13 +457,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
offset: Size,
|
||||
mode: OffsetMode,
|
||||
meta: MemPlaceMeta<Prov>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
match self.as_mplace_or_imm() {
|
||||
Left(mplace) => Ok(mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into()),
|
||||
|
|
@ -475,9 +475,9 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
_ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
_ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||
Ok(self.clone())
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
|
||||
/// Returns `None` if the layout does not permit loading this as a value.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use tracing::trace;
|
|||
|
||||
use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine};
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
|
||||
let res = Ord::cmp(&lhs, &rhs);
|
||||
return ImmTy::from_ordering(res, *self.tcx);
|
||||
|
|
|
|||
|
|
@ -77,12 +77,12 @@ impl<Prov: Provenance> MemPlace<Prov> {
|
|||
|
||||
#[inline]
|
||||
// Not called `offset_with_meta` to avoid confusion with the trait method.
|
||||
fn offset_with_meta_<'mir, 'tcx, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset_with_meta_<'tcx, M: Machine<'tcx, Provenance = Prov>>(
|
||||
self,
|
||||
offset: Size,
|
||||
mode: OffsetMode,
|
||||
meta: MemPlaceMeta<Prov>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
debug_assert!(
|
||||
!meta.has_meta() || self.meta.has_meta(),
|
||||
|
|
@ -162,20 +162,20 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
|
|||
self.mplace.meta
|
||||
}
|
||||
|
||||
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
offset: Size,
|
||||
mode: OffsetMode,
|
||||
meta: MemPlaceMeta<Prov>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
Ok(MPlaceTy { mplace: self.mplace.offset_with_meta_(offset, mode, meta, ecx)?, layout })
|
||||
}
|
||||
|
||||
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
_ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
_ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||
Ok(self.clone().into())
|
||||
}
|
||||
|
|
@ -274,13 +274,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
offset: Size,
|
||||
mode: OffsetMode,
|
||||
meta: MemPlaceMeta<Prov>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
Ok(match self.as_mplace_or_local() {
|
||||
Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(),
|
||||
|
|
@ -305,9 +305,9 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
|
|||
})
|
||||
}
|
||||
|
||||
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||
ecx.place_to_op(self)
|
||||
}
|
||||
|
|
@ -341,9 +341,9 @@ pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
|
|||
&self,
|
||||
) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)>;
|
||||
|
||||
fn force_mplace<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &mut InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Prov>>;
|
||||
}
|
||||
|
||||
|
|
@ -357,9 +357,9 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn force_mplace<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &mut InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Prov>> {
|
||||
ecx.force_allocation(self)
|
||||
}
|
||||
|
|
@ -374,19 +374,19 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn force_mplace<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
_ecx: &mut InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Prov>> {
|
||||
Ok(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
|
||||
impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M>
|
||||
impl<'tcx, Prov, M> InterpCx<'tcx, M>
|
||||
where
|
||||
Prov: Provenance,
|
||||
M: Machine<'mir, 'tcx, Provenance = Prov>,
|
||||
M: Machine<'tcx, Provenance = Prov>,
|
||||
{
|
||||
pub fn ptr_with_meta_to_mplace(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
|
|||
fn meta(&self) -> MemPlaceMeta<Prov>;
|
||||
|
||||
/// Get the length of a slice/string/array stored here.
|
||||
fn len<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn len<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, u64> {
|
||||
let layout = self.layout();
|
||||
if layout.is_unsized() {
|
||||
|
|
@ -65,29 +65,29 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
|
|||
}
|
||||
|
||||
/// Offset the value by the given amount, replacing the layout and metadata.
|
||||
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
offset: Size,
|
||||
mode: OffsetMode,
|
||||
meta: MemPlaceMeta<Prov>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self>;
|
||||
|
||||
fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn offset<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
offset: Size,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
assert!(layout.is_sized());
|
||||
self.offset_with_meta(offset, OffsetMode::Inbounds, MemPlaceMeta::None, layout, ecx)
|
||||
}
|
||||
|
||||
fn transmute<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn transmute<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Self> {
|
||||
assert!(self.layout().is_sized() && layout.is_sized());
|
||||
assert_eq!(self.layout().size, layout.size);
|
||||
|
|
@ -96,9 +96,9 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
|
|||
|
||||
/// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for
|
||||
/// reading from this thing.
|
||||
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>>;
|
||||
}
|
||||
|
||||
|
|
@ -113,9 +113,9 @@ pub struct ArrayIterator<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>>
|
|||
|
||||
impl<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> ArrayIterator<'tcx, 'a, Prov, P> {
|
||||
/// Should be the same `ecx` on each call, and match the one used to create the iterator.
|
||||
pub fn next<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
|
||||
pub fn next<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&mut self,
|
||||
ecx: &InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
) -> InterpResult<'tcx, Option<(u64, P)>> {
|
||||
let Some(idx) = self.range.next() else { return Ok(None) };
|
||||
// We use `Wrapping` here since the offset has already been checked when the iterator was created.
|
||||
|
|
@ -133,10 +133,10 @@ impl<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> ArrayIterator<'tcx,
|
|||
}
|
||||
|
||||
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
|
||||
impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M>
|
||||
impl<'tcx, Prov, M> InterpCx<'tcx, M>
|
||||
where
|
||||
Prov: Provenance,
|
||||
M: Machine<'mir, 'tcx, Provenance = Prov>,
|
||||
M: Machine<'tcx, Provenance = Prov>,
|
||||
{
|
||||
/// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is
|
||||
/// always possible without allocating, so it can take `&self`. Also return the field's layout.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use super::{
|
|||
};
|
||||
use crate::util;
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Returns `true` as long as there are more things to do.
|
||||
///
|
||||
/// This is used by [priroda](https://github.com/oli-obk/priroda)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
|
||||
/// original memory occurs.
|
||||
pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use tracing::trace;
|
|||
use super::util::ensure_monomorphic_enough;
|
||||
use super::{InterpCx, Machine};
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
|
||||
/// objects.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ where
|
|||
}
|
||||
|
||||
impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> {
|
||||
fn make_result<'mir>(
|
||||
fn make_result(
|
||||
mplace: MPlaceTy<'tcx>,
|
||||
ecx: &mut InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
||||
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
) -> Self {
|
||||
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
|
||||
let alloc = ecx.memory.alloc_map.swap_remove(&alloc_id).unwrap().1;
|
||||
|
|
@ -92,8 +92,8 @@ impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_static_alloc<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
|
||||
pub(crate) fn create_static_alloc<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
static_def_id: LocalDefId,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ fn write_path(out: &mut String, path: &[PathElem]) {
|
|||
}
|
||||
}
|
||||
|
||||
struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
|
||||
/// The `path` may be pushed to, but the part that is present when a function
|
||||
/// starts must not be changed! `visit_fields` and `visit_array` rely on
|
||||
/// this stack discipline.
|
||||
|
|
@ -213,10 +213,10 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
|||
ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
|
||||
/// `None` indicates this is not validating for CTFE (but for runtime).
|
||||
ctfe_mode: Option<CtfeValidationMode>,
|
||||
ecx: &'rt InterpCx<'mir, 'tcx, M>,
|
||||
ecx: &'rt InterpCx<'tcx, M>,
|
||||
}
|
||||
|
||||
impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M> {
|
||||
impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
||||
fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) -> PathElem {
|
||||
// First, check if we are projecting to a variant.
|
||||
match layout.variants {
|
||||
|
|
@ -706,10 +706,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
|||
/// Returns whether the allocation is mutable, and whether it's actually a static.
|
||||
/// For "root" statics we look at the type to account for interior
|
||||
/// mutability; for nested statics we have no type and directly use the annotated mutability.
|
||||
fn mutability<'mir, 'tcx: 'mir>(
|
||||
ecx: &InterpCx<'mir, 'tcx, impl Machine<'mir, 'tcx>>,
|
||||
alloc_id: AllocId,
|
||||
) -> Mutability {
|
||||
fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId) -> Mutability {
|
||||
// Let's see what kind of memory this points to.
|
||||
// We're not using `try_global_alloc` since dangling pointers have already been handled.
|
||||
match ecx.tcx.global_alloc(alloc_id) {
|
||||
|
|
@ -751,13 +748,11 @@ fn mutability<'mir, 'tcx: 'mir>(
|
|||
}
|
||||
}
|
||||
|
||||
impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
for ValidityVisitor<'rt, 'mir, 'tcx, M>
|
||||
{
|
||||
impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> {
|
||||
type V = OpTy<'tcx, M::Provenance>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
|
||||
fn ecx(&self) -> &InterpCx<'tcx, M> {
|
||||
self.ecx
|
||||
}
|
||||
|
||||
|
|
@ -1009,7 +1004,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
fn validate_operand_internal(
|
||||
&self,
|
||||
op: &OpTy<'tcx, M::Provenance>,
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ use std::num::NonZero;
|
|||
use super::{throw_inval, InterpCx, MPlaceTy, Machine, Projectable};
|
||||
|
||||
/// How to traverse a value and what to do when we are at the leaves.
|
||||
pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
|
||||
pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
||||
type V: Projectable<'tcx, M::Provenance> + From<MPlaceTy<'tcx, M::Provenance>>;
|
||||
|
||||
/// The visitor must have an `InterpCx` in it.
|
||||
fn ecx(&self) -> &InterpCx<'mir, 'tcx, M>;
|
||||
fn ecx(&self) -> &InterpCx<'tcx, M>;
|
||||
|
||||
/// `read_discriminant` can be hooked for better error messages.
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, Compil
|
|||
use crate::interpret::*;
|
||||
|
||||
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
||||
fn alloc_caller_location<'mir, 'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
|
||||
fn alloc_caller_location<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
filename: Symbol,
|
||||
line: u32,
|
||||
col: u32,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#![feature(extend_one)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(hasher_prefixfree_extras)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(lint_reasons)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(map_try_insert)]
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ use std::process::{self, Command, Stdio};
|
|||
use std::str;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::{Instant, SystemTime};
|
||||
use std::time::{Duration, Instant, SystemTime};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::trace;
|
||||
|
||||
|
|
@ -1502,14 +1502,13 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
|
|||
pub fn install_ctrlc_handler() {
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
ctrlc::set_handler(move || {
|
||||
// Indicate that we have been signaled to stop. If we were already signaled, exit
|
||||
// immediately. In our interpreter loop we try to consult this value often, but if for
|
||||
// whatever reason we don't get to that check or the cleanup we do upon finding that
|
||||
// this bool has become true takes a long time, the exit here will promptly exit the
|
||||
// process on the second Ctrl-C.
|
||||
if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
// Indicate that we have been signaled to stop, then give the rest of the compiler a bit of
|
||||
// time to check CTRL_C_RECEIVED and run its own shutdown logic, but after a short amount
|
||||
// of time exit the process. This sleep+exit ensures that even if nobody is checking
|
||||
// CTRL_C_RECEIVED, the compiler exits reasonably promptly.
|
||||
CTRL_C_RECEIVED.store(true, Ordering::Relaxed);
|
||||
std::thread::sleep(Duration::from_millis(100));
|
||||
std::process::exit(1);
|
||||
})
|
||||
.expect("Unable to install ctrlc handler");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(internal_features)]
|
||||
|
|
@ -365,17 +364,6 @@ impl From<Cow<'static, str>> for DiagMessage {
|
|||
}
|
||||
}
|
||||
|
||||
/// A workaround for must_produce_diag ICEs when formatting types in disabled lints.
|
||||
///
|
||||
/// Delays formatting until `.into(): DiagMessage` is used.
|
||||
pub struct DelayDm<F>(pub F);
|
||||
|
||||
impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagMessage {
|
||||
fn from(DelayDm(f): DelayDm<F>) -> Self {
|
||||
DiagMessage::from(f())
|
||||
}
|
||||
}
|
||||
|
||||
/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
|
||||
/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagMessage` and the
|
||||
/// subdiagnostic derive refers to typed identifiers that are `DiagMessage`s, so need to be
|
||||
|
|
|
|||
|
|
@ -200,8 +200,6 @@ pub trait SubdiagMessageOp<G: EmissionGuarantee> =
|
|||
pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
|
||||
/// Decorate and emit a lint.
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
|
||||
|
||||
fn msg(&self) -> DiagMessage;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub use diagnostic_impls::{
|
|||
};
|
||||
pub use emitter::ColorConfig;
|
||||
pub use rustc_error_messages::{
|
||||
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier,
|
||||
fallback_fluent_bundle, fluent_bundle, DiagMessage, FluentBundle, LanguageIdentifier,
|
||||
LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
|
||||
};
|
||||
pub use rustc_lint_defs::{pluralize, Applicability};
|
||||
|
|
@ -572,8 +572,8 @@ impl Drop for DiagCtxtInner {
|
|||
if let Some(backtrace) = &self.must_produce_diag {
|
||||
panic!(
|
||||
"must_produce_diag: `trimmed_def_paths` called but no diagnostics emitted; \
|
||||
use `DelayDm` for lints or `with_no_trimmed_paths` for debugging. \
|
||||
called at: {backtrace}"
|
||||
`with_no_trimmed_paths` for debugging. \
|
||||
called at: {backtrace}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(lazy_cell)]
|
||||
|
||||
mod accepted;
|
||||
mod builtin_attrs;
|
||||
|
|
|
|||
|
|
@ -46,13 +46,9 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
|
|||
.emit();
|
||||
}
|
||||
None => {
|
||||
tcx.node_span_lint(
|
||||
UNSUPPORTED_CALLING_CONVENTIONS,
|
||||
hir_id,
|
||||
span,
|
||||
"use of calling convention not supported on this target",
|
||||
|_| {},
|
||||
);
|
||||
tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
|
||||
lint.primary_message("use of calling convention not supported on this target");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -243,8 +239,8 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
UNINHABITED_STATIC,
|
||||
tcx.local_def_id_to_hir_id(def_id),
|
||||
span,
|
||||
"static of uninhabited type",
|
||||
|lint| {
|
||||
lint.primary_message("static of uninhabited type");
|
||||
lint
|
||||
.note("uninhabited statics cannot be initialized, and any access would be an immediate error");
|
||||
},
|
||||
|
|
@ -538,11 +534,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
|
|||
// the cases that were stabilized with the `impl_trait_projection`
|
||||
// feature -- see <https://github.com/rust-lang/rust/pull/115659>.
|
||||
if let DefKind::LifetimeParam = tcx.def_kind(def_id)
|
||||
&& let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
|
||||
| ty::ReLateParam(ty::LateParamRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
}) = *tcx.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
|
||||
&& let Some(def_id) = tcx
|
||||
.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
|
||||
.opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
|
||||
{
|
||||
shadowed_captures.insert(def_id);
|
||||
}
|
||||
|
|
@ -585,12 +579,9 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
|
|||
// Check if the lifetime param was captured but isn't named in the precise captures list.
|
||||
if variances[param.index as usize] == ty::Invariant {
|
||||
if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(param.def_id))
|
||||
&& let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
|
||||
| ty::ReLateParam(ty::LateParamRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
}) = *tcx
|
||||
&& let Some(def_id) = tcx
|
||||
.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local())
|
||||
.opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
|
||||
{
|
||||
tcx.dcx().emit_err(errors::LifetimeNotCaptured {
|
||||
opaque_span,
|
||||
|
|
@ -1315,9 +1306,11 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
|
||||
tcx.local_def_id_to_hir_id(adt.did().expect_local()),
|
||||
span,
|
||||
"zero-sized fields in `repr(transparent)` cannot \
|
||||
contain external non-exhaustive types",
|
||||
|lint| {
|
||||
lint.primary_message(
|
||||
"zero-sized fields in `repr(transparent)` cannot \
|
||||
contain external non-exhaustive types",
|
||||
);
|
||||
let note = if non_exhaustive {
|
||||
"is marked with `#[non_exhaustive]`"
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -876,7 +876,8 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
|||
ty::ReLateParam(_) => {}
|
||||
// Remap early-bound regions as long as they don't come from the `impl` itself,
|
||||
// in which case we don't really need to renumber them.
|
||||
ty::ReEarlyParam(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
|
||||
ty::ReEarlyParam(ebr)
|
||||
if ebr.index >= self.tcx.generics_of(self.impl_def_id).count() as u32 => {}
|
||||
_ => return Ok(region),
|
||||
}
|
||||
|
||||
|
|
@ -889,12 +890,8 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
let guar = match region.kind() {
|
||||
ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
|
||||
| ty::ReLateParam(ty::LateParamRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
}) => {
|
||||
let guar = match region.opt_param_def_id(self.tcx, self.tcx.parent(self.def_id)) {
|
||||
Some(def_id) => {
|
||||
let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
|
||||
self.tcx.def_span(opaque_ty.def_id)
|
||||
} else {
|
||||
|
|
@ -914,7 +911,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
|||
.with_note(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.emit()
|
||||
}
|
||||
_ => {
|
||||
None => {
|
||||
// This code path is not reached in any tests, but may be
|
||||
// reachable. If this is triggered, it should be converted
|
||||
// to `delayed_bug` and the triggering case turned into a
|
||||
|
|
@ -928,7 +925,6 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
|||
Ok(ty::Region::new_early_param(
|
||||
self.tcx,
|
||||
ty::EarlyParamRegion {
|
||||
def_id: e.def_id,
|
||||
name: e.name,
|
||||
index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -281,8 +281,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
lint::builtin::ASM_SUB_REGISTER,
|
||||
expr.hir_id,
|
||||
spans,
|
||||
"formatting may not be suitable for sub-register argument",
|
||||
|lint| {
|
||||
lint.primary_message("formatting may not be suitable for sub-register argument");
|
||||
lint.span_label(expr.span, "for this argument");
|
||||
lint.help(format!(
|
||||
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}` (for {suggested_size}-bit values)",
|
||||
|
|
|
|||
|
|
@ -675,11 +675,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
|||
let region_param = gat_generics.param_at(*region_a_idx, tcx);
|
||||
let region_param = ty::Region::new_early_param(
|
||||
tcx,
|
||||
ty::EarlyParamRegion {
|
||||
def_id: region_param.def_id,
|
||||
index: region_param.index,
|
||||
name: region_param.name,
|
||||
},
|
||||
ty::EarlyParamRegion { index: region_param.index, name: region_param.name },
|
||||
);
|
||||
// The predicate we expect to see. (In our example,
|
||||
// `Self: 'me`.)
|
||||
|
|
@ -708,21 +704,13 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
|||
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
|
||||
let region_a_param = ty::Region::new_early_param(
|
||||
tcx,
|
||||
ty::EarlyParamRegion {
|
||||
def_id: region_a_param.def_id,
|
||||
index: region_a_param.index,
|
||||
name: region_a_param.name,
|
||||
},
|
||||
ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name },
|
||||
);
|
||||
// Same for the region.
|
||||
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
|
||||
let region_b_param = ty::Region::new_early_param(
|
||||
tcx,
|
||||
ty::EarlyParamRegion {
|
||||
def_id: region_b_param.def_id,
|
||||
index: region_b_param.index,
|
||||
name: region_b_param.name,
|
||||
},
|
||||
ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name },
|
||||
);
|
||||
// The predicate we expect to see.
|
||||
bounds.insert(
|
||||
|
|
@ -2101,16 +2089,14 @@ fn lint_redundant_lifetimes<'tcx>(
|
|||
}
|
||||
|
||||
for &victim in &lifetimes[(idx + 1)..] {
|
||||
// We should only have late-bound lifetimes of the `BrNamed` variety,
|
||||
// since we get these signatures straight from `hir_lowering`. And any
|
||||
// other regions (ReError/ReStatic/etc.) shouldn't matter, since we
|
||||
// All region parameters should have a `DefId` available as:
|
||||
// - Late-bound parameters should be of the`BrNamed` variety,
|
||||
// since we get these signatures straight from `hir_lowering`.
|
||||
// - Early-bound parameters unconditionally have a `DefId` available.
|
||||
//
|
||||
// Any other regions (ReError/ReStatic/etc.) shouldn't matter, since we
|
||||
// can't really suggest to remove them.
|
||||
let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
|
||||
| ty::ReLateParam(ty::LateParamRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
})) = victim.kind()
|
||||
else {
|
||||
let Some(def_id) = victim.opt_param_def_id(tcx, owner_id.to_def_id()) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,11 +35,12 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
|
|||
continue;
|
||||
}
|
||||
let (path, _) = item.expect_use();
|
||||
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
|
||||
format!("unused import: `{snippet}`")
|
||||
} else {
|
||||
"unused import".to_owned()
|
||||
};
|
||||
tcx.node_span_lint(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, msg, |_| {});
|
||||
tcx.node_span_lint(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, |lint| {
|
||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
|
||||
lint.primary_message(format!("unused import: `{snippet}`"));
|
||||
} else {
|
||||
lint.primary_message("unused import");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -453,7 +453,6 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
|||
poly_trait_ref,
|
||||
|_| {
|
||||
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
|
||||
def_id: item_def_id,
|
||||
index: 0,
|
||||
name: Symbol::intern(<_name),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -317,8 +317,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
|
||||
param.hir_id,
|
||||
param.span,
|
||||
TYPE_DEFAULT_NOT_ALLOWED,
|
||||
|_| {},
|
||||
|lint| {
|
||||
lint.primary_message(TYPE_DEFAULT_NOT_ALLOWED);
|
||||
},
|
||||
);
|
||||
}
|
||||
Defaults::Deny => {
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
|
|||
if let ty::ReEarlyParam(..) = *orig_lifetime {
|
||||
let dup_lifetime = ty::Region::new_early_param(
|
||||
tcx,
|
||||
ty::EarlyParamRegion { def_id: param.def_id, index: param.index, name: param.name },
|
||||
ty::EarlyParamRegion { index: param.index, name: param.name },
|
||||
);
|
||||
let span = tcx.def_span(param.def_id);
|
||||
predicates.push((
|
||||
|
|
|
|||
|
|
@ -646,8 +646,9 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
|||
LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||
args.args[0].hir_id(),
|
||||
multispan,
|
||||
msg,
|
||||
|_| {},
|
||||
|lint| {
|
||||
lint.primary_message(msg);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
|
||||
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
|
||||
} else {
|
||||
let msg = "trait objects without an explicit `dyn` are deprecated";
|
||||
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
|
||||
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
|
||||
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
|
||||
if self_ty.span.can_be_used_for_suggestions() {
|
||||
lint.multipart_suggestion_verbose(
|
||||
"if this is an object-safe trait, use `dyn`",
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.param_def_id_to_index[&def_id];
|
||||
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name })
|
||||
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
|
||||
}
|
||||
|
||||
Some(rbv::ResolvedArg::Free(scope, id)) => {
|
||||
|
|
@ -1165,33 +1165,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let ty = self.lower_assoc_ty(span, assoc_ty_did, assoc_segment, bound);
|
||||
|
||||
if let Some(variant_def_id) = variant_resolution {
|
||||
tcx.node_span_lint(
|
||||
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||
hir_ref_id,
|
||||
span,
|
||||
"ambiguous associated item",
|
||||
|lint| {
|
||||
let mut could_refer_to = |kind: DefKind, def_id, also| {
|
||||
let note_msg = format!(
|
||||
"`{}` could{} refer to the {} defined here",
|
||||
assoc_ident,
|
||||
also,
|
||||
tcx.def_kind_descr(kind, def_id)
|
||||
);
|
||||
lint.span_note(tcx.def_span(def_id), note_msg);
|
||||
};
|
||||
|
||||
could_refer_to(DefKind::Variant, variant_def_id, "");
|
||||
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
|
||||
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"use fully-qualified syntax",
|
||||
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
|
||||
Applicability::MachineApplicable,
|
||||
tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
|
||||
lint.primary_message("ambiguous associated item");
|
||||
let mut could_refer_to = |kind: DefKind, def_id, also| {
|
||||
let note_msg = format!(
|
||||
"`{}` could{} refer to the {} defined here",
|
||||
assoc_ident,
|
||||
also,
|
||||
tcx.def_kind_descr(kind, def_id)
|
||||
);
|
||||
},
|
||||
);
|
||||
lint.span_note(tcx.def_span(def_id), note_msg);
|
||||
};
|
||||
|
||||
could_refer_to(DefKind::Variant, variant_def_id, "");
|
||||
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
|
||||
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"use fully-qualified syntax",
|
||||
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
}
|
||||
Ok((ty, DefKind::AssocTy, assoc_ty_did))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ This API is completely unstable and subject to change.
|
|||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(try_blocks)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1871,11 +1871,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
// If this is due to a block, then maybe we forgot a `return`/`break`.
|
||||
if due_to_block
|
||||
&& let Some(expr) = expression
|
||||
&& let Some((parent_fn_decl, parent_id)) = fcx
|
||||
.tcx
|
||||
.hir()
|
||||
.parent_iter(block_or_return_id)
|
||||
.find_map(|(_, node)| Some((node.fn_decl()?, node.associated_body()?.0)))
|
||||
&& let Some(parent_fn_decl) =
|
||||
fcx.tcx.hir().fn_decl_by_hir_id(fcx.tcx.local_def_id_to_hir_id(fcx.body_id))
|
||||
{
|
||||
fcx.suggest_missing_break_or_return_expr(
|
||||
&mut err,
|
||||
|
|
@ -1884,7 +1881,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
expected,
|
||||
found,
|
||||
block_or_return_id,
|
||||
parent_id,
|
||||
fcx.body_id,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1741,7 +1741,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
}
|
||||
|
||||
PatKind::Slice(before, ref slice, after) => {
|
||||
let Some(element_ty) = place_with_id.place.ty().builtin_index() else {
|
||||
let Some(element_ty) = self
|
||||
.cx
|
||||
.try_structurally_resolve_type(pat.span, place_with_id.place.ty())
|
||||
.builtin_index()
|
||||
else {
|
||||
debug!("explicit index of non-indexable type {:?}", place_with_id);
|
||||
return Err(self
|
||||
.cx
|
||||
|
|
|
|||
|
|
@ -64,19 +64,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
|
||||
|
||||
let msg = format!("unreachable {kind}");
|
||||
self.tcx().node_span_lint(
|
||||
lint::builtin::UNREACHABLE_CODE,
|
||||
id,
|
||||
span,
|
||||
msg.clone(),
|
||||
|lint| {
|
||||
lint.span_label(span, msg).span_label(
|
||||
orig_span,
|
||||
custom_note
|
||||
.unwrap_or("any code following this expression is unreachable"),
|
||||
);
|
||||
},
|
||||
)
|
||||
self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
|
||||
lint.primary_message(msg.clone());
|
||||
lint.span_label(span, msg).span_label(
|
||||
orig_span,
|
||||
custom_note.unwrap_or("any code following this expression is unreachable"),
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,11 +91,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
prelude_or_array_lint,
|
||||
self_expr.hir_id,
|
||||
self_expr.span,
|
||||
format!(
|
||||
"trait method `{}` will become ambiguous in Rust {edition}",
|
||||
segment.ident.name
|
||||
),
|
||||
|lint| {
|
||||
lint.primary_message(format!(
|
||||
"trait method `{}` will become ambiguous in Rust {edition}",
|
||||
segment.ident.name
|
||||
));
|
||||
|
||||
let sp = self_expr.span;
|
||||
|
||||
let derefs = "*".repeat(pick.autoderefs);
|
||||
|
|
@ -144,11 +145,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
prelude_or_array_lint,
|
||||
call_expr.hir_id,
|
||||
call_expr.span,
|
||||
format!(
|
||||
"trait method `{}` will become ambiguous in Rust {edition}",
|
||||
segment.ident.name
|
||||
),
|
||||
|lint| {
|
||||
lint.primary_message(format!(
|
||||
"trait method `{}` will become ambiguous in Rust {edition}",
|
||||
segment.ident.name
|
||||
));
|
||||
|
||||
let sp = call_expr.span;
|
||||
let trait_name = self.trait_path_or_bare_name(
|
||||
span,
|
||||
|
|
@ -251,73 +253,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
self.tcx.node_span_lint(
|
||||
RUST_2021_PRELUDE_COLLISIONS,
|
||||
expr_id,
|
||||
span,
|
||||
format!(
|
||||
self.tcx.node_span_lint(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
|
||||
lint.primary_message(format!(
|
||||
"trait-associated function `{}` will become ambiguous in Rust 2021",
|
||||
method_name.name
|
||||
),
|
||||
|lint| {
|
||||
// "type" refers to either a type or, more likely, a trait from which
|
||||
// the associated function or method is from.
|
||||
let container_id = pick.item.container_id(self.tcx);
|
||||
let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
|
||||
let trait_generics = self.tcx.generics_of(container_id);
|
||||
));
|
||||
|
||||
let trait_name =
|
||||
if trait_generics.own_params.len() <= trait_generics.has_self as usize {
|
||||
trait_path
|
||||
} else {
|
||||
let counts = trait_generics.own_counts();
|
||||
format!(
|
||||
"{}<{}>",
|
||||
trait_path,
|
||||
// "type" refers to either a type or, more likely, a trait from which
|
||||
// the associated function or method is from.
|
||||
let container_id = pick.item.container_id(self.tcx);
|
||||
let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
|
||||
let trait_generics = self.tcx.generics_of(container_id);
|
||||
|
||||
let trait_name =
|
||||
if trait_generics.own_params.len() <= trait_generics.has_self as usize {
|
||||
trait_path
|
||||
} else {
|
||||
let counts = trait_generics.own_counts();
|
||||
format!(
|
||||
"{}<{}>",
|
||||
trait_path,
|
||||
std::iter::repeat("'_")
|
||||
.take(counts.lifetimes)
|
||||
.chain(std::iter::repeat("_").take(
|
||||
counts.types + counts.consts - trait_generics.has_self as usize
|
||||
))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
};
|
||||
|
||||
let mut self_ty_name = self_ty_span
|
||||
.find_ancestor_inside(span)
|
||||
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
|
||||
.unwrap_or_else(|| self_ty.to_string());
|
||||
|
||||
// Get the number of generics the self type has (if an Adt) unless we can determine that
|
||||
// the user has written the self type with generics already which we (naively) do by looking
|
||||
// for a "<" in `self_ty_name`.
|
||||
if !self_ty_name.contains('<') {
|
||||
if let ty::Adt(def, _) = self_ty.kind() {
|
||||
let generics = self.tcx.generics_of(def.did());
|
||||
if !generics.is_own_empty() {
|
||||
let counts = generics.own_counts();
|
||||
self_ty_name += &format!(
|
||||
"<{}>",
|
||||
std::iter::repeat("'_")
|
||||
.take(counts.lifetimes)
|
||||
.chain(std::iter::repeat("_").take(
|
||||
counts.types + counts.consts - trait_generics.has_self as usize
|
||||
))
|
||||
.chain(std::iter::repeat("_").take(counts.types + counts.consts))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
};
|
||||
|
||||
let mut self_ty_name = self_ty_span
|
||||
.find_ancestor_inside(span)
|
||||
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
|
||||
.unwrap_or_else(|| self_ty.to_string());
|
||||
|
||||
// Get the number of generics the self type has (if an Adt) unless we can determine that
|
||||
// the user has written the self type with generics already which we (naively) do by looking
|
||||
// for a "<" in `self_ty_name`.
|
||||
if !self_ty_name.contains('<') {
|
||||
if let ty::Adt(def, _) = self_ty.kind() {
|
||||
let generics = self.tcx.generics_of(def.did());
|
||||
if !generics.is_own_empty() {
|
||||
let counts = generics.own_counts();
|
||||
self_ty_name += &format!(
|
||||
"<{}>",
|
||||
std::iter::repeat("'_")
|
||||
.take(counts.lifetimes)
|
||||
.chain(
|
||||
std::iter::repeat("_").take(counts.types + counts.consts)
|
||||
)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"disambiguate the associated function",
|
||||
format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"disambiguate the associated function",
|
||||
format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn trait_path_or_bare_name(
|
||||
|
|
|
|||
|
|
@ -395,8 +395,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// ambiguous.
|
||||
if let Some(bad_ty) = &steps.opt_bad_ty {
|
||||
if is_suggestion.0 {
|
||||
// Ambiguity was encountered during a suggestion. Just keep going.
|
||||
debug!("ProbeContext: encountered ambiguity in suggestion");
|
||||
// Ambiguity was encountered during a suggestion. There's really
|
||||
// not much use in suggesting methods in this case.
|
||||
return Err(MethodError::NoMatch(NoMatchData {
|
||||
static_candidates: Vec::new(),
|
||||
unsatisfied_predicates: Vec::new(),
|
||||
out_of_scope_traits: Vec::new(),
|
||||
similar_candidate: None,
|
||||
mode,
|
||||
}));
|
||||
} else if bad_ty.reached_raw_pointer
|
||||
&& !self.tcx.features().arbitrary_self_types
|
||||
&& !self.tcx.sess.at_least_rust_2018()
|
||||
|
|
@ -408,8 +415,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
"type annotations needed",
|
||||
|_| {},
|
||||
|lint| {
|
||||
lint.primary_message("type annotations needed");
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// Ended up encountering a type variable when doing autoderef,
|
||||
|
|
@ -1279,53 +1287,49 @@ impl<'tcx> Pick<'tcx> {
|
|||
return;
|
||||
}
|
||||
let def_kind = self.item.kind.as_def_kind();
|
||||
tcx.node_span_lint(
|
||||
lint::builtin::UNSTABLE_NAME_COLLISIONS,
|
||||
scope_expr_id,
|
||||
span,
|
||||
format!(
|
||||
tcx.node_span_lint(lint::builtin::UNSTABLE_NAME_COLLISIONS, scope_expr_id, span, |lint| {
|
||||
lint.primary_message(format!(
|
||||
"{} {} with this name may be added to the standard library in the future",
|
||||
tcx.def_kind_descr_article(def_kind, self.item.def_id),
|
||||
tcx.def_kind_descr(def_kind, self.item.def_id),
|
||||
),
|
||||
|lint| {
|
||||
match (self.item.kind, self.item.container) {
|
||||
(ty::AssocKind::Fn, _) => {
|
||||
// FIXME: This should be a `span_suggestion` instead of `help`
|
||||
// However `self.span` only
|
||||
// highlights the method name, so we can't use it. Also consider reusing
|
||||
// the code from `report_method_error()`.
|
||||
lint.help(format!(
|
||||
"call with fully qualified syntax `{}(...)` to keep using the current \
|
||||
));
|
||||
|
||||
match (self.item.kind, self.item.container) {
|
||||
(ty::AssocKind::Fn, _) => {
|
||||
// FIXME: This should be a `span_suggestion` instead of `help`
|
||||
// However `self.span` only
|
||||
// highlights the method name, so we can't use it. Also consider reusing
|
||||
// the code from `report_method_error()`.
|
||||
lint.help(format!(
|
||||
"call with fully qualified syntax `{}(...)` to keep using the current \
|
||||
method",
|
||||
tcx.def_path_str(self.item.def_id),
|
||||
));
|
||||
}
|
||||
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
|
||||
let def_id = self.item.container_id(tcx);
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"use the fully qualified path to the associated const",
|
||||
format!(
|
||||
"<{} as {}>::{}",
|
||||
self.self_ty,
|
||||
tcx.def_path_str(def_id),
|
||||
self.item.name
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
tcx.def_path_str(self.item.def_id),
|
||||
));
|
||||
}
|
||||
tcx.disabled_nightly_features(
|
||||
lint,
|
||||
Some(scope_expr_id),
|
||||
self.unstable_candidates.iter().map(|(candidate, feature)| {
|
||||
(format!(" `{}`", tcx.def_path_str(candidate.item.def_id)), *feature)
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
|
||||
let def_id = self.item.container_id(tcx);
|
||||
lint.span_suggestion(
|
||||
span,
|
||||
"use the fully qualified path to the associated const",
|
||||
format!(
|
||||
"<{} as {}>::{}",
|
||||
self.self_ty,
|
||||
tcx.def_path_str(def_id),
|
||||
self.item.name
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
tcx.disabled_nightly_features(
|
||||
lint,
|
||||
Some(scope_expr_id),
|
||||
self.unstable_candidates.iter().map(|(candidate, feature)| {
|
||||
(format!(" `{}`", tcx.def_path_str(candidate.item.def_id)), *feature)
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1950,15 +1950,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
self.tcx.node_span_lint(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
|
||||
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
|
||||
lint.help(
|
||||
"ensure that all fields are mentioned explicitly by adding the suggested fields",
|
||||
);
|
||||
lint.note(format!(
|
||||
"the pattern is of type `{ty}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
||||
));
|
||||
});
|
||||
self.tcx.node_span_lint(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |lint| {
|
||||
lint.primary_message("some fields are not explicitly listed");
|
||||
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
|
||||
lint.help(
|
||||
"ensure that all fields are mentioned explicitly by adding the suggested fields",
|
||||
);
|
||||
lint.note(format!(
|
||||
"the pattern is of type `{ty}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns a diagnostic reporting a struct pattern which does not mention some fields.
|
||||
|
|
|
|||
|
|
@ -955,8 +955,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
|
||||
closure_hir_id,
|
||||
closure_head_span,
|
||||
reasons.migration_message(),
|
||||
|lint| {
|
||||
lint.primary_message(reasons.migration_message());
|
||||
|
||||
for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
|
||||
// Labels all the usage of the captured variable and why they are responsible
|
||||
// for migration being needed
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use rustc_errors::{
|
|||
MultiSpan, SubdiagMessageOp, Subdiagnostic,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{walk_ty, Visitor};
|
||||
use rustc_hir::FnRetTy;
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
|
|
@ -344,6 +345,7 @@ impl Subdiagnostic for LifetimeMismatchLabels {
|
|||
|
||||
pub struct AddLifetimeParamsSuggestion<'a> {
|
||||
pub tcx: TyCtxt<'a>,
|
||||
pub generic_param_scope: LocalDefId,
|
||||
pub sub: Region<'a>,
|
||||
pub ty_sup: &'a hir::Ty<'a>,
|
||||
pub ty_sub: &'a hir::Ty<'a>,
|
||||
|
|
@ -357,7 +359,8 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
|
|||
_f: &F,
|
||||
) {
|
||||
let mut mk_suggestion = || {
|
||||
let Some(anon_reg) = self.tcx.is_suitable_region(self.sub) else {
|
||||
let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::fluent_generated as fluent;
|
||||
use crate::infer::error_reporting::nice_region_error::find_anon_type;
|
||||
use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::{symbol::kw, Span};
|
||||
|
|
@ -14,12 +15,15 @@ struct DescriptionCtx<'a> {
|
|||
impl<'a> DescriptionCtx<'a> {
|
||||
fn new<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
region: ty::Region<'tcx>,
|
||||
alt_span: Option<Span>,
|
||||
) -> Option<Self> {
|
||||
let (span, kind, arg) = match *region {
|
||||
ty::ReEarlyParam(ref br) => {
|
||||
let scope = region.free_region_binding_scope(tcx).expect_local();
|
||||
ty::ReEarlyParam(br) => {
|
||||
let scope = tcx
|
||||
.parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
|
||||
.expect_local();
|
||||
let span = if let Some(param) =
|
||||
tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
|
||||
{
|
||||
|
|
@ -35,11 +39,12 @@ impl<'a> DescriptionCtx<'a> {
|
|||
}
|
||||
ty::ReLateParam(ref fr) => {
|
||||
if !fr.bound_region.is_named()
|
||||
&& let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
|
||||
&& let Some((ty, _)) =
|
||||
find_anon_type(tcx, generic_param_scope, region, &fr.bound_region)
|
||||
{
|
||||
(Some(ty.span), "defined_here", String::new())
|
||||
} else {
|
||||
let scope = region.free_region_binding_scope(tcx).expect_local();
|
||||
let scope = fr.scope.expect_local();
|
||||
match fr.bound_region {
|
||||
ty::BoundRegionKind::BrNamed(_, name) => {
|
||||
let span = if let Some(param) = tcx
|
||||
|
|
@ -143,12 +148,17 @@ pub struct RegionExplanation<'a> {
|
|||
impl RegionExplanation<'_> {
|
||||
pub fn new<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
region: ty::Region<'tcx>,
|
||||
alt_span: Option<Span>,
|
||||
prefix: PrefixKind,
|
||||
suffix: SuffixKind,
|
||||
) -> Option<Self> {
|
||||
Some(Self { desc: DescriptionCtx::new(tcx, region, alt_span)?, prefix, suffix })
|
||||
Some(Self {
|
||||
desc: DescriptionCtx::new(tcx, generic_param_scope, region, alt_span)?,
|
||||
prefix,
|
||||
suffix,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
|
|||
pub(super) fn note_and_explain_region<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
err: &mut Diag<'_>,
|
||||
generic_param_scope: LocalDefId,
|
||||
prefix: &str,
|
||||
region: ty::Region<'tcx>,
|
||||
suffix: &str,
|
||||
|
|
@ -168,7 +169,7 @@ pub(super) fn note_and_explain_region<'tcx>(
|
|||
) {
|
||||
let (description, span) = match *region {
|
||||
ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => {
|
||||
msg_span_from_named_region(tcx, region, alt_span)
|
||||
msg_span_from_named_region(tcx, generic_param_scope, region, alt_span)
|
||||
}
|
||||
|
||||
ty::ReError(_) => return,
|
||||
|
|
@ -187,23 +188,27 @@ pub(super) fn note_and_explain_region<'tcx>(
|
|||
fn explain_free_region<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
err: &mut Diag<'_>,
|
||||
generic_param_scope: LocalDefId,
|
||||
prefix: &str,
|
||||
region: ty::Region<'tcx>,
|
||||
suffix: &str,
|
||||
) {
|
||||
let (description, span) = msg_span_from_named_region(tcx, region, None);
|
||||
let (description, span) = msg_span_from_named_region(tcx, generic_param_scope, region, None);
|
||||
|
||||
label_msg_span(err, prefix, description, span, suffix);
|
||||
}
|
||||
|
||||
fn msg_span_from_named_region<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
region: ty::Region<'tcx>,
|
||||
alt_span: Option<Span>,
|
||||
) -> (String, Option<Span>) {
|
||||
match *region {
|
||||
ty::ReEarlyParam(ref br) => {
|
||||
let scope = region.free_region_binding_scope(tcx).expect_local();
|
||||
ty::ReEarlyParam(br) => {
|
||||
let scope = tcx
|
||||
.parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
|
||||
.expect_local();
|
||||
let span = if let Some(param) =
|
||||
tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
|
||||
{
|
||||
|
|
@ -220,21 +225,21 @@ fn msg_span_from_named_region<'tcx>(
|
|||
}
|
||||
ty::ReLateParam(ref fr) => {
|
||||
if !fr.bound_region.is_named()
|
||||
&& let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
|
||||
&& let Some((ty, _)) =
|
||||
find_anon_type(tcx, generic_param_scope, region, &fr.bound_region)
|
||||
{
|
||||
("the anonymous lifetime defined here".to_string(), Some(ty.span))
|
||||
} else {
|
||||
let scope = region.free_region_binding_scope(tcx).expect_local();
|
||||
match fr.bound_region {
|
||||
ty::BoundRegionKind::BrNamed(_, name) => {
|
||||
let span = if let Some(param) = tcx
|
||||
.hir()
|
||||
.get_generics(scope)
|
||||
.get_generics(generic_param_scope)
|
||||
.and_then(|generics| generics.get_named(name))
|
||||
{
|
||||
param.span
|
||||
} else {
|
||||
tcx.def_span(scope)
|
||||
tcx.def_span(generic_param_scope)
|
||||
};
|
||||
let text = if name == kw::UnderscoreLifetime {
|
||||
"the anonymous lifetime as defined here".to_string()
|
||||
|
|
@ -245,11 +250,11 @@ fn msg_span_from_named_region<'tcx>(
|
|||
}
|
||||
ty::BrAnon => (
|
||||
"the anonymous lifetime as defined here".to_string(),
|
||||
Some(tcx.def_span(scope)),
|
||||
Some(tcx.def_span(generic_param_scope)),
|
||||
),
|
||||
_ => (
|
||||
format!("the lifetime `{region}` as defined here"),
|
||||
Some(tcx.def_span(scope)),
|
||||
Some(tcx.def_span(generic_param_scope)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
@ -302,6 +307,7 @@ fn label_msg_span(
|
|||
#[instrument(level = "trace", skip(tcx))]
|
||||
pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
span: Span,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
hidden_region: ty::Region<'tcx>,
|
||||
|
|
@ -327,11 +333,12 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
|||
explain_free_region(
|
||||
tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
&format!("hidden type `{hidden_ty}` captures "),
|
||||
hidden_region,
|
||||
"",
|
||||
);
|
||||
if let Some(reg_info) = tcx.is_suitable_region(hidden_region) {
|
||||
if let Some(reg_info) = tcx.is_suitable_region(generic_param_scope, hidden_region) {
|
||||
let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id);
|
||||
nice_region_error::suggest_new_region_bound(
|
||||
tcx,
|
||||
|
|
@ -349,6 +356,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
|||
explain_free_region(
|
||||
tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
&format!("hidden type `{}` captures ", hidden_ty),
|
||||
hidden_region,
|
||||
"",
|
||||
|
|
@ -376,6 +384,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
|||
note_and_explain_region(
|
||||
tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
&format!("hidden type `{hidden_ty}` captures "),
|
||||
hidden_region,
|
||||
"",
|
||||
|
|
@ -450,7 +459,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
for error in errors {
|
||||
debug!("report_region_errors: error = {:?}", error);
|
||||
|
||||
guar = Some(if let Some(guar) = self.try_report_nice_region_error(&error) {
|
||||
let e = if let Some(guar) =
|
||||
self.try_report_nice_region_error(generic_param_scope, &error)
|
||||
{
|
||||
guar
|
||||
} else {
|
||||
match error.clone() {
|
||||
|
|
@ -463,9 +474,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
// general bit of code that displays the error information
|
||||
RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
|
||||
if sub.is_placeholder() || sup.is_placeholder() {
|
||||
self.report_placeholder_failure(origin, sub, sup).emit()
|
||||
self.report_placeholder_failure(generic_param_scope, origin, sub, sup)
|
||||
.emit()
|
||||
} else {
|
||||
self.report_concrete_failure(origin, sub, sup).emit()
|
||||
self.report_concrete_failure(generic_param_scope, origin, sub, sup)
|
||||
.emit()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -488,12 +501,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
_,
|
||||
) => {
|
||||
if sub_r.is_placeholder() {
|
||||
self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit()
|
||||
self.report_placeholder_failure(
|
||||
generic_param_scope,
|
||||
sub_origin,
|
||||
sub_r,
|
||||
sup_r,
|
||||
)
|
||||
.emit()
|
||||
} else if sup_r.is_placeholder() {
|
||||
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit()
|
||||
self.report_placeholder_failure(
|
||||
generic_param_scope,
|
||||
sup_origin,
|
||||
sub_r,
|
||||
sup_r,
|
||||
)
|
||||
.emit()
|
||||
} else {
|
||||
self.report_sub_sup_conflict(
|
||||
var_origin, sub_origin, sub_r, sup_origin, sup_r,
|
||||
generic_param_scope,
|
||||
var_origin,
|
||||
sub_origin,
|
||||
sub_r,
|
||||
sup_origin,
|
||||
sup_r,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -514,7 +544,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
// value.
|
||||
let sub_r = self.tcx.lifetimes.re_erased;
|
||||
|
||||
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit()
|
||||
self.report_placeholder_failure(
|
||||
generic_param_scope,
|
||||
sup_origin,
|
||||
sub_r,
|
||||
sup_r,
|
||||
)
|
||||
.emit()
|
||||
}
|
||||
|
||||
RegionResolutionError::CannotNormalize(clause, origin) => {
|
||||
|
|
@ -526,7 +562,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
.emit()
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
guar = Some(e)
|
||||
}
|
||||
|
||||
guar.unwrap()
|
||||
|
|
@ -2347,7 +2385,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
'_explain: {
|
||||
let (description, span) = match sub.kind() {
|
||||
ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
|
||||
msg_span_from_named_region(self.tcx, sub, Some(span))
|
||||
msg_span_from_named_region(self.tcx, generic_param_scope, sub, Some(span))
|
||||
}
|
||||
_ => (format!("lifetime `{sub}`"), Some(span)),
|
||||
};
|
||||
|
|
@ -2398,7 +2436,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
let suggestion_scope = {
|
||||
let lifetime_scope = match sub.kind() {
|
||||
ty::ReStatic => hir::def_id::CRATE_DEF_ID,
|
||||
_ => match self.tcx.is_suitable_region(sub) {
|
||||
_ => match self.tcx.is_suitable_region(generic_param_scope, sub) {
|
||||
Some(info) => info.def_id,
|
||||
None => generic_param_scope,
|
||||
},
|
||||
|
|
@ -2410,7 +2448,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
};
|
||||
|
||||
let mut suggs = vec![];
|
||||
let lt_name = self.suggest_name_region(sub, &mut suggs);
|
||||
let lt_name = self.suggest_name_region(generic_param_scope, sub, &mut suggs);
|
||||
|
||||
if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span
|
||||
&& suggestion_scope == type_scope
|
||||
|
|
@ -2455,6 +2493,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
pub fn suggest_name_region(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
lifetime: Region<'tcx>,
|
||||
add_lt_suggs: &mut Vec<(Span, String)>,
|
||||
) -> String {
|
||||
|
|
@ -2501,12 +2540,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) {
|
||||
Some(info) if !lifetime.has_name() => {
|
||||
(info.bound_region.get_id().unwrap().expect_local(), info.def_id)
|
||||
}
|
||||
_ => return lifetime.get_name_or_anon().to_string(),
|
||||
};
|
||||
let (lifetime_def_id, lifetime_scope) =
|
||||
match self.tcx.is_suitable_region(generic_param_scope, lifetime) {
|
||||
Some(info) if !lifetime.has_name() => {
|
||||
(info.bound_region.get_id().unwrap().expect_local(), info.def_id)
|
||||
}
|
||||
_ => return lifetime.get_name_or_anon().to_string(),
|
||||
};
|
||||
|
||||
let new_lt = {
|
||||
let generics = self.tcx.generics_of(lifetime_scope);
|
||||
|
|
@ -2557,6 +2597,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
fn report_sub_sup_conflict(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
var_origin: RegionVariableOrigin,
|
||||
sub_origin: SubregionOrigin<'tcx>,
|
||||
sub_region: Region<'tcx>,
|
||||
|
|
@ -2568,6 +2609,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"first, the lifetime cannot outlive ",
|
||||
sup_region,
|
||||
"...",
|
||||
|
|
@ -2590,6 +2632,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"...but the lifetime must also be valid for ",
|
||||
sub_region,
|
||||
"...",
|
||||
|
|
@ -2613,6 +2656,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"but, the lifetime must be valid for ",
|
||||
sub_region,
|
||||
"...",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use crate::infer::TyCtxt;
|
|||
|
||||
use rustc_errors::Subdiagnostic;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::Ty;
|
||||
use rustc_middle::ty::Region;
|
||||
|
||||
|
|
@ -66,17 +67,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// Determine whether the sub and sup consist of both anonymous (elided) regions.
|
||||
let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
|
||||
let anon_reg_sup = self.tcx().is_suitable_region(self.generic_param_scope, sup)?;
|
||||
|
||||
let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
|
||||
let anon_reg_sub = self.tcx().is_suitable_region(self.generic_param_scope, sub)?;
|
||||
let scope_def_id_sup = anon_reg_sup.def_id;
|
||||
let bregion_sup = anon_reg_sup.bound_region;
|
||||
let scope_def_id_sub = anon_reg_sub.def_id;
|
||||
let bregion_sub = anon_reg_sub.bound_region;
|
||||
|
||||
let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?;
|
||||
let ty_sup = find_anon_type(self.tcx(), self.generic_param_scope, sup, &bregion_sup)?;
|
||||
|
||||
let ty_sub = find_anon_type(self.tcx(), sub, &bregion_sub)?;
|
||||
let ty_sub = find_anon_type(self.tcx(), self.generic_param_scope, sub, &bregion_sub)?;
|
||||
|
||||
debug!(
|
||||
"try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
|
||||
|
|
@ -127,8 +128,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
},
|
||||
};
|
||||
|
||||
let suggestion =
|
||||
AddLifetimeParamsSuggestion { tcx: self.tcx(), sub, ty_sup, ty_sub, add_note: true };
|
||||
let suggestion = AddLifetimeParamsSuggestion {
|
||||
tcx: self.tcx(),
|
||||
sub,
|
||||
ty_sup,
|
||||
ty_sub,
|
||||
add_note: true,
|
||||
generic_param_scope: self.generic_param_scope,
|
||||
};
|
||||
let err = LifetimeMismatch { span, labels, suggestion };
|
||||
let reported = self.tcx().dcx().emit_err(err);
|
||||
Some(reported)
|
||||
|
|
@ -139,11 +146,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
/// removed in favour of public_errors::AddLifetimeParamsSuggestion
|
||||
pub fn suggest_adding_lifetime_params<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
err: &mut Diag<'_>,
|
||||
generic_param_scope: LocalDefId,
|
||||
sub: Region<'tcx>,
|
||||
ty_sup: &'tcx Ty<'_>,
|
||||
ty_sub: &'tcx Ty<'_>,
|
||||
err: &mut Diag<'_>,
|
||||
) {
|
||||
let suggestion = AddLifetimeParamsSuggestion { tcx, sub, ty_sup, ty_sub, add_note: false };
|
||||
let suggestion = AddLifetimeParamsSuggestion {
|
||||
tcx,
|
||||
sub,
|
||||
ty_sup,
|
||||
ty_sub,
|
||||
add_note: false,
|
||||
generic_param_scope,
|
||||
};
|
||||
suggestion.add_to_diag(err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use core::ops::ControlFlow;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
|
@ -23,10 +24,11 @@ use rustc_middle::ty::{self, Region, TyCtxt};
|
|||
/// for e.g., `&u8` and `Vec<&u8>`.
|
||||
pub fn find_anon_type<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
region: Region<'tcx>,
|
||||
br: &ty::BoundRegionKind,
|
||||
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> {
|
||||
let anon_reg = tcx.is_suitable_region(region)?;
|
||||
let anon_reg = tcx.is_suitable_region(generic_param_scope, region)?;
|
||||
let fn_sig = tcx.hir_node_by_def_id(anon_reg.def_id).fn_sig()?;
|
||||
|
||||
fn_sig
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
|
||||
let expl = note_and_explain::RegionExplanation::new(
|
||||
self.tcx(),
|
||||
self.generic_param_scope,
|
||||
sup,
|
||||
Some(binding_span),
|
||||
note_and_explain::PrefixKind::Empty,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::infer::error_reporting::TypeErrCtxt;
|
|||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||
use crate::infer::lexical_region_resolve::RegionResolutionError::*;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
|
@ -23,30 +24,39 @@ pub use util::find_param_with_region;
|
|||
impl<'cx, 'tcx> TypeErrCtxt<'cx, 'tcx> {
|
||||
pub fn try_report_nice_region_error(
|
||||
&'cx self,
|
||||
generic_param_scope: LocalDefId,
|
||||
error: &RegionResolutionError<'tcx>,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
NiceRegionError::new(self, error.clone()).try_report()
|
||||
NiceRegionError::new(self, generic_param_scope, error.clone()).try_report()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NiceRegionError<'cx, 'tcx> {
|
||||
cx: &'cx TypeErrCtxt<'cx, 'tcx>,
|
||||
/// The innermost definition that introduces generic parameters that may be involved in
|
||||
/// the region errors we are dealing with.
|
||||
generic_param_scope: LocalDefId,
|
||||
error: Option<RegionResolutionError<'tcx>>,
|
||||
regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
||||
pub fn new(cx: &'cx TypeErrCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self {
|
||||
Self { cx, error: Some(error), regions: None }
|
||||
pub fn new(
|
||||
cx: &'cx TypeErrCtxt<'cx, 'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
error: RegionResolutionError<'tcx>,
|
||||
) -> Self {
|
||||
Self { cx, error: Some(error), regions: None, generic_param_scope }
|
||||
}
|
||||
|
||||
pub fn new_from_span(
|
||||
cx: &'cx TypeErrCtxt<'cx, 'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
span: Span,
|
||||
sub: ty::Region<'tcx>,
|
||||
sup: ty::Region<'tcx>,
|
||||
) -> Self {
|
||||
Self { cx, error: None, regions: Some((span, sub, sup)) }
|
||||
Self { cx, error: None, regions: Some((span, sub, sup)), generic_param_scope }
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
// version new_ty of its type where the anonymous region is replaced
|
||||
// with the named one.
|
||||
let (named, anon, anon_param_info, region_info) = if sub.has_name()
|
||||
&& let Some(region_info) = self.tcx().is_suitable_region(sup)
|
||||
&& let Some(region_info) = self.tcx().is_suitable_region(self.generic_param_scope, sup)
|
||||
&& let Some(anon_param_info) = self.find_param_with_region(sup, sub)
|
||||
{
|
||||
(sub, sup, anon_param_info, region_info)
|
||||
} else if sup.has_name()
|
||||
&& let Some(region_info) = self.tcx().is_suitable_region(sub)
|
||||
&& let Some(region_info) = self.tcx().is_suitable_region(self.generic_param_scope, sub)
|
||||
&& let Some(anon_param_info) = self.find_param_with_region(sub, sup)
|
||||
{
|
||||
(sup, sub, anon_param_info, region_info)
|
||||
|
|
@ -72,7 +72,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
|
||||
if find_anon_type(self.tcx(), anon, &br).is_some()
|
||||
if find_anon_type(self.tcx(), self.generic_param_scope, anon, &br).is_some()
|
||||
&& self.is_self_anon(is_first, scope_def_id)
|
||||
{
|
||||
return None;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() {
|
||||
// This may have a closure and it would cause ICE
|
||||
// through `find_param_with_region` (#78262).
|
||||
let anon_reg_sup = tcx.is_suitable_region(*sup_r)?;
|
||||
let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
|
||||
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
||||
if fn_returns.is_empty() {
|
||||
return None;
|
||||
|
|
@ -92,7 +92,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
"try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
|
||||
var_origin, sub_origin, sub_r, sup_origin, sup_r
|
||||
);
|
||||
let anon_reg_sup = tcx.is_suitable_region(*sup_r)?;
|
||||
let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
|
||||
debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
|
||||
let sp = var_origin.span();
|
||||
let return_sp = sub_origin.span();
|
||||
|
|
|
|||
|
|
@ -37,13 +37,15 @@ pub struct AnonymousParamInfo<'tcx> {
|
|||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn find_param_with_region<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
anon_region: Region<'tcx>,
|
||||
replace_region: Region<'tcx>,
|
||||
) -> Option<AnonymousParamInfo<'tcx>> {
|
||||
let (id, bound_region) = match *anon_region {
|
||||
ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region),
|
||||
ty::ReEarlyParam(ebr) => {
|
||||
(tcx.parent(ebr.def_id), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name))
|
||||
let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id;
|
||||
(tcx.parent(region_def), ty::BoundRegionKind::BrNamed(region_def, ebr.name))
|
||||
}
|
||||
_ => return None, // not a free region
|
||||
};
|
||||
|
|
@ -53,7 +55,7 @@ pub fn find_param_with_region<'tcx>(
|
|||
|
||||
// FIXME: use def_kind
|
||||
// Don't perform this on closures
|
||||
match tcx.hir_node_by_def_id(def_id) {
|
||||
match tcx.hir_node_by_def_id(generic_param_scope) {
|
||||
hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
|
||||
return None;
|
||||
}
|
||||
|
|
@ -110,7 +112,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
anon_region: Region<'tcx>,
|
||||
replace_region: Region<'tcx>,
|
||||
) -> Option<AnonymousParamInfo<'tcx>> {
|
||||
find_param_with_region(self.tcx(), anon_region, replace_region)
|
||||
find_param_with_region(self.tcx(), self.generic_param_scope, anon_region, replace_region)
|
||||
}
|
||||
|
||||
// Here, we check for the case where the anonymous region
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
pub(super) fn report_concrete_failure(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
|
|
@ -89,6 +90,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"",
|
||||
sup,
|
||||
" doesn't meet the lifetime requirements",
|
||||
|
|
@ -99,6 +101,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"the required lifetime does not necessarily outlive ",
|
||||
sub,
|
||||
"",
|
||||
|
|
@ -106,10 +109,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
}
|
||||
_ => {
|
||||
note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"",
|
||||
sup,
|
||||
"...",
|
||||
None,
|
||||
);
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"...does not necessarily outlive ",
|
||||
sub,
|
||||
"",
|
||||
|
|
@ -122,6 +134,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::Reborrow(span) => {
|
||||
let reference_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::RefValidFor,
|
||||
|
|
@ -129,6 +142,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
let content_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::ContentValidFor,
|
||||
|
|
@ -142,6 +156,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::RelateObjectBound(span) => {
|
||||
let object_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::TypeObjValidFor,
|
||||
|
|
@ -149,6 +164,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
let pointer_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::SourcePointerValidFor,
|
||||
|
|
@ -170,7 +186,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
note_and_explain::SuffixKind::Empty
|
||||
};
|
||||
let note = note_and_explain::RegionExplanation::new(
|
||||
self.tcx, sub, opt_span, prefix, suffix,
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
opt_span,
|
||||
prefix,
|
||||
suffix,
|
||||
);
|
||||
self.dcx().create_err(FulfillReqLifetime {
|
||||
span,
|
||||
|
|
@ -181,6 +202,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::RelateRegionParamBound(span) => {
|
||||
let param_instantiated = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfParamInstantiatedWith,
|
||||
|
|
@ -188,6 +210,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
let param_must_outlive = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfParamMustOutlive,
|
||||
|
|
@ -201,6 +224,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::ReferenceOutlivesReferent(ty, span) => {
|
||||
let pointer_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::PointerValidFor,
|
||||
|
|
@ -208,6 +232,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
let data_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::DataValidFor,
|
||||
|
|
@ -239,7 +264,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
err
|
||||
}
|
||||
infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
|
||||
let mut err = self.report_concrete_failure(*parent, sub, sup);
|
||||
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
|
||||
// folks.
|
||||
|
|
@ -262,6 +287,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::AscribeUserTypeProvePredicate(span) => {
|
||||
let instantiated = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfInstantiatedWith,
|
||||
|
|
@ -269,6 +295,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
let must_outlive = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfMustOutlive,
|
||||
|
|
@ -347,6 +374,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
pub(super) fn report_placeholder_failure(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
|
|
@ -368,7 +396,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
&& !span.is_dummy()
|
||||
{
|
||||
let span = *span;
|
||||
self.report_concrete_failure(placeholder_origin, sub, sup)
|
||||
self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
|
||||
.with_span_note(span, "the lifetime requirement is introduced here")
|
||||
} else {
|
||||
unreachable!(
|
||||
|
|
@ -380,7 +408,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
let terr = TypeError::RegionsPlaceholderMismatch;
|
||||
return self.report_and_explain_type_error(trace, terr);
|
||||
}
|
||||
_ => return self.report_concrete_failure(placeholder_origin, sub, sup),
|
||||
_ => {
|
||||
return self.report_concrete_failure(
|
||||
generic_param_scope,
|
||||
placeholder_origin,
|
||||
sub,
|
||||
sup,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ use super::glb::Glb;
|
|||
use super::lub::Lub;
|
||||
use super::type_relating::TypeRelating;
|
||||
use super::StructurallyRelateAliases;
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
|
||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace};
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::canonical::OriginalQueryValues;
|
||||
use rustc_middle::infer::unify_key::EffectVarValue;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
|
||||
|
|
@ -159,36 +159,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let a = self.shallow_resolve_const(a);
|
||||
let b = self.shallow_resolve_const(b);
|
||||
|
||||
// We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
|
||||
// correct type for the generic param they are an argument for. However there have been a number of cases
|
||||
// historically where asserting that the types are equal has found bugs in the compiler so this is valuable
|
||||
// to check even if it is a bit nasty impl wise :(
|
||||
//
|
||||
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
|
||||
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
|
||||
self.probe(|_| {
|
||||
if a.ty() == b.ty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
|
||||
// two const param's types are able to be equal has to go through a canonical query with the actual logic
|
||||
// in `rustc_trait_selection`.
|
||||
let canonical = self.canonicalize_query(
|
||||
relation.param_env().and((a.ty(), b.ty())),
|
||||
&mut OriginalQueryValues::default(),
|
||||
);
|
||||
self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
|
||||
// The error will only be reported later. If we emit an ErrorGuaranteed
|
||||
// here, then we will never get to the code that actually emits the error.
|
||||
self.tcx.dcx().delayed_bug(format!(
|
||||
"cannot relate consts of different types (a={a:?}, b={b:?})",
|
||||
));
|
||||
// We treat these constants as if they were of the same type, so that any
|
||||
// such constants being used in impls make these impls match barring other mismatches.
|
||||
// This helps with diagnostics down the road.
|
||||
});
|
||||
});
|
||||
// It is always an error if the types of two constants that are related are not equal.
|
||||
let InferOk { value: (), obligations } = self
|
||||
.at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env())
|
||||
.eq(DefineOpaqueTypes::No, a.ty(), b.ty())?;
|
||||
relation.register_obligations(obligations);
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(decl_macro)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(thread_spawn_unchecked)]
|
||||
#![feature(try_blocks)]
|
||||
|
|
|
|||
|
|
@ -799,10 +799,7 @@ fn test_unstable_options_tracking_hash() {
|
|||
tracked!(mir_opt_level, Some(4));
|
||||
tracked!(move_size_limit, Some(4096));
|
||||
tracked!(mutable_noalias, false);
|
||||
tracked!(
|
||||
next_solver,
|
||||
Some(NextSolverConfig { coherence: true, globally: false, dump_tree: Default::default() })
|
||||
);
|
||||
tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false }));
|
||||
tracked!(no_generate_arange_section, true);
|
||||
tracked!(no_jump_tables, true);
|
||||
tracked!(no_link, true);
|
||||
|
|
|
|||
|
|
@ -1950,14 +1950,22 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
|
|||
|
||||
impl ExplicitOutlivesRequirements {
|
||||
fn lifetimes_outliving_lifetime<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
|
||||
def_id: DefId,
|
||||
item: DefId,
|
||||
lifetime: DefId,
|
||||
) -> Vec<ty::Region<'tcx>> {
|
||||
let item_generics = tcx.generics_of(item);
|
||||
|
||||
inferred_outlives
|
||||
.iter()
|
||||
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
|
||||
ty::ReEarlyParam(ebr) if ebr.def_id == def_id => Some(b),
|
||||
ty::ReEarlyParam(ebr)
|
||||
if item_generics.region_param(ebr, tcx).def_id == lifetime =>
|
||||
{
|
||||
Some(b)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
|
@ -1986,9 +1994,12 @@ impl ExplicitOutlivesRequirements {
|
|||
bounds: &hir::GenericBounds<'_>,
|
||||
inferred_outlives: &[ty::Region<'tcx>],
|
||||
predicate_span: Span,
|
||||
item: DefId,
|
||||
) -> Vec<(usize, Span)> {
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
|
||||
let item_generics = tcx.generics_of(item);
|
||||
|
||||
bounds
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
|
@ -2000,7 +2011,7 @@ impl ExplicitOutlivesRequirements {
|
|||
let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
|
||||
Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
|
||||
.iter()
|
||||
.any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { ebr.def_id == def_id })),
|
||||
.any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id })),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
@ -2109,7 +2120,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
{
|
||||
(
|
||||
Self::lifetimes_outliving_lifetime(
|
||||
cx.tcx,
|
||||
inferred_outlives,
|
||||
item.owner_id.to_def_id(),
|
||||
region_def_id,
|
||||
),
|
||||
&predicate.bounds,
|
||||
|
|
@ -2152,6 +2165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
bounds,
|
||||
&relevant_lifetimes,
|
||||
predicate_span,
|
||||
item.owner_id.to_def_id(),
|
||||
);
|
||||
bound_count += bound_spans.len();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::{Diag, DiagMessage, LintDiagnostic, MultiSpan};
|
||||
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
|
||||
use rustc_feature::Features;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
|
|
@ -539,7 +539,9 @@ impl EarlyContext<'_> {
|
|||
span: MultiSpan,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
) {
|
||||
diagnostics::emit_buffered_lint(self, lint, span, diagnostic)
|
||||
self.opt_span_lint(lint, Some(span), |diag| {
|
||||
diagnostics::decorate_lint(self.sess(), diagnostic, diag);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -556,7 +558,6 @@ pub trait LintContext {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<S>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
);
|
||||
|
||||
|
|
@ -568,8 +569,8 @@ pub trait LintContext {
|
|||
span: S,
|
||||
decorator: impl for<'a> LintDiagnostic<'a, ()>,
|
||||
) {
|
||||
self.opt_span_lint(lint, Some(span), decorator.msg(), |diag| {
|
||||
decorator.decorate_lint(diag);
|
||||
self.opt_span_lint(lint, Some(span), |lint| {
|
||||
decorator.decorate_lint(lint);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -581,17 +582,16 @@ pub trait LintContext {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: S,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
self.opt_span_lint(lint, Some(span), msg, decorate);
|
||||
self.opt_span_lint(lint, Some(span), decorate);
|
||||
}
|
||||
|
||||
/// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
|
||||
/// generated by `#[derive(LintDiagnostic)]`).
|
||||
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> LintDiagnostic<'a, ()>) {
|
||||
self.opt_span_lint(lint, None as Option<Span>, decorator.msg(), |diag| {
|
||||
decorator.decorate_lint(diag);
|
||||
self.opt_span_lint(lint, None as Option<Span>, |lint| {
|
||||
decorator.decorate_lint(lint);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -599,13 +599,8 @@ pub trait LintContext {
|
|||
///
|
||||
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
|
||||
#[rustc_lint_diagnostics]
|
||||
fn lint(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
self.opt_span_lint(lint, None as Option<Span>, msg, decorate);
|
||||
fn lint(&self, lint: &'static Lint, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)) {
|
||||
self.opt_span_lint(lint, None as Option<Span>, decorate);
|
||||
}
|
||||
|
||||
/// This returns the lint level for the given lint at the current location.
|
||||
|
|
@ -668,14 +663,13 @@ impl<'tcx> LintContext for LateContext<'tcx> {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<S>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
let hir_id = self.last_node_with_lint_attrs;
|
||||
|
||||
match span {
|
||||
Some(s) => self.tcx.node_span_lint(lint, hir_id, s, msg, decorate),
|
||||
None => self.tcx.node_lint(lint, hir_id, msg, decorate),
|
||||
Some(s) => self.tcx.node_span_lint(lint, hir_id, s, decorate),
|
||||
None => self.tcx.node_lint(lint, hir_id, decorate),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -695,10 +689,9 @@ impl LintContext for EarlyContext<'_> {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<S>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
self.builder.opt_span_lint(lint, span.map(|s| s.into()), msg, decorate)
|
||||
self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate)
|
||||
}
|
||||
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> Level {
|
||||
|
|
|
|||
|
|
@ -4,24 +4,19 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{elided_lifetime_in_path_suggestion, DiagArgValue, MultiSpan};
|
||||
use rustc_errors::elided_lifetime_in_path_suggestion;
|
||||
use rustc_errors::{Applicability, Diag, DiagArgValue, LintDiagnostic};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_session::lint::{BuiltinLintDiag, Lint};
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::BytePos;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{lints, EarlyContext, LintContext as _};
|
||||
use crate::lints;
|
||||
|
||||
mod check_cfg;
|
||||
|
||||
pub(super) fn emit_buffered_lint(
|
||||
ctx: &EarlyContext<'_>,
|
||||
lint: &'static Lint,
|
||||
span: MultiSpan,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
) {
|
||||
let sess = ctx.sess();
|
||||
pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
|
||||
match diagnostic {
|
||||
BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => {
|
||||
let spans: Vec<_> = content
|
||||
|
|
@ -40,16 +35,14 @@ pub(super) fn emit_buffered_lint(
|
|||
let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion {
|
||||
spans: spans.iter().map(|(_c, span)| *span).collect(),
|
||||
});
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::UnicodeTextFlow {
|
||||
comment_span,
|
||||
characters,
|
||||
suggestions,
|
||||
num_codepoints: spans.len(),
|
||||
},
|
||||
)
|
||||
|
||||
lints::UnicodeTextFlow {
|
||||
comment_span,
|
||||
characters,
|
||||
suggestions,
|
||||
num_codepoints: spans.len(),
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AbsPathWithModule(mod_span) => {
|
||||
let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) {
|
||||
|
|
@ -62,48 +55,35 @@ pub(super) fn emit_buffered_lint(
|
|||
}
|
||||
Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
|
||||
};
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::AbsPathWithModule {
|
||||
sugg: lints::AbsPathWithModuleSugg {
|
||||
span: mod_span,
|
||||
applicability,
|
||||
replacement,
|
||||
},
|
||||
},
|
||||
);
|
||||
lints::AbsPathWithModule {
|
||||
sugg: lints::AbsPathWithModuleSugg { span: mod_span, applicability, replacement },
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => ctx
|
||||
.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident },
|
||||
),
|
||||
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => ctx
|
||||
.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
|
||||
),
|
||||
BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => {
|
||||
lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident }
|
||||
.decorate_lint(diag)
|
||||
}
|
||||
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
|
||||
lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def }
|
||||
.decorate_lint(diag)
|
||||
}
|
||||
|
||||
BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::ElidedLifetimesInPaths {
|
||||
subdiag: elided_lifetime_in_path_suggestion(
|
||||
sess.source_map(),
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
),
|
||||
},
|
||||
);
|
||||
lints::ElidedLifetimesInPaths {
|
||||
subdiag: elided_lifetime_in_path_suggestion(
|
||||
sess.source_map(),
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
),
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
|
||||
let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate });
|
||||
ctx.emit_span_lint(lint, span, lints::UnknownCrateTypes { sugg });
|
||||
lints::UnknownCrateTypes { sugg }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedImports {
|
||||
remove_whole_use,
|
||||
|
|
@ -120,18 +100,15 @@ pub(super) fn emit_buffered_lint(
|
|||
let test_module_span =
|
||||
test_module_span.map(|span| sess.source_map().guess_head_span(span));
|
||||
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::UnusedImports {
|
||||
sugg,
|
||||
test_module_span,
|
||||
num_snippets: span_snippets.len(),
|
||||
span_snippets: DiagArgValue::StrListSepByAnd(
|
||||
span_snippets.into_iter().map(Cow::Owned).collect(),
|
||||
),
|
||||
},
|
||||
);
|
||||
lints::UnusedImports {
|
||||
sugg,
|
||||
test_module_span,
|
||||
num_snippets: span_snippets.len(),
|
||||
span_snippets: DiagArgValue::StrListSepByAnd(
|
||||
span_snippets.into_iter().map(Cow::Owned).collect(),
|
||||
),
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::RedundantImport(spans, ident) => {
|
||||
let subs = spans
|
||||
|
|
@ -145,7 +122,7 @@ pub(super) fn emit_buffered_lint(
|
|||
})(span)
|
||||
})
|
||||
.collect();
|
||||
ctx.emit_span_lint(lint, span, lints::RedundantImport { subs, ident });
|
||||
lints::RedundantImport { subs, ident }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::DeprecatedMacro {
|
||||
suggestion,
|
||||
|
|
@ -159,90 +136,63 @@ pub(super) fn emit_buffered_lint(
|
|||
kind: "macro".to_owned(),
|
||||
suggestion,
|
||||
});
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind },
|
||||
);
|
||||
|
||||
stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedDocComment(attr_span) => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnusedDocComment { span: attr_span });
|
||||
lints::UnusedDocComment { span: attr_span }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
|
||||
let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
|
||||
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
if is_foreign {
|
||||
lints::PatternsInFnsWithoutBody::Foreign { sub }
|
||||
} else {
|
||||
lints::PatternsInFnsWithoutBody::Bodiless { sub }
|
||||
},
|
||||
);
|
||||
if is_foreign {
|
||||
lints::PatternsInFnsWithoutBody::Foreign { sub }
|
||||
} else {
|
||||
lints::PatternsInFnsWithoutBody::Bodiless { sub }
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MissingAbi(label_span, default_abi) => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::MissingAbi { span: label_span, default_abi: default_abi.name() },
|
||||
);
|
||||
lints::MissingAbi { span: label_span, default_abi: default_abi.name() }
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
|
||||
ctx.emit_span_lint(lint, span, lints::LegacyDeriveHelpers { span: label_span });
|
||||
lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::ProcMacroBackCompat { crate_name, fixed_version },
|
||||
);
|
||||
lints::ProcMacroBackCompat { crate_name, fixed_version }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::OrPatternsBackCompat { span: suggestion_span, suggestion },
|
||||
);
|
||||
lints::OrPatternsBackCompat { span: suggestion_span, suggestion }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::ReservedPrefix(label_span, prefix) => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::ReservedPrefix {
|
||||
label: label_span,
|
||||
suggestion: label_span.shrink_to_hi(),
|
||||
prefix,
|
||||
},
|
||||
);
|
||||
lints::ReservedPrefix {
|
||||
label: label_span,
|
||||
suggestion: label_span.shrink_to_hi(),
|
||||
prefix,
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name },
|
||||
);
|
||||
lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
|
||||
ctx.emit_span_lint(lint, span, lints::TrailingMacro { is_trailing, name });
|
||||
lints::TrailingMacro { is_trailing, name }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::BreakWithLabelAndLoop {
|
||||
sub: lints::BreakWithLabelAndLoopSub {
|
||||
left: sugg_span.shrink_to_lo(),
|
||||
right: sugg_span.shrink_to_hi(),
|
||||
},
|
||||
lints::BreakWithLabelAndLoop {
|
||||
sub: lints::BreakWithLabelAndLoopSub {
|
||||
left: sugg_span.shrink_to_lo(),
|
||||
right: sugg_span.shrink_to_hi(),
|
||||
},
|
||||
);
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgName(name, value) => {
|
||||
ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_name(sess, name, value));
|
||||
check_cfg::unexpected_cfg_name(sess, name, value).decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
|
||||
ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_value(sess, name, value));
|
||||
check_cfg::unexpected_cfg_value(sess, name, value).decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
|
||||
let suggestion = match sugg {
|
||||
|
|
@ -253,7 +203,7 @@ pub(super) fn emit_buffered_lint(
|
|||
},
|
||||
None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp },
|
||||
};
|
||||
ctx.emit_span_lint(lint, span, lints::DeprecatedWhereClauseLocation { suggestion });
|
||||
lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::SingleUseLifetime {
|
||||
param_span,
|
||||
|
|
@ -280,15 +230,12 @@ pub(super) fn emit_buffered_lint(
|
|||
None
|
||||
};
|
||||
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::SingleUseLifetime { suggestion, param_span, use_span, ident },
|
||||
);
|
||||
lints::SingleUseLifetime { suggestion, param_span, use_span, ident }
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
|
||||
debug!(?deletion_span);
|
||||
ctx.emit_span_lint(lint, span, lints::UnusedLifetime { deletion_span, ident });
|
||||
lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::NamedArgumentUsedPositionally {
|
||||
position_sp_to_replace,
|
||||
|
|
@ -316,35 +263,29 @@ pub(super) fn emit_buffered_lint(
|
|||
(None, String::new())
|
||||
};
|
||||
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::NamedArgumentUsedPositionally {
|
||||
named_arg_sp,
|
||||
position_label_sp: position_sp_for_msg,
|
||||
suggestion,
|
||||
name,
|
||||
named_arg_name,
|
||||
},
|
||||
)
|
||||
lints::NamedArgumentUsedPositionally {
|
||||
named_arg_sp,
|
||||
position_label_sp: position_sp_for_msg,
|
||||
suggestion,
|
||||
name,
|
||||
named_arg_name,
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
|
||||
ctx.emit_span_lint(lint, span, lints::ByteSliceInPackedStructWithDerive { ty })
|
||||
lints::ByteSliceInPackedStructWithDerive { ty }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedExternCrate { removal_span } => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnusedExternCrate { removal_span })
|
||||
lints::UnusedExternCrate { removal_span }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
|
||||
let suggestion_span = vis_span.between(ident_span);
|
||||
let code = if vis_span.is_empty() { "use " } else { " use " };
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::ExternCrateNotIdiomatic { span: suggestion_span, code },
|
||||
);
|
||||
|
||||
lints::ExternCrateNotIdiomatic { span: suggestion_span, code }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
|
||||
ctx.emit_span_lint(lint, span, lints::AmbiguousGlobImports { ambiguity });
|
||||
lints::AmbiguousGlobImports { ambiguity }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AmbiguousGlobReexports {
|
||||
name,
|
||||
|
|
@ -352,16 +293,13 @@ pub(super) fn emit_buffered_lint(
|
|||
first_reexport_span,
|
||||
duplicate_reexport_span,
|
||||
} => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::AmbiguousGlobReexports {
|
||||
first_reexport: first_reexport_span,
|
||||
duplicate_reexport: duplicate_reexport_span,
|
||||
name,
|
||||
namespace,
|
||||
},
|
||||
);
|
||||
lints::AmbiguousGlobReexports {
|
||||
first_reexport: first_reexport_span,
|
||||
duplicate_reexport: duplicate_reexport_span,
|
||||
name,
|
||||
namespace,
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::HiddenGlobReexports {
|
||||
name,
|
||||
|
|
@ -369,127 +307,112 @@ pub(super) fn emit_buffered_lint(
|
|||
glob_reexport_span,
|
||||
private_item_span,
|
||||
} => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::HiddenGlobReexports {
|
||||
glob_reexport: glob_reexport_span,
|
||||
private_item: private_item_span,
|
||||
lints::HiddenGlobReexports {
|
||||
glob_reexport: glob_reexport_span,
|
||||
private_item: private_item_span,
|
||||
|
||||
name,
|
||||
namespace,
|
||||
},
|
||||
);
|
||||
name,
|
||||
namespace,
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedQualifications { removal_span } => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnusedQualifications { removal_span });
|
||||
lints::UnusedQualifications { removal_span }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => {
|
||||
let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
|
||||
let code = if elided { "'static " } else { "'static" };
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::AssociatedConstElidedLifetime { span: lt_span, code, elided },
|
||||
);
|
||||
lints::AssociatedConstElidedLifetime { span: lt_span, code, elided }
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => {
|
||||
ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis },
|
||||
);
|
||||
lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis }
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnknownDiagnosticAttribute { span: typo_span, typo_name } => {
|
||||
let typo = typo_name.map(|typo_name| lints::UnknownDiagnosticAttributeTypoSugg {
|
||||
span: typo_span,
|
||||
typo_name,
|
||||
});
|
||||
ctx.emit_span_lint(lint, span, lints::UnknownDiagnosticAttribute { typo });
|
||||
lints::UnknownDiagnosticAttribute { typo }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MacroUseDeprecated => {
|
||||
ctx.emit_span_lint(lint, span, lints::MacroUseDeprecated)
|
||||
lints::MacroUseDeprecated.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedMacroUse => ctx.emit_span_lint(lint, span, lints::UnusedMacroUse),
|
||||
BuiltinLintDiag::UnusedMacroUse => lints::UnusedMacroUse.decorate_lint(diag),
|
||||
BuiltinLintDiag::PrivateExternCrateReexport(ident) => {
|
||||
ctx.emit_span_lint(lint, span, lints::PrivateExternCrateReexport { ident })
|
||||
lints::PrivateExternCrateReexport { ident }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedLabel => ctx.emit_span_lint(lint, span, lints::UnusedLabel),
|
||||
BuiltinLintDiag::UnusedLabel => lints::UnusedLabel.decorate_lint(diag),
|
||||
BuiltinLintDiag::MacroIsPrivate(ident) => {
|
||||
ctx.emit_span_lint(lint, span, lints::MacroIsPrivate { ident })
|
||||
lints::MacroIsPrivate { ident }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedMacroDefinition(name) => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnusedMacroDefinition { name })
|
||||
lints::UnusedMacroDefinition { name }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MacroRuleNeverUsed(n, name) => {
|
||||
ctx.emit_span_lint(lint, span, lints::MacroRuleNeverUsed { n: n + 1, name })
|
||||
lints::MacroRuleNeverUsed { n: n + 1, name }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnstableFeature(msg) => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnstableFeature { msg })
|
||||
lints::UnstableFeature { msg }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AvoidUsingIntelSyntax => {
|
||||
ctx.emit_span_lint(lint, span, lints::AvoidIntelSyntax)
|
||||
lints::AvoidIntelSyntax.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AvoidUsingAttSyntax => {
|
||||
ctx.emit_span_lint(lint, span, lints::AvoidAttSyntax)
|
||||
lints::AvoidAttSyntax.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::IncompleteInclude => {
|
||||
ctx.emit_span_lint(lint, span, lints::IncompleteInclude)
|
||||
lints::IncompleteInclude.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnnameableTestItems => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnnameableTestItems)
|
||||
lints::UnnameableTestItems.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::DuplicateMacroAttribute => {
|
||||
ctx.emit_span_lint(lint, span, lints::DuplicateMacroAttribute)
|
||||
lints::DuplicateMacroAttribute.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::CfgAttrNoAttributes => {
|
||||
ctx.emit_span_lint(lint, span, lints::CfgAttrNoAttributes)
|
||||
lints::CfgAttrNoAttributes.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::CrateTypeInCfgAttr => {
|
||||
ctx.emit_span_lint(lint, span, lints::CrateTypeInCfgAttr)
|
||||
lints::CrateTypeInCfgAttr.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::CrateNameInCfgAttr => {
|
||||
ctx.emit_span_lint(lint, span, lints::CrateNameInCfgAttr)
|
||||
lints::CrateNameInCfgAttr.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MissingFragmentSpecifier => {
|
||||
ctx.emit_span_lint(lint, span, lints::MissingFragmentSpecifier)
|
||||
lints::MissingFragmentSpecifier.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MetaVariableStillRepeating(name) => {
|
||||
ctx.emit_span_lint(lint, span, lints::MetaVariableStillRepeating { name })
|
||||
lints::MetaVariableStillRepeating { name }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MetaVariableWrongOperator => {
|
||||
ctx.emit_span_lint(lint, span, lints::MetaVariableWrongOperator)
|
||||
lints::MetaVariableWrongOperator.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::DuplicateMatcherBinding => {
|
||||
ctx.emit_span_lint(lint, span, lints::DuplicateMatcherBinding)
|
||||
lints::DuplicateMatcherBinding.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnknownMacroVariable(name) => {
|
||||
ctx.emit_span_lint(lint, span, lints::UnknownMacroVariable { name })
|
||||
lints::UnknownMacroVariable { name }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
lints::UnusedCrateDependency { extern_crate, local_crate },
|
||||
),
|
||||
BuiltinLintDiag::WasmCAbi => ctx.emit_span_lint(lint, span, lints::WasmCAbi),
|
||||
BuiltinLintDiag::IllFormedAttributeInput { suggestions } => ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
|
||||
lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
|
||||
}
|
||||
BuiltinLintDiag::WasmCAbi => lints::WasmCAbi.decorate_lint(diag),
|
||||
BuiltinLintDiag::IllFormedAttributeInput { suggestions } => {
|
||||
lints::IllFormedAttributeInput {
|
||||
num_suggestions: suggestions.len(),
|
||||
suggestions: DiagArgValue::StrListSepByAnd(
|
||||
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
|
||||
),
|
||||
},
|
||||
),
|
||||
BuiltinLintDiag::InnerAttributeUnstable { is_macro } => ctx.emit_span_lint(
|
||||
lint,
|
||||
span,
|
||||
if is_macro {
|
||||
lints::InnerAttributeUnstable::InnerMacroAttribute
|
||||
} else {
|
||||
lints::InnerAttributeUnstable::CustomInnerAttribute
|
||||
},
|
||||
),
|
||||
}
|
||||
.decorate_lint(diag)
|
||||
}
|
||||
BuiltinLintDiag::InnerAttributeUnstable { is_macro } => if is_macro {
|
||||
lints::InnerAttributeUnstable::InnerMacroAttribute
|
||||
} else {
|
||||
lints::InnerAttributeUnstable::CustomInnerAttribute
|
||||
}
|
||||
.decorate_lint(diag),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_macros::LintDiagnostic;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
|
||||
|
|
@ -303,20 +303,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
|
|||
ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id),
|
||||
) => {
|
||||
if self.tcx.def_kind(self.tcx.parent(def_id)) == DefKind::OpaqueTy {
|
||||
let (ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
|
||||
| ty::ReLateParam(ty::LateParamRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
})) = self
|
||||
let def_id = self
|
||||
.tcx
|
||||
.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
|
||||
.kind()
|
||||
else {
|
||||
span_bug!(
|
||||
self.tcx.def_span(def_id),
|
||||
"variable should have been duplicated from a parent"
|
||||
);
|
||||
};
|
||||
.opt_param_def_id(self.tcx, self.parent_def_id.to_def_id())
|
||||
.expect("variable should have been duplicated from parent");
|
||||
|
||||
explicitly_captured.insert(def_id);
|
||||
} else {
|
||||
explicitly_captured.insert(def_id);
|
||||
|
|
@ -369,6 +361,7 @@ struct ImplTraitOvercapturesLint<'tcx> {
|
|||
|
||||
impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_impl_trait_overcaptures);
|
||||
diag.arg("self_ty", self.self_ty.to_string())
|
||||
.arg("num_captured", self.num_captured)
|
||||
.span_note(self.uncaptured_spans, fluent::lint_note)
|
||||
|
|
@ -382,10 +375,6 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagMessage {
|
||||
fluent::lint_impl_trait_overcaptures
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::{Diag, DiagMessage, LintDiagnostic, MultiSpan};
|
||||
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
|
||||
use rustc_feature::{Features, GateIssue};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
|
|
@ -1064,26 +1064,19 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
lint_level(
|
||||
self.sess,
|
||||
lint,
|
||||
level,
|
||||
src,
|
||||
Some(span.into()),
|
||||
fluent::lint_unknown_gated_lint,
|
||||
|lint| {
|
||||
lint.arg("name", lint_id.lint.name_lower());
|
||||
lint.note(fluent::lint_note);
|
||||
rustc_session::parse::add_feature_diagnostics_for_issue(
|
||||
lint,
|
||||
&self.sess,
|
||||
feature,
|
||||
GateIssue::Language,
|
||||
lint_from_cli,
|
||||
None,
|
||||
);
|
||||
},
|
||||
);
|
||||
lint_level(self.sess, lint, level, src, Some(span.into()), |lint| {
|
||||
lint.primary_message(fluent::lint_unknown_gated_lint);
|
||||
lint.arg("name", lint_id.lint.name_lower());
|
||||
lint.note(fluent::lint_note);
|
||||
rustc_session::parse::add_feature_diagnostics_for_issue(
|
||||
lint,
|
||||
&self.sess,
|
||||
feature,
|
||||
GateIssue::Language,
|
||||
lint_from_cli,
|
||||
None,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
false
|
||||
|
|
@ -1104,11 +1097,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
let (level, src) = self.lint_level(lint);
|
||||
lint_level(self.sess, lint, level, src, span, msg, decorate)
|
||||
lint_level(self.sess, lint, level, src, span, decorate)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
@ -1119,7 +1111,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
decorate: impl for<'a> LintDiagnostic<'a, ()>,
|
||||
) {
|
||||
let (level, src) = self.lint_level(lint);
|
||||
lint_level(self.sess, lint, level, src, Some(span), decorate.msg(), |lint| {
|
||||
lint_level(self.sess, lint, level, src, Some(span), |lint| {
|
||||
decorate.decorate_lint(lint);
|
||||
});
|
||||
}
|
||||
|
|
@ -1127,7 +1119,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
|||
#[track_caller]
|
||||
pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) {
|
||||
let (level, src) = self.lint_level(lint);
|
||||
lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
|
||||
lint_level(self.sess, lint, level, src, None, |lint| {
|
||||
decorate.decorate_lint(lint);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -539,6 +539,16 @@ fn register_builtins(store: &mut LintStore) {
|
|||
"converted into hard error, see RFC #3535 \
|
||||
<https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
|
||||
);
|
||||
store.register_removed(
|
||||
"indirect_structural_match",
|
||||
"converted into hard error, see RFC #3535 \
|
||||
<https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
|
||||
);
|
||||
store.register_removed(
|
||||
"pointer_structural_match",
|
||||
"converted into hard error, see RFC #3535 \
|
||||
<https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
|
||||
);
|
||||
}
|
||||
|
||||
fn register_internals(store: &mut LintStore) {
|
||||
|
|
|
|||
|
|
@ -145,12 +145,9 @@ pub struct BuiltinMissingDebugImpl<'a> {
|
|||
// Needed for def_path_str
|
||||
impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_builtin_missing_debug_impl);
|
||||
diag.arg("debug", self.tcx.def_path_str(self.def_id));
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_builtin_missing_debug_impl
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -250,6 +247,7 @@ pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
|
|||
|
||||
impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_ungated_async_fn_track_caller);
|
||||
diag.span_label(self.label, fluent::lint_label);
|
||||
rustc_session::parse::add_feature_diagnostics(
|
||||
diag,
|
||||
|
|
@ -257,10 +255,6 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
|
|||
sym::async_fn_track_caller,
|
||||
);
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_ungated_async_fn_track_caller
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -432,6 +426,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> {
|
|||
|
||||
impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(self.msg);
|
||||
diag.arg("ty", self.ty);
|
||||
diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
|
||||
if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
|
||||
|
|
@ -443,10 +438,6 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
|
|||
}
|
||||
self.sub.add_to_diag(diag);
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
self.msg.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(davidtwco): make translatable
|
||||
|
|
@ -1169,6 +1160,7 @@ pub struct NonFmtPanicUnused {
|
|||
// Used because of two suggestions based on one Option<Span>
|
||||
impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_non_fmt_panic_unused);
|
||||
diag.arg("count", self.count);
|
||||
diag.note(fluent::lint_note);
|
||||
if let Some(span) = self.suggestion {
|
||||
|
|
@ -1186,10 +1178,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_non_fmt_panic_unused
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -1411,13 +1399,10 @@ pub struct DropTraitConstraintsDiag<'a> {
|
|||
// Needed for def_path_str
|
||||
impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_drop_trait_constraints);
|
||||
diag.arg("predicate", self.predicate);
|
||||
diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_drop_trait_constraints
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DropGlue<'a> {
|
||||
|
|
@ -1428,12 +1413,9 @@ pub struct DropGlue<'a> {
|
|||
// Needed for def_path_str
|
||||
impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_drop_glue);
|
||||
diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_drop_glue
|
||||
}
|
||||
}
|
||||
|
||||
// types.rs
|
||||
|
|
@ -1711,6 +1693,7 @@ pub struct ImproperCTypes<'a> {
|
|||
// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
|
||||
impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_improper_ctypes);
|
||||
diag.arg("ty", self.ty);
|
||||
diag.arg("desc", self.desc);
|
||||
diag.span_label(self.label, fluent::lint_label);
|
||||
|
|
@ -1722,10 +1705,6 @@ impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
|
|||
diag.span_note(note, fluent::lint_note);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_improper_ctypes
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -1854,6 +1833,7 @@ pub enum UnusedDefSuggestion {
|
|||
// Needed because of def_path_str
|
||||
impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_unused_def);
|
||||
diag.arg("pre", self.pre);
|
||||
diag.arg("post", self.post);
|
||||
diag.arg("def", self.cx.tcx.def_path_str(self.def_id));
|
||||
|
|
@ -1865,10 +1845,6 @@ impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
|
|||
diag.subdiagnostic(diag.dcx, sugg);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_unused_def
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -1937,15 +1913,12 @@ pub struct AsyncFnInTraitDiag {
|
|||
|
||||
impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::lint_async_fn_in_trait);
|
||||
diag.note(fluent::lint_note);
|
||||
if let Some(sugg) = self.sugg {
|
||||
diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
fluent::lint_async_fn_in_trait
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -2273,10 +2246,8 @@ pub struct UnstableFeature {
|
|||
}
|
||||
|
||||
impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
|
||||
fn decorate_lint<'b>(self, _diag: &'b mut Diag<'a, ()>) {}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
self.msg.clone()
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
diag.primary_message(self.msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2738,12 +2709,9 @@ pub struct AmbiguousGlobImports {
|
|||
|
||||
impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
|
||||
diag.primary_message(self.ambiguity.msg.clone());
|
||||
rustc_errors::report_ambiguity_error(diag, self.ambiguity);
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
DiagMessage::Str(self.ambiguity.msg.clone().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
cx.span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
|
||||
cx.span_lint(NON_FMT_PANICS, arg_span, |lint| {
|
||||
lint.primary_message(fluent::lint_non_fmt_panic);
|
||||
lint.arg("name", symbol);
|
||||
lint.note(fluent::lint_note);
|
||||
lint.note(fluent::lint_more_info_note);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ declare_lint_pass! {
|
|||
HIDDEN_GLOB_REEXPORTS,
|
||||
ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
INCOMPLETE_INCLUDE,
|
||||
INDIRECT_STRUCTURAL_MATCH,
|
||||
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
||||
INLINE_NO_SANITIZE,
|
||||
INVALID_DOC_ATTRIBUTES,
|
||||
|
|
@ -74,7 +73,6 @@ declare_lint_pass! {
|
|||
ORDER_DEPENDENT_TRAIT_OBJECTS,
|
||||
OVERLAPPING_RANGE_ENDPOINTS,
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
POINTER_STRUCTURAL_MATCH,
|
||||
PRIVATE_BOUNDS,
|
||||
PRIVATE_INTERFACES,
|
||||
PROC_MACRO_BACK_COMPAT,
|
||||
|
|
@ -1316,10 +1314,8 @@ declare_lint! {
|
|||
/// * If you are trying to perform a one-time initialization of a global:
|
||||
/// * If the value can be computed at compile-time, consider using
|
||||
/// const-compatible values (see [Constant Evaluation]).
|
||||
/// * For more complex single-initialization cases, consider using a
|
||||
/// third-party crate, such as [`lazy_static`] or [`once_cell`].
|
||||
/// * If you are using the [nightly channel], consider the new
|
||||
/// [`lazy`] module in the standard library.
|
||||
/// * For more complex single-initialization cases, consider using
|
||||
/// [`std::sync::LazyLock`].
|
||||
/// * If you truly need a mutable global, consider using a [`static`],
|
||||
/// which has a variety of options:
|
||||
/// * Simple data types can be directly defined and mutated with an
|
||||
|
|
@ -1334,9 +1330,7 @@ declare_lint! {
|
|||
/// [Constant Evaluation]: https://doc.rust-lang.org/reference/const_eval.html
|
||||
/// [`static`]: https://doc.rust-lang.org/reference/items/static-items.html
|
||||
/// [mutable `static`]: https://doc.rust-lang.org/reference/items/static-items.html#mutable-statics
|
||||
/// [`lazy`]: https://doc.rust-lang.org/nightly/std/lazy/index.html
|
||||
/// [`lazy_static`]: https://crates.io/crates/lazy_static
|
||||
/// [`once_cell`]: https://crates.io/crates/once_cell
|
||||
/// [`std::sync::LazyLock`]: https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html
|
||||
/// [`atomic`]: https://doc.rust-lang.org/std/sync/atomic/index.html
|
||||
/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
|
||||
pub CONST_ITEM_MUTATION,
|
||||
|
|
@ -2355,52 +2349,6 @@ declare_lint! {
|
|||
"outlives requirements can be inferred"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `indirect_structural_match` lint detects a `const` in a pattern
|
||||
/// that manually implements [`PartialEq`] and [`Eq`].
|
||||
///
|
||||
/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
|
||||
/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(indirect_structural_match)]
|
||||
///
|
||||
/// struct NoDerive(i32);
|
||||
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
||||
/// impl Eq for NoDerive { }
|
||||
/// #[derive(PartialEq, Eq)]
|
||||
/// struct WrapParam<T>(T);
|
||||
/// const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
|
||||
/// fn main() {
|
||||
/// match WRAP_INDIRECT_PARAM {
|
||||
/// WRAP_INDIRECT_PARAM => { }
|
||||
/// _ => { }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The compiler unintentionally accepted this form in the past. This is a
|
||||
/// [future-incompatible] lint to transition this to a hard error in the
|
||||
/// future. See [issue #62411] for a complete description of the problem,
|
||||
/// and some possible solutions.
|
||||
///
|
||||
/// [issue #62411]: https://github.com/rust-lang/rust/issues/62411
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub INDIRECT_STRUCTURAL_MATCH,
|
||||
Warn,
|
||||
"constant used in pattern contains value of non-structural-match type in a field or a variant",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
||||
reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `deprecated_in_future` lint is internal to rustc and should not be
|
||||
/// used by user code.
|
||||
|
|
@ -2418,45 +2366,6 @@ declare_lint! {
|
|||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `pointer_structural_match` lint detects pointers used in patterns whose behaviour
|
||||
/// cannot be relied upon across compiler versions and optimization levels.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(pointer_structural_match)]
|
||||
/// fn foo(a: usize, b: usize) -> usize { a + b }
|
||||
/// const FOO: fn(usize, usize) -> usize = foo;
|
||||
/// fn main() {
|
||||
/// match FOO {
|
||||
/// FOO => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Previous versions of Rust allowed function pointers and all raw pointers in patterns.
|
||||
/// While these work in many cases as expected by users, it is possible that due to
|
||||
/// optimizations pointers are "not equal to themselves" or pointers to different functions
|
||||
/// compare as equal during runtime. This is because LLVM optimizations can deduplicate
|
||||
/// functions if their bodies are the same, thus also making pointers to these functions point
|
||||
/// to the same location. Additionally functions may get duplicated if they are instantiated
|
||||
/// in different crates and not deduplicated again via LTO. Pointer identity for memory
|
||||
/// created by `const` is similarly unreliable.
|
||||
pub POINTER_STRUCTURAL_MATCH,
|
||||
Warn,
|
||||
"pointers are not structural-match",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
||||
reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ambiguous_associated_items` lint detects ambiguity between
|
||||
/// [associated items] and [enum variants].
|
||||
|
|
|
|||
|
|
@ -764,19 +764,7 @@ pub struct LintBuffer {
|
|||
|
||||
impl LintBuffer {
|
||||
pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
|
||||
let arr = self.map.entry(early_lint.node_id).or_default();
|
||||
arr.push(early_lint);
|
||||
}
|
||||
|
||||
pub fn add_lint(
|
||||
&mut self,
|
||||
lint: &'static Lint,
|
||||
node_id: NodeId,
|
||||
span: MultiSpan,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
) {
|
||||
let lint_id = LintId::of(lint);
|
||||
self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, diagnostic });
|
||||
self.map.entry(early_lint.node_id).or_default().push(early_lint);
|
||||
}
|
||||
|
||||
pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
|
||||
|
|
@ -787,11 +775,16 @@ impl LintBuffer {
|
|||
pub fn buffer_lint(
|
||||
&mut self,
|
||||
lint: &'static Lint,
|
||||
id: NodeId,
|
||||
sp: impl Into<MultiSpan>,
|
||||
node_id: NodeId,
|
||||
span: impl Into<MultiSpan>,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
) {
|
||||
self.add_lint(lint, id, sp.into(), diagnostic)
|
||||
self.add_early_lint(BufferedEarlyLint {
|
||||
lint_id: LintId::of(lint),
|
||||
node_id,
|
||||
span: span.into(),
|
||||
diagnostic,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,25 +105,12 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||
pub(crate) fn into_tokens(self) -> TokenStream {
|
||||
let LintDiagnosticDerive { mut structure } = self;
|
||||
let kind = DiagnosticDeriveKind::LintDiagnostic;
|
||||
let slugs = RefCell::new(Vec::new());
|
||||
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
|
||||
let preamble = builder.preamble(variant);
|
||||
let body = builder.body(variant);
|
||||
|
||||
let formatting_init = &builder.formatting_init;
|
||||
quote! {
|
||||
#preamble
|
||||
#formatting_init
|
||||
#body
|
||||
diag
|
||||
}
|
||||
});
|
||||
|
||||
let slugs = RefCell::new(Vec::new());
|
||||
let msg = kind.each_variant(&mut structure, |mut builder, variant| {
|
||||
// Collect the slug by generating the preamble.
|
||||
let _ = builder.preamble(variant);
|
||||
|
||||
match builder.slug.value_ref() {
|
||||
let primary_message = match builder.slug.value_ref() {
|
||||
None => {
|
||||
span_err(builder.span, "diagnostic slug not specified")
|
||||
.help(
|
||||
|
|
@ -146,9 +133,18 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||
Some(slug) => {
|
||||
slugs.borrow_mut().push(slug.clone());
|
||||
quote! {
|
||||
crate::fluent_generated::#slug.into()
|
||||
diag.primary_message(crate::fluent_generated::#slug);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let formatting_init = &builder.formatting_init;
|
||||
quote! {
|
||||
#primary_message
|
||||
#preamble
|
||||
#formatting_init
|
||||
#body
|
||||
diag
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -161,10 +157,6 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||
) {
|
||||
#implementation;
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagMessage {
|
||||
#msg
|
||||
}
|
||||
}
|
||||
});
|
||||
for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ pub fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
|
|||
/// Then, later, to emit the error:
|
||||
///
|
||||
/// ```ignore (rust)
|
||||
/// cx.span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
|
||||
/// cx.emit_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
|
||||
/// method,
|
||||
/// success_ordering,
|
||||
/// fail_ordering,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,10 @@ macro_rules! arena_types {
|
|||
[] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>,
|
||||
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
|
||||
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
|
||||
[] canonical_goal_evaluation: rustc_next_trait_solver::solve::inspect::GoalEvaluationStep<rustc_middle::ty::TyCtxt<'tcx>>,
|
||||
[] canonical_goal_evaluation:
|
||||
rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep<
|
||||
rustc_middle::ty::TyCtxt<'tcx>
|
||||
>,
|
||||
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
|
||||
[] type_op_subtype:
|
||||
rustc_middle::infer::canonical::Canonical<'tcx,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::cmp;
|
|||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_errors::{Diag, DiagMessage, MultiSpan};
|
||||
use rustc_errors::{Diag, MultiSpan};
|
||||
use rustc_hir::{HirId, ItemLocalId};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_session::lint::{
|
||||
|
|
@ -270,7 +270,6 @@ pub fn lint_level(
|
|||
level: Level,
|
||||
src: LintLevelSource,
|
||||
span: Option<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
||||
|
|
@ -282,7 +281,6 @@ pub fn lint_level(
|
|||
level: Level,
|
||||
src: LintLevelSource,
|
||||
span: Option<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: Box<dyn '_ + for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)>,
|
||||
) {
|
||||
// Check for future incompatibility lints and issue a stronger warning.
|
||||
|
|
@ -351,10 +349,6 @@ pub fn lint_level(
|
|||
}
|
||||
}
|
||||
|
||||
// Delay evaluating and setting the primary message until after we've
|
||||
// suppressed the lint due to macros.
|
||||
err.primary_message(msg);
|
||||
|
||||
err.is_lint(lint.name_lower(), has_future_breakage);
|
||||
|
||||
// Lint diagnostics that are covered by the expect level will not be emitted outside
|
||||
|
|
@ -419,7 +413,7 @@ pub fn lint_level(
|
|||
explain_lint_level_source(lint, level, src, &mut err);
|
||||
err.emit()
|
||||
}
|
||||
lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
|
||||
lint_level_impl(sess, lint, level, src, span, Box::new(decorate))
|
||||
}
|
||||
|
||||
/// Returns whether `span` originates in a foreign crate's external macro.
|
||||
|
|
|
|||
|
|
@ -157,6 +157,13 @@ pub struct Deprecated {
|
|||
|
||||
impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
|
||||
diag.primary_message(match &self.since_kind {
|
||||
DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated,
|
||||
DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future,
|
||||
DeprecatedSinceKind::InVersion(_) => {
|
||||
crate::fluent_generated::middle_deprecated_in_version
|
||||
}
|
||||
});
|
||||
diag.arg("kind", self.kind);
|
||||
diag.arg("path", self.path);
|
||||
if let DeprecatedSinceKind::InVersion(version) = self.since_kind {
|
||||
|
|
@ -172,16 +179,6 @@ impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecate
|
|||
diag.subdiagnostic(diag.dcx, sub);
|
||||
}
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagMessage {
|
||||
match &self.since_kind {
|
||||
DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated,
|
||||
DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future,
|
||||
DeprecatedSinceKind::InVersion(_) => {
|
||||
crate::fluent_generated::middle_deprecated_in_version
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deprecated_since_kind(is_in_effect: bool, since: DeprecatedSince) -> DeprecatedSinceKind {
|
||||
|
|
@ -598,7 +595,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
unmarked: impl FnOnce(Span, DefId),
|
||||
) -> bool {
|
||||
let soft_handler = |lint, span, msg: String| {
|
||||
self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |_| {})
|
||||
self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
|
||||
lint.primary_message(msg);
|
||||
})
|
||||
};
|
||||
let eval_result =
|
||||
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
|
||||
|
|
|
|||
|
|
@ -113,8 +113,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
||||
self.local_def_id_to_hir_id(local_def_id),
|
||||
self.def_span(ct.def),
|
||||
"cannot use constants which depend on generic parameters in types",
|
||||
|_| {},
|
||||
|lint| { lint.primary_message("cannot use constants which depend on generic parameters in types"); },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2218,15 +2218,6 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
|
||||
/// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if
|
||||
/// the types might be equal.
|
||||
query check_tys_might_be_eq(
|
||||
arg: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>
|
||||
) -> Result<(), NoSolution> {
|
||||
desc { "check whether two const param are definitely not equal to eachother"}
|
||||
}
|
||||
|
||||
/// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
|
||||
/// Should not be called for the local crate before the resolver outputs are created, as it
|
||||
/// is only fed there.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub struct EvaluationCache<'tcx> {
|
|||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct CacheData<'tcx> {
|
||||
pub result: QueryResult<'tcx>,
|
||||
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
|
||||
pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>,
|
||||
pub additional_depth: usize,
|
||||
pub encountered_overflow: bool,
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ impl<'tcx> EvaluationCache<'tcx> {
|
|||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: CanonicalInput<'tcx>,
|
||||
proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
|
||||
proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>,
|
||||
additional_depth: usize,
|
||||
encountered_overflow: bool,
|
||||
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
|
||||
|
|
@ -107,7 +107,7 @@ struct Success<'tcx> {
|
|||
#[derive(Clone, Copy)]
|
||||
pub struct QueryData<'tcx> {
|
||||
pub result: QueryResult<'tcx>,
|
||||
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
|
||||
pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>,
|
||||
}
|
||||
|
||||
/// The cache entry for a goal `CanonicalInput`.
|
||||
|
|
|
|||
|
|
@ -47,9 +47,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, RwLock, Work
|
|||
#[cfg(parallel_compiler)]
|
||||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
||||
};
|
||||
use rustc_errors::{Applicability, Diag, DiagCtxt, ErrorGuaranteed, LintDiagnostic, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
|
|
@ -103,7 +101,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
type PredefinedOpaques = solve::PredefinedOpaques<'tcx>;
|
||||
type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
|
||||
type ExternalConstraints = ExternalConstraints<'tcx>;
|
||||
type GoalEvaluationSteps = &'tcx [solve::inspect::GoalEvaluationStep<TyCtxt<'tcx>>];
|
||||
type CanonicalGoalEvaluationStepRef =
|
||||
&'tcx solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>;
|
||||
|
||||
type Ty = Ty<'tcx>;
|
||||
type Tys = &'tcx List<Ty<'tcx>>;
|
||||
|
|
@ -1488,13 +1487,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
/// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
|
||||
pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> {
|
||||
pub fn is_suitable_region(
|
||||
self,
|
||||
generic_param_scope: LocalDefId,
|
||||
mut region: Region<'tcx>,
|
||||
) -> Option<FreeRegionInfo> {
|
||||
let (suitable_region_binding_scope, bound_region) = loop {
|
||||
let def_id = match region.kind() {
|
||||
ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?,
|
||||
ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?,
|
||||
_ => return None, // not a free region
|
||||
};
|
||||
let def_id =
|
||||
region.opt_param_def_id(self, generic_param_scope.to_def_id())?.as_local()?;
|
||||
let scope = self.local_parent(def_id);
|
||||
if self.def_kind(scope) == DefKind::OpaqueTy {
|
||||
// Lifetime params of opaque types are synthetic and thus irrelevant to
|
||||
|
|
@ -2469,10 +2469,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
span: impl Into<MultiSpan>,
|
||||
decorator: impl for<'a> LintDiagnostic<'a, ()>,
|
||||
) {
|
||||
let msg = decorator.msg();
|
||||
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
||||
lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
|
||||
decorator.decorate_lint(diag);
|
||||
lint_level(self.sess, lint, level, src, Some(span.into()), |lint| {
|
||||
decorator.decorate_lint(lint);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2486,11 +2485,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
lint: &'static Lint,
|
||||
hir_id: HirId,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
||||
lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
|
||||
lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
|
||||
}
|
||||
|
||||
/// Find the crate root and the appropriate span where `use` and outer attributes can be
|
||||
|
|
@ -2541,8 +2539,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
id: HirId,
|
||||
decorator: impl for<'a> LintDiagnostic<'a, ()>,
|
||||
) {
|
||||
self.node_lint(lint, id, decorator.msg(), |diag| {
|
||||
decorator.decorate_lint(diag);
|
||||
self.node_lint(lint, id, |lint| {
|
||||
decorator.decorate_lint(lint);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2555,11 +2553,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self,
|
||||
lint: &'static Lint,
|
||||
id: HirId,
|
||||
msg: impl Into<DiagMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
|
||||
) {
|
||||
let (level, src) = self.lint_level_at_node(lint, id);
|
||||
lint_level(self.sess, lint, level, src, None, msg, decorate);
|
||||
lint_level(self.sess, lint, level, src, None, decorate);
|
||||
}
|
||||
|
||||
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
|
||||
|
|
@ -2633,7 +2630,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
return ty::Region::new_early_param(
|
||||
self,
|
||||
ty::EarlyParamRegion {
|
||||
def_id: ebv,
|
||||
index: generics
|
||||
.param_def_id_to_index(self, ebv)
|
||||
.expect("early-bound var should be present in fn generics"),
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ pub struct GenericParamDef {
|
|||
impl GenericParamDef {
|
||||
pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion {
|
||||
if let GenericParamDefKind::Lifetime = self.kind {
|
||||
ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name }
|
||||
ty::EarlyParamRegion { index: self.index, name: self.name }
|
||||
} else {
|
||||
bug!("cannot convert a non-lifetime parameter def to an early bound region")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3314,7 +3314,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
|
|||
///
|
||||
/// The implementation uses similar import discovery logic to that of 'use' suggestions.
|
||||
///
|
||||
/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
|
||||
/// See also [`with_no_trimmed_paths!`].
|
||||
// this is pub to be able to intra-doc-link it
|
||||
pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
|
||||
// Trimming paths is expensive and not optimized, since we expect it to only be used for error
|
||||
|
|
|
|||
|
|
@ -265,33 +265,6 @@ impl<'tcx> Region<'tcx> {
|
|||
flags
|
||||
}
|
||||
|
||||
/// Given an early-bound or free region, returns the `DefId` where it was bound.
|
||||
/// For example, consider the regions in this snippet of code:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a> Foo {
|
||||
/// // ^^ -- early bound, declared on an impl
|
||||
///
|
||||
/// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c
|
||||
/// // ^^ ^^ ^ anonymous, late-bound
|
||||
/// // | early-bound, appears in where-clauses
|
||||
/// // late-bound, appears only in fn args
|
||||
/// {..}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Here, `free_region_binding_scope('a)` would return the `DefId`
|
||||
/// of the impl, and for all the other highlighted regions, it
|
||||
/// would return the `DefId` of the function. In other cases (not shown), this
|
||||
/// function might return the `DefId` of a closure.
|
||||
pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId {
|
||||
match *self {
|
||||
ty::ReEarlyParam(br) => tcx.parent(br.def_id),
|
||||
ty::ReLateParam(fr) => fr.scope,
|
||||
_ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
/// True for free regions other than `'static`.
|
||||
pub fn is_param(self) -> bool {
|
||||
matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_))
|
||||
|
|
@ -321,6 +294,21 @@ impl<'tcx> Region<'tcx> {
|
|||
_ => bug!("expected region {:?} to be of kind ReVar", self),
|
||||
}
|
||||
}
|
||||
|
||||
/// Given some item `binding_item`, check if this region is a generic parameter introduced by it
|
||||
/// or one of the parent generics. Returns the `DefId` of the parameter definition if so.
|
||||
pub fn opt_param_def_id(self, tcx: TyCtxt<'tcx>, binding_item: DefId) -> Option<DefId> {
|
||||
match self.kind() {
|
||||
ty::ReEarlyParam(ebr) => {
|
||||
Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id)
|
||||
}
|
||||
ty::ReLateParam(ty::LateParamRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
}) => Some(def_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Deref for Region<'tcx> {
|
||||
|
|
@ -335,16 +323,13 @@ impl<'tcx> Deref for Region<'tcx> {
|
|||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub struct EarlyParamRegion {
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for EarlyParamRegion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// FIXME(BoxyUwU): self.def_id goes first because of `erased-regions-in-hidden-ty.rs` being impossible to write
|
||||
// error annotations for otherwise. :). Ideally this would be `self.name, self.index, self.def_id`.
|
||||
write!(f, "{:?}_{}/#{}", self.def_id, self.name, self.index)
|
||||
write!(f, "{}/#{}", self.name, self.index)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -352,6 +337,12 @@ impl std::fmt::Debug for EarlyParamRegion {
|
|||
#[derive(HashStable)]
|
||||
/// The parameter representation of late-bound function parameters, "some region
|
||||
/// at least as big as the scope `fr.scope`".
|
||||
///
|
||||
/// Similar to a placeholder region as we create `LateParam` regions when entering a binder
|
||||
/// except they are always in the root universe and instead of using a boundvar to distinguish
|
||||
/// between others we use the `DefId` of the parameter. For this reason the `bound_region` field
|
||||
/// should basically always be `BoundRegionKind::BrNamed` as otherwise there is no way of telling
|
||||
/// different parameters apart.
|
||||
pub struct LateParamRegion {
|
||||
pub scope: DefId,
|
||||
pub bound_region: BoundRegionKind,
|
||||
|
|
|
|||
|
|
@ -109,9 +109,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
|
|||
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||
.label = use of extern static
|
||||
|
||||
mir_build_indirect_structural_match =
|
||||
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
|
||||
|
||||
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
|
||||
mir_build_initializing_type_with_requires_unsafe =
|
||||
|
|
@ -257,9 +254,6 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type
|
|||
mir_build_non_partial_eq_match =
|
||||
to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq`
|
||||
|
||||
mir_build_nontrivial_structural_match =
|
||||
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
|
||||
|
||||
mir_build_pattern_not_covered = refutable pattern in {$origin}
|
||||
.pattern_ty = the matched value is of type `{$pattern_ty}`
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use crate::build::expr::category::Category;
|
|||
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::place::Projection as HirProjection;
|
||||
use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
|
||||
use rustc_middle::middle::region;
|
||||
|
|
@ -13,6 +12,7 @@ use rustc_middle::mir::*;
|
|||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::AdtDef;
|
||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
|
@ -252,7 +252,18 @@ fn strip_prefix<'a, 'tcx>(
|
|||
|
||||
impl<'tcx> PlaceBuilder<'tcx> {
|
||||
pub(in crate::build) fn to_place(&self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
|
||||
self.try_to_place(cx).unwrap()
|
||||
self.try_to_place(cx).unwrap_or_else(|| match self.base {
|
||||
PlaceBase::Local(local) => span_bug!(
|
||||
cx.local_decls[local].source_info.span,
|
||||
"could not resolve local: {local:#?} + {:?}",
|
||||
self.projection
|
||||
),
|
||||
PlaceBase::Upvar { var_hir_id, closure_def_id: _ } => span_bug!(
|
||||
cx.tcx.hir().span(var_hir_id.0),
|
||||
"could not resolve upvar: {var_hir_id:?} + {:?}",
|
||||
self.projection
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a `Place` or returns `None` if an upvar cannot be resolved
|
||||
|
|
|
|||
|
|
@ -794,9 +794,12 @@ pub struct NaNPattern {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_pointer_pattern)]
|
||||
pub struct PointerPattern;
|
||||
pub struct PointerPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_non_empty_never_pattern)]
|
||||
|
|
@ -808,22 +811,6 @@ pub struct NonEmptyNeverPattern<'tcx> {
|
|||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_indirect_structural_match)]
|
||||
#[note(mir_build_type_not_structural_tip)]
|
||||
#[note(mir_build_type_not_structural_more_info)]
|
||||
pub struct IndirectStructuralMatch<'tcx> {
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_nontrivial_structural_match)]
|
||||
#[note(mir_build_type_not_structural_tip)]
|
||||
#[note(mir_build_type_not_structural_more_info)]
|
||||
pub struct NontrivialStructuralMatch<'tcx> {
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_exceeds_mcdc_condition_num_limit)]
|
||||
pub(crate) struct MCDCExceedsConditionNumLimit {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use rustc_middle::mir;
|
|||
use rustc_middle::span_bug;
|
||||
use rustc_middle::thir::{FieldPat, Pat, PatKind};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, ValTree};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
|
|
@ -18,8 +17,8 @@ use std::cell::Cell;
|
|||
|
||||
use super::PatCtxt;
|
||||
use crate::errors::{
|
||||
IndirectStructuralMatch, InvalidPattern, NaNPattern, PointerPattern, TypeNotPartialEq,
|
||||
TypeNotStructural, UnionPattern, UnsizedPattern,
|
||||
InvalidPattern, NaNPattern, PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern,
|
||||
UnsizedPattern,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
|
|
@ -51,15 +50,6 @@ struct ConstToPat<'tcx> {
|
|||
// value.
|
||||
saw_const_match_error: Cell<Option<ErrorGuaranteed>>,
|
||||
|
||||
// This tracks if we emitted some diagnostic for a given const value, so that
|
||||
// we will not subsequently issue an irrelevant lint for the same const
|
||||
// value.
|
||||
saw_const_match_lint: Cell<bool>,
|
||||
|
||||
// For backcompat we need to keep allowing non-structurally-eq types behind references.
|
||||
// See also all the `cant-hide-behind` tests.
|
||||
behind_reference: Cell<bool>,
|
||||
|
||||
// inference context used for checking `T: Structural` bounds.
|
||||
infcx: InferCtxt<'tcx>,
|
||||
|
||||
|
|
@ -86,8 +76,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
infcx,
|
||||
param_env: pat_ctxt.param_env,
|
||||
saw_const_match_error: Cell::new(None),
|
||||
saw_const_match_lint: Cell::new(false),
|
||||
behind_reference: Cell::new(false),
|
||||
treat_byte_string_as_slice: pat_ctxt
|
||||
.typeck_results
|
||||
.treat_byte_string_as_slice
|
||||
|
|
@ -199,15 +187,12 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// complained about structural match violations there, so we don't
|
||||
// have to check anything any more.
|
||||
}
|
||||
} else if !have_valtree && !self.saw_const_match_lint.get() {
|
||||
} else if !have_valtree {
|
||||
// The only way valtree construction can fail without the structural match
|
||||
// checker finding a violation is if there is a pointer somewhere.
|
||||
self.tcx().emit_node_span_lint(
|
||||
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
self.span,
|
||||
PointerPattern,
|
||||
);
|
||||
let e = self.tcx().dcx().emit_err(PointerPattern { span: self.span });
|
||||
let kind = PatKind::Error(e);
|
||||
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
|
||||
}
|
||||
|
||||
// Always check for `PartialEq` if we had no other errors yet.
|
||||
|
|
@ -276,36 +261,11 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
cv: ValTree<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> {
|
||||
let id = self.id;
|
||||
let span = self.span;
|
||||
let tcx = self.tcx();
|
||||
let param_env = self.param_env;
|
||||
|
||||
let kind = match ty.kind() {
|
||||
// If the type is not structurally comparable, just emit the constant directly,
|
||||
// causing the pattern match code to treat it opaquely.
|
||||
// FIXME: This code doesn't emit errors itself, the caller emits the errors.
|
||||
// So instead of specific errors, you just get blanket errors about the whole
|
||||
// const type. See
|
||||
// https://github.com/rust-lang/rust/pull/70743#discussion_r404701963 for
|
||||
// details.
|
||||
// Backwards compatibility hack because we can't cause hard errors on these
|
||||
// types, so we compare them via `PartialEq::eq` at runtime.
|
||||
ty::Adt(..) if !self.type_marked_structural(ty) && self.behind_reference.get() => {
|
||||
if self.saw_const_match_error.get().is_none() && !self.saw_const_match_lint.get() {
|
||||
self.saw_const_match_lint.set(true);
|
||||
tcx.emit_node_span_lint(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
IndirectStructuralMatch { non_sm_ty: ty },
|
||||
);
|
||||
}
|
||||
// Since we are behind a reference, we can just bubble the error up so we get a
|
||||
// constant at reference type, making it easy to let the fallback call
|
||||
// `PartialEq::eq` on it.
|
||||
return Err(FallbackToOpaqueConst);
|
||||
}
|
||||
ty::FnDef(..) => {
|
||||
let e = tcx.dcx().emit_err(InvalidPattern { span, non_sm_ty: ty });
|
||||
self.saw_const_match_error.set(Some(e));
|
||||
|
|
@ -379,38 +339,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
ty::Str => {
|
||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
||||
}
|
||||
// Backwards compatibility hack: support references to non-structural types,
|
||||
// but hard error if we aren't behind a double reference. We could just use
|
||||
// the fallback code path below, but that would allow *more* of this fishy
|
||||
// code to compile, as then it only goes through the future incompat lint
|
||||
// instead of a hard error.
|
||||
ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
|
||||
if self.behind_reference.get() {
|
||||
if self.saw_const_match_error.get().is_none()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
tcx.emit_node_span_lint(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
span,
|
||||
IndirectStructuralMatch { non_sm_ty: *pointee_ty },
|
||||
);
|
||||
}
|
||||
return Err(FallbackToOpaqueConst);
|
||||
} else {
|
||||
if let Some(e) = self.saw_const_match_error.get() {
|
||||
// We already errored. Signal that in the pattern, so that follow up errors can be silenced.
|
||||
PatKind::Error(e)
|
||||
} else {
|
||||
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
|
||||
let e = tcx.dcx().emit_err(err);
|
||||
self.saw_const_match_error.set(Some(e));
|
||||
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
||||
PatKind::Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
// All other references are converted into deref patterns and then recursively
|
||||
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
||||
// deref pattern.
|
||||
|
|
@ -421,7 +349,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
||||
PatKind::Error(e)
|
||||
} else {
|
||||
let old = self.behind_reference.replace(true);
|
||||
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
|
||||
// matching against references, you can only use byte string literals.
|
||||
// The typechecker has a special case for byte string literals, by treating them
|
||||
|
|
@ -436,7 +363,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
};
|
||||
// References have the same valtree representation as their pointee.
|
||||
let subpattern = self.recur(cv, pointee_ty)?;
|
||||
self.behind_reference.set(old);
|
||||
PatKind::Deref { subpattern }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ struct ConstAnalysis<'a, 'tcx> {
|
|||
map: Map,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
local_decls: &'a LocalDecls<'tcx>,
|
||||
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||
ecx: InterpCx<'tcx, DummyMachine>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
|
|
@ -142,11 +142,10 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
|||
_ => return,
|
||||
};
|
||||
if let Some(variant_target_idx) = variant_target {
|
||||
for (field_index, operand) in operands.iter().enumerate() {
|
||||
if let Some(field) = self.map().apply(
|
||||
variant_target_idx,
|
||||
TrackElem::Field(FieldIdx::from_usize(field_index)),
|
||||
) {
|
||||
for (field_index, operand) in operands.iter_enumerated() {
|
||||
if let Some(field) =
|
||||
self.map().apply(variant_target_idx, TrackElem::Field(field_index))
|
||||
{
|
||||
self.assign_operand(state, field, operand);
|
||||
}
|
||||
}
|
||||
|
|
@ -565,7 +564,7 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
|
|||
|
||||
fn try_make_constant(
|
||||
&self,
|
||||
ecx: &mut InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||
ecx: &mut InterpCx<'tcx, DummyMachine>,
|
||||
place: Place<'tcx>,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
|
|
@ -618,7 +617,7 @@ fn propagatable_scalar(
|
|||
|
||||
#[instrument(level = "trace", skip(ecx, state, map))]
|
||||
fn try_write_constant<'tcx>(
|
||||
ecx: &mut InterpCx<'_, 'tcx, DummyMachine>,
|
||||
ecx: &mut InterpCx<'tcx, DummyMachine>,
|
||||
dest: &PlaceTy<'tcx>,
|
||||
place: PlaceIndex,
|
||||
ty: Ty<'tcx>,
|
||||
|
|
@ -836,7 +835,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> {
|
|||
struct OperandCollector<'tcx, 'map, 'locals, 'a> {
|
||||
state: &'a State<FlatSet<Scalar>>,
|
||||
visitor: &'a mut Collector<'tcx, 'locals>,
|
||||
ecx: &'map mut InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||
ecx: &'map mut InterpCx<'tcx, DummyMachine>,
|
||||
map: &'map Map,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_errors::{codes::*, Diag, DiagMessage, LintDiagnostic};
|
||||
use rustc_errors::{codes::*, Diag, LintDiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
@ -50,18 +50,15 @@ pub(crate) enum AssertLintKind {
|
|||
|
||||
impl<'a, P: std::fmt::Debug> LintDiagnostic<'a, ()> for AssertLint<P> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
|
||||
let message = self.assert_kind.diagnostic_message();
|
||||
diag.primary_message(match self.lint_kind {
|
||||
AssertLintKind::ArithmeticOverflow => fluent::mir_transform_arithmetic_overflow,
|
||||
AssertLintKind::UnconditionalPanic => fluent::mir_transform_operation_will_panic,
|
||||
});
|
||||
let label = self.assert_kind.diagnostic_message();
|
||||
self.assert_kind.add_args(&mut |name, value| {
|
||||
diag.arg(name, value);
|
||||
});
|
||||
diag.span_label(self.span, message);
|
||||
}
|
||||
|
||||
fn msg(&self) -> DiagMessage {
|
||||
match self.lint_kind {
|
||||
AssertLintKind::ArithmeticOverflow => fluent::mir_transform_arithmetic_overflow,
|
||||
AssertLintKind::UnconditionalPanic => fluent::mir_transform_operation_will_panic,
|
||||
}
|
||||
diag.span_label(self.span, label);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +101,7 @@ pub(crate) struct MustNotSupend<'tcx, 'a> {
|
|||
// Needed for def_path_str
|
||||
impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
|
||||
diag.primary_message(fluent::mir_transform_must_not_suspend);
|
||||
diag.span_label(self.yield_sp, fluent::_subdiag::label);
|
||||
if let Some(reason) = self.reason {
|
||||
diag.subdiagnostic(diag.dcx, reason);
|
||||
|
|
@ -113,10 +111,6 @@ impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> {
|
|||
diag.arg("def_path", self.tcx.def_path_str(self.def_id));
|
||||
diag.arg("post", self.post);
|
||||
}
|
||||
|
||||
fn msg(&self) -> rustc_errors::DiagMessage {
|
||||
fluent::mir_transform_must_not_suspend
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ enum Value<'tcx> {
|
|||
|
||||
struct VnState<'body, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||
ecx: InterpCx<'tcx, DummyMachine>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
local_decls: &'body LocalDecls<'tcx>,
|
||||
/// Value stored in each local.
|
||||
|
|
@ -1139,7 +1139,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
}
|
||||
|
||||
fn op_to_prop_const<'tcx>(
|
||||
ecx: &mut InterpCx<'_, 'tcx, DummyMachine>,
|
||||
ecx: &mut InterpCx<'tcx, DummyMachine>,
|
||||
op: &OpTy<'tcx>,
|
||||
) -> Option<ConstValue<'tcx>> {
|
||||
// Do not attempt to propagate unsized locals.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use rustc_middle::ty::layout::ValidityRequirement;
|
|||
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
pub struct InstSimplify;
|
||||
|
|
@ -217,11 +216,11 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
|||
&& let Some(place) = operand.place()
|
||||
{
|
||||
let variant = adt_def.non_enum_variant();
|
||||
for (i, field) in variant.fields.iter().enumerate() {
|
||||
for (i, field) in variant.fields.iter_enumerated() {
|
||||
let field_ty = field.ty(self.tcx, args);
|
||||
if field_ty == *cast_ty {
|
||||
let place = place.project_deeper(
|
||||
&[ProjectionElem::Field(FieldIdx::from_usize(i), *cast_ty)],
|
||||
&[ProjectionElem::Field(i, *cast_ty)],
|
||||
self.tcx,
|
||||
);
|
||||
let operand = if operand.is_move() {
|
||||
|
|
|
|||
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