Auto merge of #95056 - Dylan-DPC:rollup-swtuw2n, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #91133 (Improve `unsafe` diagnostic) - #93222 (Make ErrorReported impossible to construct outside `rustc_errors`) - #93745 (Stabilize ADX target feature) - #94309 ([generator_interior] Be more precise with scopes of borrowed places) - #94698 (Remove redundant code from copy-suggestions) - #94731 (Suggest adding `{ .. }` around a const function call with arguments) - #94960 (Fix many spelling mistakes) - #94982 (Add deprecated_safe feature gate and attribute, cc #94978) - #94997 (debuginfo: Fix ICE when generating name for type that produces a layout error.) - #95000 (Fixed wrong type name in comment) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
cd11905716
181 changed files with 1290 additions and 773 deletions
|
@ -26,7 +26,7 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
|
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
|
||||||
/// to the where clause that is prefered, if it exists. Otherwise, it sets the span to the other where
|
/// to the where clause that is preferred, if it exists. Otherwise, it sets the span to the other where
|
||||||
/// clause if it exists.
|
/// clause if it exists.
|
||||||
fn add_ty_alias_where_clause(
|
fn add_ty_alias_where_clause(
|
||||||
generics: &mut ast::Generics,
|
generics: &mut ast::Generics,
|
||||||
|
|
|
@ -952,7 +952,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
sess.diagnostic().delay_span_bug(
|
sess.diagnostic().delay_span_bug(
|
||||||
span,
|
span,
|
||||||
"unexpected delimiter in key-value attribute's value",
|
"unexpected delimiter in key-value attribute's value",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
unwrap_single_token(sess, tokens, span)
|
unwrap_single_token(sess, tokens, span)
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,7 +440,7 @@ impl<'a> AstValidator<'a> {
|
||||||
attr.span,
|
attr.span,
|
||||||
"allow, cfg, cfg_attr, deny, \
|
"allow, cfg, cfg_attr, deny, \
|
||||||
forbid, and warn are the only allowed built-in attributes in function parameters",
|
forbid, and warn are the only allowed built-in attributes in function parameters",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,11 +252,12 @@ impl<'a> PostExpansionVisitor<'a> {
|
||||||
"wasm ABI is experimental and subject to change"
|
"wasm ABI is experimental and subject to change"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
abi => self
|
abi => {
|
||||||
.sess
|
self.sess.parse_sess.span_diagnostic.delay_span_bug(
|
||||||
.parse_sess
|
span,
|
||||||
.span_diagnostic
|
&format!("unrecognized ABI not caught in lowering: {}", abi),
|
||||||
.delay_span_bug(span, &format!("unrecognized ABI not caught in lowering: {}", abi)),
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,7 @@ use rustc_middle::mir::{
|
||||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
||||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
||||||
self, suggest_constraining_type_param, suggest_constraining_type_params, PredicateKind, Ty,
|
|
||||||
};
|
|
||||||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{BytePos, MultiSpan, Span};
|
use rustc_span::{BytePos, MultiSpan, Span};
|
||||||
|
@ -285,27 +283,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
Some(ref name) => format!("`{}`", name),
|
Some(ref name) => format!("`{}`", name),
|
||||||
None => "value".to_owned(),
|
None => "value".to_owned(),
|
||||||
};
|
};
|
||||||
if let ty::Param(param_ty) = ty.kind() {
|
|
||||||
let tcx = self.infcx.tcx;
|
|
||||||
let generics = tcx.generics_of(self.mir_def_id());
|
|
||||||
let param = generics.type_param(¶m_ty, tcx);
|
|
||||||
if let Some(generics) = tcx
|
|
||||||
.typeck_root_def_id(self.mir_def_id().to_def_id())
|
|
||||||
.as_local()
|
|
||||||
.and_then(|def_id| tcx.hir().get_generics(def_id))
|
|
||||||
{
|
|
||||||
suggest_constraining_type_param(
|
|
||||||
tcx,
|
|
||||||
generics,
|
|
||||||
&mut err,
|
|
||||||
param.name.as_str(),
|
|
||||||
"Copy",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
|
||||||
|
|
||||||
|
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let generics = tcx.generics_of(self.mir_def_id());
|
let generics = tcx.generics_of(self.mir_def_id());
|
||||||
if let Some(hir_generics) = tcx
|
if let Some(hir_generics) = tcx
|
||||||
|
@ -342,10 +321,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
match predicate.self_ty().kind() {
|
match predicate.self_ty().kind() {
|
||||||
ty::Param(param_ty) => Ok((
|
ty::Param(param_ty) => Ok((
|
||||||
generics.type_param(param_ty, tcx),
|
generics.type_param(param_ty, tcx),
|
||||||
predicate
|
predicate.trait_ref.print_only_trait_path().to_string(),
|
||||||
.trait_ref
|
|
||||||
.print_only_trait_path()
|
|
||||||
.to_string(),
|
|
||||||
)),
|
)),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
|
@ -366,7 +342,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let span = if let Some(local) = place.as_local() {
|
let span = if let Some(local) = place.as_local() {
|
||||||
let decl = &self.body.local_decls[local];
|
let decl = &self.body.local_decls[local];
|
||||||
|
|
|
@ -178,7 +178,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
||||||
|
|
||||||
// Gather the upvars of a closure, if any.
|
// Gather the upvars of a closure, if any.
|
||||||
let tables = tcx.typeck_opt_const_arg(def);
|
let tables = tcx.typeck_opt_const_arg(def);
|
||||||
if let Some(ErrorGuaranteed) = tables.tainted_by_errors {
|
if let Some(ErrorGuaranteed { .. }) = tables.tainted_by_errors {
|
||||||
infcx.set_tainted_by_errors();
|
infcx.set_tainted_by_errors();
|
||||||
errors.set_tainted_by_errors();
|
errors.set_tainted_by_errors();
|
||||||
}
|
}
|
||||||
|
@ -2274,6 +2274,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod error {
|
mod error {
|
||||||
|
use rustc_errors::ErrorGuaranteed;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub struct BorrowckErrors<'tcx> {
|
pub struct BorrowckErrors<'tcx> {
|
||||||
|
@ -2311,7 +2313,7 @@ mod error {
|
||||||
// FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is
|
// FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is
|
||||||
// set before any emission actually happens (weakening the guarantee).
|
// set before any emission actually happens (weakening the guarantee).
|
||||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
||||||
self.tainted_by_errors = Some(ErrorGuaranteed {});
|
self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||||
t.buffer(&mut self.buffered);
|
t.buffer(&mut self.buffered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2320,7 +2322,7 @@ mod error {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_tainted_by_errors(&mut self) {
|
pub fn set_tainted_by_errors(&mut self) {
|
||||||
self.tainted_by_errors = Some(ErrorGuaranteed {});
|
self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
//! Handling of `static`s, `const`s and promoted allocations
|
//! Handling of `static`s, `const`s and promoted allocations
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
|
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
|
||||||
|
@ -54,7 +53,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
||||||
{
|
{
|
||||||
all_constants_ok = false;
|
all_constants_ok = false;
|
||||||
match err {
|
match err {
|
||||||
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {
|
ErrorHandled::Reported(_) | ErrorHandled::Linted => {
|
||||||
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
|
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
|
||||||
}
|
}
|
||||||
ErrorHandled::TooGeneric => {
|
ErrorHandled::TooGeneric => {
|
||||||
|
|
|
@ -74,9 +74,30 @@ fn push_debuginfo_type_name<'tcx>(
|
||||||
ty::Float(float_ty) => output.push_str(float_ty.name_str()),
|
ty::Float(float_ty) => output.push_str(float_ty.name_str()),
|
||||||
ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
|
ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
|
||||||
ty::Adt(def, substs) => {
|
ty::Adt(def, substs) => {
|
||||||
let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).expect("layout error");
|
// `layout_for_cpp_like_fallback` will be `Some` if we want to use the fallback encoding.
|
||||||
|
let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() {
|
||||||
|
match tcx.layout_of(ParamEnv::reveal_all().and(t)) {
|
||||||
|
Ok(layout) => {
|
||||||
|
if !wants_c_like_enum_debuginfo(layout) {
|
||||||
|
Some(layout)
|
||||||
|
} else {
|
||||||
|
// This is a C-like enum so we don't want to use the fallback encoding
|
||||||
|
// for the name.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// Computing the layout can still fail here, e.g. if the target architecture
|
||||||
|
// cannot represent the type. See https://github.com/rust-lang/rust/issues/94961.
|
||||||
|
tcx.sess.fatal(&format!("{}", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We are not emitting cpp-like debuginfo or this isn't even an enum.
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if def.is_enum() && cpp_like_debuginfo && !wants_c_like_enum_debuginfo(ty_and_layout) {
|
if let Some(ty_and_layout) = layout_for_cpp_like_fallback {
|
||||||
msvc_enum_fallback(
|
msvc_enum_fallback(
|
||||||
tcx,
|
tcx,
|
||||||
ty_and_layout,
|
ty_and_layout,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
|
||||||
|
@ -191,7 +190,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
all_consts_ok = false;
|
all_consts_ok = false;
|
||||||
match err {
|
match err {
|
||||||
// errored or at least linted
|
// errored or at least linted
|
||||||
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {}
|
ErrorHandled::Reported(_) | ErrorHandled::Linted => {}
|
||||||
ErrorHandled::TooGeneric => {
|
ErrorHandled::TooGeneric => {
|
||||||
span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err)
|
span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||||
("adx", Some(sym::adx_target_feature)),
|
("adx", None),
|
||||||
("aes", None),
|
("aes", None),
|
||||||
("avx", None),
|
("avx", None),
|
||||||
("avx2", None),
|
("avx2", None),
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
@ -247,11 +246,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||||
if ecx.tcx.is_ctfe_mir_available(def.did) {
|
if ecx.tcx.is_ctfe_mir_available(def.did) {
|
||||||
Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
|
Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
|
||||||
} else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst {
|
} else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst {
|
||||||
ecx.tcx.sess.delay_span_bug(
|
let guar = ecx.tcx.sess.delay_span_bug(
|
||||||
rustc_span::DUMMY_SP,
|
rustc_span::DUMMY_SP,
|
||||||
"This is likely a const item that is missing from its impl",
|
"This is likely a const item that is missing from its impl",
|
||||||
);
|
);
|
||||||
throw_inval!(AlreadyReported(ErrorGuaranteed {}));
|
throw_inval!(AlreadyReported(guar));
|
||||||
} else {
|
} else {
|
||||||
let path = ecx.tcx.def_path_str(def.did);
|
let path = ecx.tcx.def_path_str(def.did);
|
||||||
Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path))
|
Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path))
|
||||||
|
|
|
@ -406,8 +406,11 @@ pub fn intern_const_alloc_recursive<
|
||||||
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
|
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
|
||||||
// Codegen does not like dangling pointers, and generally `tcx` assumes that
|
// Codegen does not like dangling pointers, and generally `tcx` assumes that
|
||||||
// all allocations referenced anywhere actually exist. So, make sure we error here.
|
// all allocations referenced anywhere actually exist. So, make sure we error here.
|
||||||
ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
|
let reported = ecx
|
||||||
return Err(ErrorGuaranteed);
|
.tcx
|
||||||
|
.sess
|
||||||
|
.span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
|
||||||
|
return Err(reported);
|
||||||
} else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
|
} else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
|
||||||
// We have hit an `AllocId` that is neither in local or global memory and isn't
|
// We have hit an `AllocId` that is neither in local or global memory and isn't
|
||||||
// marked as dangling by local memory. That should be impossible.
|
// marked as dangling by local memory. That should be impossible.
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_hir::def::Namespace;
|
use rustc_hir::def::Namespace;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
|
||||||
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
|
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
|
||||||
use rustc_middle::ty::{ConstInt, Ty};
|
use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty};
|
||||||
use rustc_middle::{mir, ty};
|
use rustc_middle::{mir, ty};
|
||||||
use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
|
use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
|
||||||
use rustc_target::abi::{VariantIdx, Variants};
|
use rustc_target::abi::{VariantIdx, Variants};
|
||||||
|
@ -565,7 +564,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
match val.val() {
|
match val.val() {
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
|
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
|
||||||
ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorGuaranteed)),
|
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
|
||||||
|
throw_inval!(AlreadyReported(reported))
|
||||||
|
}
|
||||||
ty::ConstKind::Unevaluated(uv) => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
let instance = self.resolve(uv.def, uv.substs)?;
|
let instance = self.resolve(uv.def, uv.substs)?;
|
||||||
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
|
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
|
||||||
|
|
|
@ -259,7 +259,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
||||||
self.tcx.sess.diagnostic().emit_diagnostic(&error);
|
self.tcx.sess.diagnostic().emit_diagnostic(&error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert!(self.tcx.sess.has_errors());
|
assert!(self.tcx.sess.has_errors().is_some());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,8 +327,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
||||||
|
|
||||||
match op.importance() {
|
match op.importance() {
|
||||||
ops::DiagnosticImportance::Primary => {
|
ops::DiagnosticImportance::Primary => {
|
||||||
self.error_emitted = Some(ErrorGuaranteed);
|
let reported = err.emit();
|
||||||
err.emit();
|
self.error_emitted = Some(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),
|
ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),
|
||||||
|
|
|
@ -235,7 +235,7 @@ fn run_compiler(
|
||||||
};
|
};
|
||||||
|
|
||||||
match make_input(config.opts.error_format, &matches.free) {
|
match make_input(config.opts.error_format, &matches.free) {
|
||||||
Err(ErrorGuaranteed) => return Err(ErrorGuaranteed),
|
Err(reported) => return Err(reported),
|
||||||
Ok(Some((input, input_file_path))) => {
|
Ok(Some((input, input_file_path))) => {
|
||||||
config.input = input;
|
config.input = input;
|
||||||
config.input_path = input_file_path;
|
config.input_path = input_file_path;
|
||||||
|
@ -465,11 +465,11 @@ fn make_input(
|
||||||
if io::stdin().read_to_string(&mut src).is_err() {
|
if io::stdin().read_to_string(&mut src).is_err() {
|
||||||
// Immediately stop compilation if there was an issue reading
|
// Immediately stop compilation if there was an issue reading
|
||||||
// the input (for example if the input stream is not UTF-8).
|
// the input (for example if the input stream is not UTF-8).
|
||||||
early_error_no_abort(
|
let reported = early_error_no_abort(
|
||||||
error_format,
|
error_format,
|
||||||
"couldn't read from stdin, as it did not contain valid UTF-8",
|
"couldn't read from stdin, as it did not contain valid UTF-8",
|
||||||
);
|
);
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
|
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
|
||||||
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
|
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
|
||||||
|
@ -1128,7 +1128,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
|
||||||
pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
|
pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
|
||||||
catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
|
catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
|
||||||
if value.is::<rustc_errors::FatalErrorMarker>() {
|
if value.is::<rustc_errors::FatalErrorMarker>() {
|
||||||
ErrorGuaranteed
|
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||||
} else {
|
} else {
|
||||||
panic::resume_unwind(value);
|
panic::resume_unwind(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
|
||||||
DiagnosticBuilderState::Emittable(handler) => {
|
DiagnosticBuilderState::Emittable(handler) => {
|
||||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||||
|
|
||||||
handler.emit_diagnostic(&db.inner.diagnostic);
|
let guar = handler.emit_diagnostic(&db.inner.diagnostic);
|
||||||
|
|
||||||
// Only allow a guarantee if the `level` wasn't switched to a
|
// Only allow a guarantee if the `level` wasn't switched to a
|
||||||
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
||||||
|
@ -139,7 +139,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
|
||||||
from `DiagnosticBuilder<ErrorGuaranteed>`",
|
from `DiagnosticBuilder<ErrorGuaranteed>`",
|
||||||
db.inner.diagnostic.level,
|
db.inner.diagnostic.level,
|
||||||
);
|
);
|
||||||
ErrorGuaranteed
|
guar.unwrap()
|
||||||
}
|
}
|
||||||
// `.emit()` was previously called, disallowed from repeating it,
|
// `.emit()` was previously called, disallowed from repeating it,
|
||||||
// but can take advantage of the previous `.emit()`'s guarantee
|
// but can take advantage of the previous `.emit()`'s guarantee
|
||||||
|
@ -154,7 +154,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
|
||||||
became non-error ({:?}), after original `.emit()`",
|
became non-error ({:?}), after original `.emit()`",
|
||||||
db.inner.diagnostic.level,
|
db.inner.diagnostic.level,
|
||||||
);
|
);
|
||||||
ErrorGuaranteed
|
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -399,7 +399,7 @@ impl fmt::Display for ExplicitBug {
|
||||||
impl error::Error for ExplicitBug {}
|
impl error::Error for ExplicitBug {}
|
||||||
|
|
||||||
pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
|
pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
|
||||||
pub use diagnostic_builder::DiagnosticBuilder;
|
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
|
||||||
use std::backtrace::Backtrace;
|
use std::backtrace::Backtrace;
|
||||||
|
|
||||||
/// A handler deals with errors and other compiler output.
|
/// A handler deals with errors and other compiler output.
|
||||||
|
@ -644,8 +644,8 @@ impl Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit all stashed diagnostics.
|
/// Emit all stashed diagnostics.
|
||||||
pub fn emit_stashed_diagnostics(&self) {
|
pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
|
||||||
self.inner.borrow_mut().emit_stashed_diagnostics();
|
self.inner.borrow_mut().emit_stashed_diagnostics()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
|
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
|
||||||
|
@ -805,8 +805,8 @@ impl Handler {
|
||||||
FatalError.raise()
|
FatalError.raise()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
|
pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
|
||||||
self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
|
self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
|
pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
|
||||||
|
@ -829,7 +829,7 @@ impl Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) {
|
pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
|
||||||
self.inner.borrow_mut().delay_span_bug(span, msg)
|
self.inner.borrow_mut().delay_span_bug(span, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,8 +858,8 @@ impl Handler {
|
||||||
self.inner.borrow_mut().fatal(msg)
|
self.inner.borrow_mut().fatal(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn err(&self, msg: &str) {
|
pub fn err(&self, msg: &str) -> ErrorGuaranteed {
|
||||||
self.inner.borrow_mut().err(msg);
|
self.inner.borrow_mut().err(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn warn(&self, msg: &str) {
|
pub fn warn(&self, msg: &str) {
|
||||||
|
@ -880,11 +880,15 @@ impl Handler {
|
||||||
self.inner.borrow().err_count()
|
self.inner.borrow().err_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_errors(&self) -> bool {
|
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
|
||||||
self.inner.borrow().has_errors()
|
if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
|
||||||
|
}
|
||||||
|
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
|
||||||
|
if self.inner.borrow().has_errors_or_lint_errors() {
|
||||||
|
Some(ErrorGuaranteed(()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
pub fn has_errors_or_lint_errors(&self) -> bool {
|
|
||||||
self.inner.borrow().has_errors_or_lint_errors()
|
|
||||||
}
|
}
|
||||||
pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
|
pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
|
||||||
self.inner.borrow().has_errors_or_delayed_span_bugs()
|
self.inner.borrow().has_errors_or_delayed_span_bugs()
|
||||||
|
@ -915,13 +919,17 @@ impl Handler {
|
||||||
self.inner.borrow_mut().force_print_diagnostic(db)
|
self.inner.borrow_mut().force_print_diagnostic(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) {
|
pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
|
||||||
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
|
fn emit_diag_at_span(
|
||||||
|
&self,
|
||||||
|
mut diag: Diagnostic,
|
||||||
|
sp: impl Into<MultiSpan>,
|
||||||
|
) -> Option<ErrorGuaranteed> {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.emit_diagnostic(diag.set_span(sp));
|
inner.emit_diagnostic(diag.set_span(sp))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
|
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
|
||||||
|
@ -990,13 +998,20 @@ impl HandlerInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit all stashed diagnostics.
|
/// Emit all stashed diagnostics.
|
||||||
fn emit_stashed_diagnostics(&mut self) {
|
fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
|
||||||
let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
|
let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
|
||||||
diags.iter().for_each(|diag| self.emit_diagnostic(diag));
|
let mut reported = None;
|
||||||
|
diags.iter().for_each(|diag| {
|
||||||
|
if diag.is_error() {
|
||||||
|
reported = Some(ErrorGuaranteed(()));
|
||||||
|
}
|
||||||
|
self.emit_diagnostic(diag);
|
||||||
|
});
|
||||||
|
reported
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eddyb) this should ideally take `diagnostic` by value.
|
// FIXME(eddyb) this should ideally take `diagnostic` by value.
|
||||||
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
|
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
|
||||||
if diagnostic.level == Level::DelayedBug {
|
if diagnostic.level == Level::DelayedBug {
|
||||||
// FIXME(eddyb) this should check for `has_errors` and stop pushing
|
// FIXME(eddyb) this should check for `has_errors` and stop pushing
|
||||||
// once *any* errors were emitted (and truncate `delayed_span_bugs`
|
// once *any* errors were emitted (and truncate `delayed_span_bugs`
|
||||||
|
@ -1005,7 +1020,7 @@ impl HandlerInner {
|
||||||
self.delayed_span_bugs.push(diagnostic.clone());
|
self.delayed_span_bugs.push(diagnostic.clone());
|
||||||
|
|
||||||
if !self.flags.report_delayed_bugs {
|
if !self.flags.report_delayed_bugs {
|
||||||
return;
|
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,7 +1035,7 @@ impl HandlerInner {
|
||||||
if diagnostic.has_future_breakage() {
|
if diagnostic.has_future_breakage() {
|
||||||
(*TRACK_DIAGNOSTICS)(diagnostic);
|
(*TRACK_DIAGNOSTICS)(diagnostic);
|
||||||
}
|
}
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The `LintExpectationId` can be stable or unstable depending on when it was created.
|
// The `LintExpectationId` can be stable or unstable depending on when it was created.
|
||||||
|
@ -1029,16 +1044,16 @@ impl HandlerInner {
|
||||||
// a stable one by the `LintLevelsBuilder`.
|
// a stable one by the `LintLevelsBuilder`.
|
||||||
if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
|
if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
|
||||||
self.unstable_expect_diagnostics.push(diagnostic.clone());
|
self.unstable_expect_diagnostics.push(diagnostic.clone());
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*TRACK_DIAGNOSTICS)(diagnostic);
|
(*TRACK_DIAGNOSTICS)(diagnostic);
|
||||||
|
|
||||||
if let Level::Expect(expectation_id) = diagnostic.level {
|
if let Level::Expect(expectation_id) = diagnostic.level {
|
||||||
self.fulfilled_expectations.insert(expectation_id);
|
self.fulfilled_expectations.insert(expectation_id);
|
||||||
return;
|
return None;
|
||||||
} else if diagnostic.level == Allow {
|
} else if diagnostic.level == Allow {
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref code) = diagnostic.code {
|
if let Some(ref code) = diagnostic.code {
|
||||||
|
@ -1068,8 +1083,12 @@ impl HandlerInner {
|
||||||
} else {
|
} else {
|
||||||
self.bump_err_count();
|
self.bump_err_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
|
||||||
} else {
|
} else {
|
||||||
self.bump_warn_count();
|
self.bump_warn_count();
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,7 +1210,7 @@ impl HandlerInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
|
fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
|
||||||
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
|
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
|
||||||
// incrementing `err_count` by one, so we need to +1 the comparing.
|
// incrementing `err_count` by one, so we need to +1 the comparing.
|
||||||
// FIXME: Would be nice to increment err_count in a more coherent way.
|
// FIXME: Would be nice to increment err_count in a more coherent way.
|
||||||
|
@ -1202,7 +1221,7 @@ impl HandlerInner {
|
||||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
||||||
diagnostic.set_span(sp.into());
|
diagnostic.set_span(sp.into());
|
||||||
diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
|
diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
|
||||||
self.emit_diagnostic(&diagnostic)
|
self.emit_diagnostic(&diagnostic).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
|
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
|
||||||
|
@ -1221,20 +1240,20 @@ impl HandlerInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fatal(&mut self, msg: &str) -> FatalError {
|
fn fatal(&mut self, msg: &str) -> FatalError {
|
||||||
self.emit_error(Fatal, msg);
|
self.emit(Fatal, msg);
|
||||||
FatalError
|
FatalError
|
||||||
}
|
}
|
||||||
|
|
||||||
fn err(&mut self, msg: &str) {
|
fn err(&mut self, msg: &str) -> ErrorGuaranteed {
|
||||||
self.emit_error(Error { lint: false }, msg);
|
self.emit(Error { lint: false }, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit an error; level should be `Error` or `Fatal`.
|
/// Emit an error; level should be `Error` or `Fatal`.
|
||||||
fn emit_error(&mut self, level: Level, msg: &str) {
|
fn emit(&mut self, level: Level, msg: &str) -> ErrorGuaranteed {
|
||||||
if self.treat_err_as_bug() {
|
if self.treat_err_as_bug() {
|
||||||
self.bug(msg);
|
self.bug(msg);
|
||||||
}
|
}
|
||||||
self.emit_diagnostic(&Diagnostic::new(level, msg));
|
self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bug(&mut self, msg: &str) -> ! {
|
fn bug(&mut self, msg: &str) -> ! {
|
||||||
|
@ -1433,9 +1452,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Useful type to use with `Result<>` indicate that an error has already
|
/// Useful type to use with `Result<>` indicate that an error has already
|
||||||
// been reported to the user, so no need to continue checking.
|
/// been reported to the user, so no need to continue checking.
|
||||||
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct ErrorGuaranteed;
|
pub struct ErrorGuaranteed(());
|
||||||
|
|
||||||
|
impl ErrorGuaranteed {
|
||||||
|
/// To be used only if you really know what you are doing... ideally, we would find a way to
|
||||||
|
/// eliminate all calls to this method.
|
||||||
|
pub fn unchecked_claim_error_was_emitted() -> Self {
|
||||||
|
ErrorGuaranteed(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);
|
rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);
|
||||||
|
|
|
@ -1330,7 +1330,7 @@ pub fn parse_macro_name_and_helper_attrs(
|
||||||
let attributes_attr = list.get(1);
|
let attributes_attr = list.get(1);
|
||||||
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
|
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
|
||||||
if !attr.has_name(sym::attributes) {
|
if !attr.has_name(sym::attributes) {
|
||||||
diag.span_err(attr.span(), "second argument must be `attributes`")
|
diag.span_err(attr.span(), "second argument must be `attributes`");
|
||||||
}
|
}
|
||||||
attr.meta_item_list()
|
attr.meta_item_list()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
|
|
|
@ -534,10 +534,10 @@ pub fn compile_declarative_macro(
|
||||||
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
|
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
|
||||||
match transparency_error {
|
match transparency_error {
|
||||||
Some(TransparencyError::UnknownTransparency(value, span)) => {
|
Some(TransparencyError::UnknownTransparency(value, span)) => {
|
||||||
diag.span_err(span, &format!("unknown macro transparency: `{}`", value))
|
diag.span_err(span, &format!("unknown macro transparency: `{}`", value));
|
||||||
}
|
}
|
||||||
Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => {
|
Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => {
|
||||||
diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes")
|
diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes");
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -617,7 +617,9 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
|
||||||
fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
|
fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
|
||||||
match *rhs {
|
match *rhs {
|
||||||
mbe::TokenTree::Delimited(..) => return true,
|
mbe::TokenTree::Delimited(..) => return true,
|
||||||
_ => sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"),
|
_ => {
|
||||||
|
sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,7 @@ impl base::ProcMacro for BangProcMacro {
|
||||||
if let Some(s) = e.as_str() {
|
if let Some(s) = e.as_str() {
|
||||||
err.help(&format!("message: {}", s));
|
err.help(&format!("message: {}", s));
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit()
|
||||||
ErrorGuaranteed
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,8 +57,7 @@ impl base::AttrProcMacro for AttrProcMacro {
|
||||||
if let Some(s) = e.as_str() {
|
if let Some(s) = e.as_str() {
|
||||||
err.help(&format!("message: {}", s));
|
err.help(&format!("message: {}", s));
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit()
|
||||||
ErrorGuaranteed
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,8 @@ declare_features! (
|
||||||
/// Allows the sysV64 ABI to be specified on all platforms
|
/// Allows the sysV64 ABI to be specified on all platforms
|
||||||
/// instead of just the platforms on which it is the C ABI.
|
/// instead of just the platforms on which it is the C ABI.
|
||||||
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
|
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
|
||||||
|
/// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`.
|
||||||
|
(accepted, adx_target_feature, "1.61.0", Some(44839), None),
|
||||||
/// Allows the definition of associated constants in `trait` or `impl` blocks.
|
/// Allows the definition of associated constants in `trait` or `impl` blocks.
|
||||||
(accepted, associated_consts, "1.20.0", Some(29646), None),
|
(accepted, associated_consts, "1.20.0", Some(29646), None),
|
||||||
/// Allows using associated `type`s in `trait`s.
|
/// Allows using associated `type`s in `trait`s.
|
||||||
|
|
|
@ -364,6 +364,8 @@ declare_features! (
|
||||||
(active, default_alloc_error_handler, "1.48.0", Some(66741), None),
|
(active, default_alloc_error_handler, "1.48.0", Some(66741), None),
|
||||||
/// Allows default type parameters to influence type inference.
|
/// Allows default type parameters to influence type inference.
|
||||||
(active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
|
(active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
|
||||||
|
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
|
||||||
|
(active, deprecated_safe, "1.61.0", Some(94978), None),
|
||||||
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
|
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
|
||||||
(active, deprecated_suggestion, "1.61.0", Some(94785), None),
|
(active, deprecated_suggestion, "1.61.0", Some(94785), None),
|
||||||
/// Allows `#[derive(Default)]` and `#[default]` on enums.
|
/// Allows `#[derive(Default)]` and `#[default]` on enums.
|
||||||
|
|
|
@ -452,6 +452,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
"`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
|
"`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
|
||||||
as `const`, which may be removed or renamed in the future."
|
as `const`, which may be removed or renamed in the future."
|
||||||
),
|
),
|
||||||
|
// lang-team MCP 147
|
||||||
|
gated!(
|
||||||
|
deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
|
||||||
|
experimental!(deprecated_safe),
|
||||||
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Internal attributes: Stability, deprecation, and unsafe:
|
// Internal attributes: Stability, deprecation, and unsafe:
|
||||||
|
|
|
@ -225,12 +225,12 @@ pub fn prepare_session_directory(
|
||||||
let crate_dir = match crate_dir.canonicalize() {
|
let crate_dir = match crate_dir.canonicalize() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
sess.err(&format!(
|
let reported = sess.err(&format!(
|
||||||
"incremental compilation: error canonicalizing path `{}`: {}",
|
"incremental compilation: error canonicalizing path `{}`: {}",
|
||||||
crate_dir.display(),
|
crate_dir.display(),
|
||||||
err
|
err
|
||||||
));
|
));
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -489,14 +489,14 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
sess.err(&format!(
|
let reported = sess.err(&format!(
|
||||||
"Could not create incremental compilation {} \
|
"Could not create incremental compilation {} \
|
||||||
directory `{}`: {}",
|
directory `{}`: {}",
|
||||||
dir_tag,
|
dir_tag,
|
||||||
path.display(),
|
path.display(),
|
||||||
err
|
err
|
||||||
));
|
));
|
||||||
Err(ErrorGuaranteed)
|
Err(reported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,8 +545,7 @@ fn lock_directory(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
Err(err.emit())
|
||||||
Err(ErrorGuaranteed)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,8 +147,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
|
|
||||||
self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
|
self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
|
||||||
|
|
||||||
err.emit();
|
let reported = err.emit();
|
||||||
Some(ErrorGuaranteed)
|
Some(reported)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_adding_lifetime_params(
|
fn suggest_adding_lifetime_params(
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
let impl_span = self.tcx().def_span(*impl_def_id);
|
let impl_span = self.tcx().def_span(*impl_def_id);
|
||||||
err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
|
err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
|
||||||
}
|
}
|
||||||
err.emit();
|
let reported = err.emit();
|
||||||
Some(ErrorGuaranteed)
|
Some(reported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,10 +54,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
||||||
|
|
||||||
pub fn try_report(&self) -> Option<ErrorGuaranteed> {
|
pub fn try_report(&self) -> Option<ErrorGuaranteed> {
|
||||||
self.try_report_from_nll()
|
self.try_report_from_nll()
|
||||||
.map(|mut diag| {
|
.map(|mut diag| diag.emit())
|
||||||
diag.emit();
|
|
||||||
ErrorGuaranteed
|
|
||||||
})
|
|
||||||
.or_else(|| self.try_report_impl_not_conforming_to_trait())
|
.or_else(|| self.try_report_impl_not_conforming_to_trait())
|
||||||
.or_else(|| self.try_report_anon_anon_conflict())
|
.or_else(|| self.try_report_anon_anon_conflict())
|
||||||
.or_else(|| self.try_report_static_impl_trait())
|
.or_else(|| self.try_report_static_impl_trait())
|
||||||
|
|
|
@ -84,8 +84,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
|
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
|
||||||
err.emit();
|
let reported = err.emit();
|
||||||
return Some(ErrorGuaranteed);
|
return Some(reported);
|
||||||
} else {
|
} else {
|
||||||
err.cancel();
|
err.cancel();
|
||||||
}
|
}
|
||||||
|
@ -276,8 +276,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
Some((param.param_ty_span, param.param_ty.to_string())),
|
Some((param.param_ty_span, param.param_ty.to_string())),
|
||||||
);
|
);
|
||||||
|
|
||||||
err.emit();
|
let reported = err.emit();
|
||||||
Some(ErrorGuaranteed)
|
Some(reported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
|
) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
|
||||||
&& sup_expected_found == sub_expected_found
|
&& sup_expected_found == sub_expected_found
|
||||||
{
|
{
|
||||||
self.emit_err(
|
let guar = self.emit_err(
|
||||||
var_origin.span(),
|
var_origin.span(),
|
||||||
sub_expected,
|
sub_expected,
|
||||||
sub_found,
|
sub_found,
|
||||||
*trait_item_def_id,
|
*trait_item_def_id,
|
||||||
);
|
);
|
||||||
return Some(ErrorGuaranteed);
|
return Some(guar);
|
||||||
}
|
}
|
||||||
if let RegionResolutionError::ConcreteFailure(origin, _, _)
|
if let RegionResolutionError::ConcreteFailure(origin, _, _)
|
||||||
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
|
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
|
||||||
|
@ -49,18 +49,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
trait_item_def_id,
|
trait_item_def_id,
|
||||||
} = origin
|
} = origin
|
||||||
{
|
{
|
||||||
self.emit_associated_type_err(
|
let guar = self.emit_associated_type_err(
|
||||||
span,
|
span,
|
||||||
self.infcx.tcx.item_name(impl_item_def_id),
|
self.infcx.tcx.item_name(impl_item_def_id),
|
||||||
impl_item_def_id,
|
impl_item_def_id,
|
||||||
trait_item_def_id,
|
trait_item_def_id,
|
||||||
);
|
);
|
||||||
return Some(ErrorGuaranteed);
|
return Some(guar);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) {
|
fn emit_err(
|
||||||
|
&self,
|
||||||
|
sp: Span,
|
||||||
|
expected: Ty<'tcx>,
|
||||||
|
found: Ty<'tcx>,
|
||||||
|
trait_def_id: DefId,
|
||||||
|
) -> ErrorGuaranteed {
|
||||||
let trait_sp = self.tcx().def_span(trait_def_id);
|
let trait_sp = self.tcx().def_span(trait_def_id);
|
||||||
let mut err = self
|
let mut err = self
|
||||||
.tcx()
|
.tcx()
|
||||||
|
@ -142,7 +148,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
argument, the other inputs and its output",
|
argument, the other inputs and its output",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_associated_type_err(
|
fn emit_associated_type_err(
|
||||||
|
@ -151,7 +157,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
item_name: Symbol,
|
item_name: Symbol,
|
||||||
impl_item_def_id: DefId,
|
impl_item_def_id: DefId,
|
||||||
trait_item_def_id: DefId,
|
trait_item_def_id: DefId,
|
||||||
) {
|
) -> ErrorGuaranteed {
|
||||||
let impl_sp = self.tcx().def_span(impl_item_def_id);
|
let impl_sp = self.tcx().def_span(impl_item_def_id);
|
||||||
let trait_sp = self.tcx().def_span(trait_item_def_id);
|
let trait_sp = self.tcx().def_span(trait_item_def_id);
|
||||||
let mut err = self
|
let mut err = self
|
||||||
|
@ -161,7 +167,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
err.span_label(impl_sp, "found");
|
err.span_label(impl_sp, "found");
|
||||||
err.span_label(trait_sp, "expected");
|
err.span_label(trait_sp, "expected");
|
||||||
|
|
||||||
err.emit();
|
err.emit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||||
self.tcx.sess.delay_span_bug(
|
self.tcx.sess.delay_span_bug(
|
||||||
origin.span(),
|
origin.span(),
|
||||||
&format!("no region-bound-pairs for {:?}", body_id),
|
&format!("no region-bound-pairs for {:?}", body_id),
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,7 +373,7 @@ pub fn configure_and_expand(
|
||||||
if recursion_limit_hit {
|
if recursion_limit_hit {
|
||||||
// If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
|
// If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
|
||||||
// with a large AST
|
// with a large AST
|
||||||
Err(ErrorGuaranteed)
|
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
|
||||||
} else {
|
} else {
|
||||||
Ok(krate)
|
Ok(krate)
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ pub fn configure_and_expand(
|
||||||
);
|
);
|
||||||
|
|
||||||
msg.warn("The generated documentation may be incorrect");
|
msg.warn("The generated documentation may be incorrect");
|
||||||
msg.emit()
|
msg.emit();
|
||||||
} else {
|
} else {
|
||||||
krate = sess.time("maybe_create_a_macro_crate", || {
|
krate = sess.time("maybe_create_a_macro_crate", || {
|
||||||
let is_test_crate = sess.opts.test;
|
let is_test_crate = sess.opts.test;
|
||||||
|
@ -742,29 +742,30 @@ pub fn prepare_outputs(
|
||||||
if let Some(ref input_path) = compiler.input_path {
|
if let Some(ref input_path) = compiler.input_path {
|
||||||
if sess.opts.will_create_output_file() {
|
if sess.opts.will_create_output_file() {
|
||||||
if output_contains_path(&output_paths, input_path) {
|
if output_contains_path(&output_paths, input_path) {
|
||||||
sess.err(&format!(
|
let reported = sess.err(&format!(
|
||||||
"the input file \"{}\" would be overwritten by the generated \
|
"the input file \"{}\" would be overwritten by the generated \
|
||||||
executable",
|
executable",
|
||||||
input_path.display()
|
input_path.display()
|
||||||
));
|
));
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
|
if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
|
||||||
sess.err(&format!(
|
let reported = sess.err(&format!(
|
||||||
"the generated executable for the input file \"{}\" conflicts with the \
|
"the generated executable for the input file \"{}\" conflicts with the \
|
||||||
existing directory \"{}\"",
|
existing directory \"{}\"",
|
||||||
input_path.display(),
|
input_path.display(),
|
||||||
dir_path.display()
|
dir_path.display()
|
||||||
));
|
));
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref dir) = compiler.temps_dir {
|
if let Some(ref dir) = compiler.temps_dir {
|
||||||
if fs::create_dir_all(dir).is_err() {
|
if fs::create_dir_all(dir).is_err() {
|
||||||
|
let reported =
|
||||||
sess.err("failed to find or create the directory specified by `--temps-dir`");
|
sess.err("failed to find or create the directory specified by `--temps-dir`");
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,8 +777,9 @@ pub fn prepare_outputs(
|
||||||
if !only_dep_info {
|
if !only_dep_info {
|
||||||
if let Some(ref dir) = compiler.output_dir {
|
if let Some(ref dir) = compiler.output_dir {
|
||||||
if fs::create_dir_all(dir).is_err() {
|
if fs::create_dir_all(dir).is_err() {
|
||||||
|
let reported =
|
||||||
sess.err("failed to find or create the directory specified by `--out-dir`");
|
sess.err("failed to find or create the directory specified by `--out-dir`");
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -987,8 +989,8 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||||
// lot of annoying errors in the ui tests (basically,
|
// lot of annoying errors in the ui tests (basically,
|
||||||
// lint warnings and so on -- kindck used to do this abort, but
|
// lint warnings and so on -- kindck used to do this abort, but
|
||||||
// kindck is gone now). -nmatsakis
|
// kindck is gone now). -nmatsakis
|
||||||
if sess.has_errors() {
|
if let Some(reported) = sess.has_errors() {
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
sess.time("misc_checking_3", || {
|
sess.time("misc_checking_3", || {
|
||||||
|
|
|
@ -5,7 +5,6 @@ use rustc_ast as ast;
|
||||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||||
use rustc_data_structures::svh::Svh;
|
use rustc_data_structures::svh::Svh;
|
||||||
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_hir::def_id::LOCAL_CRATE;
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_incremental::DepGraphFuture;
|
use rustc_incremental::DepGraphFuture;
|
||||||
use rustc_lint::LintStore;
|
use rustc_lint::LintStore;
|
||||||
|
@ -121,10 +120,8 @@ impl<'tcx> Queries<'tcx> {
|
||||||
|
|
||||||
pub fn parse(&self) -> Result<&Query<ast::Crate>> {
|
pub fn parse(&self) -> Result<&Query<ast::Crate>> {
|
||||||
self.parse.compute(|| {
|
self.parse.compute(|| {
|
||||||
passes::parse(self.session(), &self.compiler.input).map_err(|mut parse_error| {
|
passes::parse(self.session(), &self.compiler.input)
|
||||||
parse_error.emit();
|
.map_err(|mut parse_error| parse_error.emit())
|
||||||
ErrorGuaranteed
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ impl BoxPointers {
|
||||||
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
||||||
if leaf_ty.is_box() {
|
if leaf_ty.is_box() {
|
||||||
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
|
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
|
||||||
lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit()
|
lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ impl UnsafeCode {
|
||||||
&self,
|
&self,
|
||||||
cx: &EarlyContext<'_>,
|
cx: &EarlyContext<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
// This comes from a macro that has `#[allow_internal_unsafe]`.
|
// This comes from a macro that has `#[allow_internal_unsafe]`.
|
||||||
if span.allows_unsafe() {
|
if span.allows_unsafe() {
|
||||||
|
@ -350,7 +350,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||||
macros using unsafe without triggering \
|
macros using unsafe without triggering \
|
||||||
the `unsafe_code` lint at their call site",
|
the `unsafe_code` lint at their call site",
|
||||||
)
|
)
|
||||||
.emit()
|
.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,7 +360,7 @@ impl EarlyLintPass for UnsafeCode {
|
||||||
// Don't warn about generated blocks; that'll just pollute the output.
|
// Don't warn about generated blocks; that'll just pollute the output.
|
||||||
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
||||||
self.report_unsafe(cx, blk.span, |lint| {
|
self.report_unsafe(cx, blk.span, |lint| {
|
||||||
lint.build("usage of an `unsafe` block").emit()
|
lint.build("usage of an `unsafe` block").emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,12 +370,12 @@ impl EarlyLintPass for UnsafeCode {
|
||||||
match it.kind {
|
match it.kind {
|
||||||
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
||||||
.report_unsafe(cx, it.span, |lint| {
|
.report_unsafe(cx, it.span, |lint| {
|
||||||
lint.build("declaration of an `unsafe` trait").emit()
|
lint.build("declaration of an `unsafe` trait").emit();
|
||||||
}),
|
}),
|
||||||
|
|
||||||
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
||||||
.report_unsafe(cx, it.span, |lint| {
|
.report_unsafe(cx, it.span, |lint| {
|
||||||
lint.build("implementation of an `unsafe` trait").emit()
|
lint.build("implementation of an `unsafe` trait").emit();
|
||||||
}),
|
}),
|
||||||
|
|
||||||
ast::ItemKind::Fn(..) => {
|
ast::ItemKind::Fn(..) => {
|
||||||
|
@ -450,7 +450,9 @@ impl EarlyLintPass for UnsafeCode {
|
||||||
FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
|
FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
|
||||||
FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
|
FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
|
||||||
};
|
};
|
||||||
self.report_unsafe(cx, span, |lint| lint.build(msg).emit());
|
self.report_unsafe(cx, span, |lint| {
|
||||||
|
lint.build(msg).emit();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,7 +561,7 @@ impl MissingDoc {
|
||||||
MISSING_DOCS,
|
MISSING_DOCS,
|
||||||
cx.tcx.sess.source_map().guess_head_span(sp),
|
cx.tcx.sess.source_map().guess_head_span(sp),
|
||||||
|lint| {
|
|lint| {
|
||||||
lint.build(&format!("missing documentation for {} {}", article, desc)).emit()
|
lint.build(&format!("missing documentation for {} {}", article, desc)).emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -777,7 +779,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
||||||
"type could implement `Copy`; consider adding `impl \
|
"type could implement `Copy`; consider adding `impl \
|
||||||
Copy`",
|
Copy`",
|
||||||
)
|
)
|
||||||
.emit()
|
.emit();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -858,7 +860,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
|
||||||
or a manual implementation",
|
or a manual implementation",
|
||||||
cx.tcx.def_path_str(debug)
|
cx.tcx.def_path_str(debug)
|
||||||
))
|
))
|
||||||
.emit()
|
.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1278,7 +1280,9 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
||||||
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
||||||
let msg = "transmuting &T to &mut T is undefined behavior, \
|
let msg = "transmuting &T to &mut T is undefined behavior, \
|
||||||
even if the reference is unused, consider instead using an UnsafeCell";
|
even if the reference is unused, consider instead using an UnsafeCell";
|
||||||
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| lint.build(msg).emit());
|
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
|
||||||
|
lint.build(msg).emit();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,7 +1332,7 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
||||||
if let Some(items) = attr.meta_item_list() {
|
if let Some(items) = attr.meta_item_list() {
|
||||||
for item in items {
|
for item in items {
|
||||||
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
|
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
|
||||||
lint.build("unstable feature").emit()
|
lint.build("unstable feature").emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1680,7 +1684,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
||||||
or lifetime parameters",
|
or lifetime parameters",
|
||||||
predicate_kind_name, predicate
|
predicate_kind_name, predicate
|
||||||
))
|
))
|
||||||
.emit()
|
.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1915,7 +1919,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
|
||||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
||||||
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
|
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
|
||||||
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
|
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
|
||||||
lint.build("cannot test inner items").emit()
|
lint.build("cannot test inner items").emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2040,7 +2044,7 @@ impl KeywordIdents {
|
||||||
format!("r#{}", ident),
|
format!("r#{}", ident),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit()
|
.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3055,7 +3059,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
|
||||||
"this signature doesn't match the previous declaration",
|
"this signature doesn't match the previous declaration",
|
||||||
)
|
)
|
||||||
.note_expected_found(&"", expected_str, &"", found_str)
|
.note_expected_found(&"", expected_str, &"", found_str)
|
||||||
.emit()
|
.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -593,7 +593,7 @@ pub trait LintContext: Sized {
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<impl Into<MultiSpan>>,
|
span: Option<impl Into<MultiSpan>>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
diagnostic: BuiltinLintDiagnostics,
|
diagnostic: BuiltinLintDiagnostics,
|
||||||
) {
|
) {
|
||||||
self.lookup(lint, span, |lint| {
|
self.lookup(lint, span, |lint| {
|
||||||
|
@ -840,19 +840,23 @@ pub trait LintContext: Sized {
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<S>,
|
span: Option<S>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
);
|
);
|
||||||
|
|
||||||
fn struct_span_lint<S: Into<MultiSpan>>(
|
fn struct_span_lint<S: Into<MultiSpan>>(
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: S,
|
span: S,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
self.lookup(lint, Some(span), decorate);
|
self.lookup(lint, Some(span), decorate);
|
||||||
}
|
}
|
||||||
/// Emit a lint at the appropriate level, with no associated span.
|
/// Emit a lint at the appropriate level, with no associated span.
|
||||||
fn lint(&self, lint: &'static Lint, decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) {
|
fn lint(
|
||||||
|
&self,
|
||||||
|
lint: &'static Lint,
|
||||||
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
|
) {
|
||||||
self.lookup(lint, None as Option<Span>, decorate);
|
self.lookup(lint, None as Option<Span>, decorate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -893,7 +897,7 @@ impl LintContext for LateContext<'_> {
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<S>,
|
span: Option<S>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
let hir_id = self.last_node_with_lint_attrs;
|
let hir_id = self.last_node_with_lint_attrs;
|
||||||
|
|
||||||
|
@ -920,7 +924,7 @@ impl LintContext for EarlyContext<'_> {
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<S>,
|
span: Option<S>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
|
self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,9 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
||||||
self.context.lookup_with_diagnostics(
|
self.context.lookup_with_diagnostics(
|
||||||
lint_id.lint,
|
lint_id.lint,
|
||||||
Some(span),
|
Some(span),
|
||||||
|lint| lint.build(&msg).emit(),
|
|lint| {
|
||||||
|
lint.build(&msg).emit();
|
||||||
|
},
|
||||||
diagnostic,
|
diagnostic,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,7 +652,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<MultiSpan>,
|
span: Option<MultiSpan>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
let (level, src) = self.lint_level(lint);
|
let (level, src) = self.lint_level(lint);
|
||||||
struct_lint_level(self.sess, lint, level, src, span, decorate)
|
struct_lint_level(self.sess, lint, level, src, span, decorate)
|
||||||
|
|
|
@ -180,13 +180,13 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||||
}
|
}
|
||||||
has_non_ascii_idents = true;
|
has_non_ascii_idents = true;
|
||||||
cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
|
cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
|
||||||
lint.build("identifier contains non-ASCII characters").emit()
|
lint.build("identifier contains non-ASCII characters").emit();
|
||||||
});
|
});
|
||||||
if check_uncommon_codepoints
|
if check_uncommon_codepoints
|
||||||
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
|
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
|
cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
|
||||||
lint.build("identifier contains uncommon Unicode codepoints").emit()
|
lint.build("identifier contains uncommon Unicode codepoints").emit();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,7 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||||
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
||||||
note += &char_info;
|
note += &char_info;
|
||||||
}
|
}
|
||||||
lint.build(&message).note(¬e).note("please recheck to make sure their usages are indeed what you want").emit()
|
lint.build(&message).note(¬e).note("please recheck to make sure their usages are indeed what you want").emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||||
let method = &call.ident.name;
|
let method = &call.ident.name;
|
||||||
let message =
|
let message =
|
||||||
format!("call to `.{}()` on a reference in this situation does nothing", &method,);
|
format!("call to `.{}()` on a reference in this situation does nothing", &method,);
|
||||||
lint.build(&message).span_label(span, "unnecessary method call").note(¬e).emit()
|
lint.build(&message).span_label(span, "unnecessary method call").note(¬e).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
||||||
predicate,
|
predicate,
|
||||||
cx.tcx.def_path_str(needs_drop)
|
cx.tcx.def_path_str(needs_drop)
|
||||||
);
|
);
|
||||||
lint.build(&msg).emit()
|
lint.build(&msg).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
||||||
instead using `{}` to detect whether a type is trivially dropped",
|
instead using `{}` to detect whether a type is trivially dropped",
|
||||||
cx.tcx.def_path_str(needs_drop)
|
cx.tcx.def_path_str(needs_drop)
|
||||||
);
|
);
|
||||||
lint.build(&msg).emit()
|
lint.build(&msg).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,7 +441,7 @@ fn lint_uint_literal<'tcx>(
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
))
|
))
|
||||||
.emit()
|
.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,7 +502,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||||
hir::ExprKind::Binary(binop, ref l, ref r) => {
|
hir::ExprKind::Binary(binop, ref l, ref r) => {
|
||||||
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
|
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
|
||||||
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
|
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
|
||||||
lint.build("comparison is useless due to type limits").emit()
|
lint.build("comparison is useless due to type limits").emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1382,7 +1382,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
|
||||||
larger ({} bytes) than the next largest",
|
larger ({} bytes) than the next largest",
|
||||||
largest
|
largest
|
||||||
))
|
))
|
||||||
.emit()
|
.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||||
|
|
||||||
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
||||||
cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
|
cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
|
||||||
lint.build(&format!("unused result of type `{}`", ty)).emit()
|
lint.build(&format!("unused result of type `{}`", ty)).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,9 +368,9 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
|
||||||
} else {
|
} else {
|
||||||
lint.span_help(s.span, "use `drop` to clarify the intent");
|
lint.span_help(s.span, "use `drop` to clarify the intent");
|
||||||
}
|
}
|
||||||
lint.emit()
|
lint.emit();
|
||||||
} else {
|
} else {
|
||||||
lint.build("path statement with no effect").emit()
|
lint.build("path statement with no effect").emit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1111,7 +1111,7 @@ impl UnusedImportBraces {
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
|
cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
|
||||||
lint.build(&format!("braces around {} is unnecessary", node_name)).emit()
|
lint.build(&format!("braces around {} is unnecessary", node_name)).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1170,7 +1170,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
|
||||||
"unnecessary allocation, use `&mut` instead"
|
"unnecessary allocation, use `&mut` instead"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
lint.build(msg).emit()
|
lint.build(msg).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3695,7 +3695,7 @@ declare_lint! {
|
||||||
/// ### Explanation
|
/// ### Explanation
|
||||||
///
|
///
|
||||||
/// A duplicated attribute may erroneously originate from a copy-paste and the effect of it
|
/// A duplicated attribute may erroneously originate from a copy-paste and the effect of it
|
||||||
/// being duplicated may not be obvious or desireable.
|
/// being duplicated may not be obvious or desirable.
|
||||||
///
|
///
|
||||||
/// For instance, doubling the `#[test]` attributes registers the test to be run twice with no
|
/// For instance, doubling the `#[test]` attributes registers the test to be run twice with no
|
||||||
/// change to its environment.
|
/// change to its environment.
|
||||||
|
|
|
@ -825,11 +825,13 @@ impl<'a> CrateLoader<'a> {
|
||||||
for (_, data) in self.cstore.iter_crate_data() {
|
for (_, data) in self.cstore.iter_crate_data() {
|
||||||
if data.has_global_allocator() {
|
if data.has_global_allocator() {
|
||||||
match global_allocator {
|
match global_allocator {
|
||||||
Some(other_crate) => self.sess.err(&format!(
|
Some(other_crate) => {
|
||||||
|
self.sess.err(&format!(
|
||||||
"the `#[global_allocator]` in {} conflicts with global allocator in: {}",
|
"the `#[global_allocator]` in {} conflicts with global allocator in: {}",
|
||||||
other_crate,
|
other_crate,
|
||||||
data.name()
|
data.name()
|
||||||
)),
|
));
|
||||||
|
}
|
||||||
None => global_allocator = Some(data.name()),
|
None => global_allocator = Some(data.name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -864,7 +866,7 @@ impl<'a> CrateLoader<'a> {
|
||||||
// don't perform this validation if the session has errors, as one of
|
// don't perform this validation if the session has errors, as one of
|
||||||
// those errors may indicate a circular dependency which could cause
|
// those errors may indicate a circular dependency which could cause
|
||||||
// this to stack overflow.
|
// this to stack overflow.
|
||||||
if self.sess.has_errors() {
|
if self.sess.has_errors().is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,41 +145,49 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
||||||
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
("bundle", NativeLibKind::Static { bundle, .. }) => {
|
||||||
*bundle = Some(value);
|
*bundle = Some(value);
|
||||||
}
|
}
|
||||||
("bundle", _) => sess.span_err(
|
("bundle", _) => {
|
||||||
|
sess.span_err(
|
||||||
span,
|
span,
|
||||||
"bundle linking modifier is only compatible with \
|
"bundle linking modifier is only compatible with \
|
||||||
`static` linking kind",
|
`static` linking kind",
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
|
||||||
("verbatim", _) => lib.verbatim = Some(value),
|
("verbatim", _) => lib.verbatim = Some(value),
|
||||||
|
|
||||||
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
|
||||||
*whole_archive = Some(value);
|
*whole_archive = Some(value);
|
||||||
}
|
}
|
||||||
("whole-archive", _) => sess.span_err(
|
("whole-archive", _) => {
|
||||||
|
sess.span_err(
|
||||||
span,
|
span,
|
||||||
"whole-archive linking modifier is only compatible with \
|
"whole-archive linking modifier is only compatible with \
|
||||||
`static` linking kind",
|
`static` linking kind",
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
|
||||||
("as-needed", NativeLibKind::Dylib { as_needed })
|
("as-needed", NativeLibKind::Dylib { as_needed })
|
||||||
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
|
||||||
*as_needed = Some(value);
|
*as_needed = Some(value);
|
||||||
}
|
}
|
||||||
("as-needed", _) => sess.span_err(
|
("as-needed", _) => {
|
||||||
|
sess.span_err(
|
||||||
span,
|
span,
|
||||||
"as-needed linking modifier is only compatible with \
|
"as-needed linking modifier is only compatible with \
|
||||||
`dylib` and `framework` linking kinds",
|
`dylib` and `framework` linking kinds",
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_ => sess.span_err(
|
_ => {
|
||||||
|
sess.span_err(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
"unrecognized linking modifier `{}`, expected one \
|
"unrecognized linking modifier `{}`, expected one \
|
||||||
of: bundle, verbatim, whole-archive, as-needed",
|
of: bundle, verbatim, whole-archive, as-needed",
|
||||||
modifier
|
modifier
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -247,7 +255,9 @@ impl Collector<'_> {
|
||||||
Some(span) => {
|
Some(span) => {
|
||||||
struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit();
|
struct_span_err!(self.tcx.sess, span, E0455, "{}", msg).emit();
|
||||||
}
|
}
|
||||||
None => self.tcx.sess.err(msg),
|
None => {
|
||||||
|
self.tcx.sess.err(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if lib.cfg.is_some() && !self.tcx.features().link_cfg {
|
if lib.cfg.is_some() && !self.tcx.features().link_cfg {
|
||||||
|
|
|
@ -2,7 +2,9 @@ use std::cmp;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId};
|
use rustc_errors::{
|
||||||
|
Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed,
|
||||||
|
};
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
|
@ -220,22 +222,28 @@ impl LintExpectation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a, ()>);
|
pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
|
||||||
|
|
||||||
impl<'a> LintDiagnosticBuilder<'a> {
|
impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
|
||||||
/// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
|
/// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
|
||||||
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, ()> {
|
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a, G> {
|
||||||
self.0.set_primary_message(msg);
|
self.0.set_primary_message(msg);
|
||||||
self.0.set_is_lint();
|
self.0.set_is_lint();
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder.
|
/// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
|
||||||
pub fn new(err: DiagnosticBuilder<'a, ()>) -> LintDiagnosticBuilder<'a> {
|
pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
|
||||||
LintDiagnosticBuilder(err)
|
LintDiagnosticBuilder(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||||
|
pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
|
||||||
|
LintDiagnosticBuilder(self.0.forget_guarantee())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn explain_lint_level_source(
|
pub fn explain_lint_level_source(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
|
@ -316,7 +324,7 @@ pub fn struct_lint_level<'s, 'd>(
|
||||||
level: Level,
|
level: Level,
|
||||||
src: LintLevelSource,
|
src: LintLevelSource,
|
||||||
span: Option<MultiSpan>,
|
span: Option<MultiSpan>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + 'd,
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) + 'd,
|
||||||
) {
|
) {
|
||||||
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
||||||
// the "real" work.
|
// the "real" work.
|
||||||
|
@ -326,7 +334,7 @@ pub fn struct_lint_level<'s, 'd>(
|
||||||
level: Level,
|
level: Level,
|
||||||
src: LintLevelSource,
|
src: LintLevelSource,
|
||||||
span: Option<MultiSpan>,
|
span: Option<MultiSpan>,
|
||||||
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>,
|
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) + 'd>,
|
||||||
) {
|
) {
|
||||||
// Check for future incompatibility lints and issue a stronger warning.
|
// Check for future incompatibility lints and issue a stronger warning.
|
||||||
let future_incompatible = lint.future_incompatible;
|
let future_incompatible = lint.future_incompatible;
|
||||||
|
|
|
@ -258,7 +258,7 @@ fn late_report_deprecation(
|
||||||
let kind = tcx.def_kind(def_id).descr(def_id);
|
let kind = tcx.def_kind(def_id).descr(def_id);
|
||||||
deprecation_suggestion(&mut diag, kind, suggestion, method_span);
|
deprecation_suggestion(&mut diag, kind, suggestion, method_span);
|
||||||
}
|
}
|
||||||
diag.emit()
|
diag.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
) {
|
) {
|
||||||
let soft_handler = |lint, span, msg: &_| {
|
let soft_handler = |lint, span, msg: &_| {
|
||||||
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
|
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
|
||||||
lint.build(msg).emit()
|
lint.build(msg).emit();
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
match self.eval_stability(def_id, id, span, method_span) {
|
match self.eval_stability(def_id, id, span, method_span) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ fn print_backtrace(backtrace: &Backtrace) {
|
||||||
impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
||||||
fn from(err: ErrorHandled) -> Self {
|
fn from(err: ErrorHandled) -> Self {
|
||||||
match err {
|
match err {
|
||||||
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {
|
ErrorHandled::Reported(ErrorGuaranteed { .. }) | ErrorHandled::Linted => {
|
||||||
err_inval!(ReferencedConstant)
|
err_inval!(ReferencedConstant)
|
||||||
}
|
}
|
||||||
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
|
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
|
||||||
|
@ -160,7 +160,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
|
||||||
match self {
|
match self {
|
||||||
TooGeneric => write!(f, "encountered overly generic constant"),
|
TooGeneric => write!(f, "encountered overly generic constant"),
|
||||||
ReferencedConstant => write!(f, "referenced constant has errors"),
|
ReferencedConstant => write!(f, "referenced constant has errors"),
|
||||||
AlreadyReported(ErrorGuaranteed) => {
|
AlreadyReported(ErrorGuaranteed { .. }) => {
|
||||||
write!(f, "encountered constants with type errors, stopping evaluation")
|
write!(f, "encountered constants with type errors, stopping evaluation")
|
||||||
}
|
}
|
||||||
Layout(ref err) => write!(f, "{}", err),
|
Layout(ref err) => write!(f, "{}", err),
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
|
||||||
/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
|
/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
|
||||||
/// some global state.
|
/// some global state.
|
||||||
/// We don't actually care about this `Debug` bound (we use `Provenance::fmt` to format the entire
|
/// We don't actually care about this `Debug` bound (we use `Provenance::fmt` to format the entire
|
||||||
/// pointer), but `derive` adds some unecessary bounds.
|
/// pointer), but `derive` adds some unnecessary bounds.
|
||||||
pub trait Provenance: Copy + fmt::Debug {
|
pub trait Provenance: Copy + fmt::Debug {
|
||||||
/// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
|
/// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
|
||||||
/// If `true, ptr-to-int casts work by simply discarding the provenance.
|
/// If `true, ptr-to-int casts work by simply discarding the provenance.
|
||||||
|
|
|
@ -252,7 +252,9 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
|
/// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
|
||||||
query thir_body(key: ty::WithOptConstParam<LocalDefId>) -> (&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId) {
|
query thir_body(key: ty::WithOptConstParam<LocalDefId>)
|
||||||
|
-> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed>
|
||||||
|
{
|
||||||
// Perf tests revealed that hashing THIR is inefficient (see #85729).
|
// Perf tests revealed that hashing THIR is inefficient (see #85729).
|
||||||
no_hash
|
no_hash
|
||||||
desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
|
desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
|
||||||
|
|
|
@ -31,12 +31,12 @@ pub struct Graph {
|
||||||
pub children: DefIdMap<Children>,
|
pub children: DefIdMap<Children>,
|
||||||
|
|
||||||
/// Whether an error was emitted while constructing the graph.
|
/// Whether an error was emitted while constructing the graph.
|
||||||
pub has_errored: bool,
|
pub has_errored: Option<ErrorGuaranteed>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Graph {
|
impl Graph {
|
||||||
pub fn new() -> Graph {
|
pub fn new() -> Graph {
|
||||||
Graph { parent: Default::default(), children: Default::default(), has_errored: false }
|
Graph { parent: Default::default(), children: Default::default(), has_errored: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The parent of a given impl, which is the `DefId` of the trait when the
|
/// The parent of a given impl, which is the `DefId` of the trait when the
|
||||||
|
@ -246,8 +246,10 @@ pub fn ancestors<'tcx>(
|
||||||
) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
|
) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
|
||||||
let specialization_graph = tcx.specialization_graph_of(trait_def_id);
|
let specialization_graph = tcx.specialization_graph_of(trait_def_id);
|
||||||
|
|
||||||
if specialization_graph.has_errored || tcx.type_of(start_from_impl).references_error() {
|
if let Some(reported) = specialization_graph.has_errored {
|
||||||
Err(ErrorGuaranteed)
|
Err(reported)
|
||||||
|
} else if let Some(reported) = tcx.type_of(start_from_impl).error_reported() {
|
||||||
|
Err(reported)
|
||||||
} else {
|
} else {
|
||||||
Ok(Ancestors {
|
Ok(Ancestors {
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
|
|
|
@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_data_structures::stable_hasher::HashingControls;
|
use rustc_data_structures::stable_hasher::HashingControls;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -453,7 +452,7 @@ impl<'tcx> AdtDef<'tcx> {
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let msg = match err {
|
let msg = match err {
|
||||||
ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted => {
|
ErrorHandled::Reported(_) | ErrorHandled::Linted => {
|
||||||
"enum discriminant evaluation failed"
|
"enum discriminant evaluation failed"
|
||||||
}
|
}
|
||||||
ErrorHandled::TooGeneric => "enum discriminant depends on generics",
|
ErrorHandled::TooGeneric => "enum discriminant depends on generics",
|
||||||
|
|
|
@ -264,7 +264,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
if let Some(val) = self.val().try_eval(tcx, param_env) {
|
if let Some(val) = self.val().try_eval(tcx, param_env) {
|
||||||
match val {
|
match val {
|
||||||
Ok(val) => Const::from_value(tcx, val, self.ty()),
|
Ok(val) => Const::from_value(tcx, val, self.ty()),
|
||||||
Err(ErrorGuaranteed) => tcx.const_error(self.ty()),
|
Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self
|
self
|
||||||
|
|
|
@ -91,7 +91,10 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
|
||||||
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
|
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
#[derive(TyEncodable, TyDecodable, HashStable)]
|
#[derive(TyEncodable, TyDecodable, HashStable)]
|
||||||
pub struct DelaySpanBugEmitted(());
|
pub struct DelaySpanBugEmitted {
|
||||||
|
pub reported: ErrorGuaranteed,
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||||
|
|
||||||
|
@ -1236,8 +1239,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// ensure it gets used.
|
/// ensure it gets used.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
|
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
|
||||||
self.sess.delay_span_bug(span, msg);
|
let reported = self.sess.delay_span_bug(span, msg);
|
||||||
self.mk_ty(Error(DelaySpanBugEmitted(())))
|
self.mk_ty(Error(DelaySpanBugEmitted { reported, _priv: () }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like [TyCtxt::ty_error] but for constants.
|
/// Like [TyCtxt::ty_error] but for constants.
|
||||||
|
@ -1258,8 +1261,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
span: S,
|
span: S,
|
||||||
msg: &str,
|
msg: &str,
|
||||||
) -> Const<'tcx> {
|
) -> Const<'tcx> {
|
||||||
self.sess.delay_span_bug(span, msg);
|
let reported = self.sess.delay_span_bug(span, msg);
|
||||||
self.mk_const(ty::ConstS { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
|
self.mk_const(ty::ConstS {
|
||||||
|
val: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }),
|
||||||
|
ty,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
|
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
|
||||||
|
@ -2733,7 +2739,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
span: impl Into<MultiSpan>,
|
span: impl Into<MultiSpan>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
||||||
struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
|
struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
|
||||||
|
@ -2743,7 +2749,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self,
|
self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
id: HirId,
|
id: HirId,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>),
|
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||||
) {
|
) {
|
||||||
let (level, src) = self.lint_level_at_node(lint, id);
|
let (level, src) = self.lint_level_at_node(lint, id);
|
||||||
struct_lint_level(self.sess, lint, level, src, None, decorate);
|
struct_lint_level(self.sess, lint, level, src, None, decorate);
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
|
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
|
||||||
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
@ -151,6 +152,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||||
fn references_error(&self) -> bool {
|
fn references_error(&self) -> bool {
|
||||||
self.has_type_flags(TypeFlags::HAS_ERROR)
|
self.has_type_flags(TypeFlags::HAS_ERROR)
|
||||||
}
|
}
|
||||||
|
fn error_reported(&self) -> Option<ErrorGuaranteed> {
|
||||||
|
if self.references_error() {
|
||||||
|
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
fn has_param_types_or_consts(&self) -> bool {
|
fn has_param_types_or_consts(&self) -> bool {
|
||||||
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
|
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,7 +337,7 @@ rustc_query_append! { [define_callbacks!][<'tcx>] }
|
||||||
mod sealed {
|
mod sealed {
|
||||||
use super::{DefId, LocalDefId};
|
use super::{DefId, LocalDefId};
|
||||||
|
|
||||||
/// An analogue of the `Into` trait that's intended only for query paramaters.
|
/// An analogue of the `Into` trait that's intended only for query parameters.
|
||||||
///
|
///
|
||||||
/// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
|
/// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
|
||||||
/// user call `to_def_id` to convert between them everywhere else.
|
/// user call `to_def_id` to convert between them everywhere else.
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn ty_slice_as_generic_args<'a, 'tcx>(ts: &'a [Ty<'tcx>]) -> &'a [GenericArg
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> List<Ty<'tcx>> {
|
impl<'tcx> List<Ty<'tcx>> {
|
||||||
/// Allows to freely switch betwen `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
|
/// Allows to freely switch between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
|
||||||
///
|
///
|
||||||
/// As lists are interned, `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>` have
|
/// As lists are interned, `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>` have
|
||||||
/// be interned together, see `intern_type_list` for more details.
|
/// be interned together, see `intern_type_list` for more details.
|
||||||
|
|
|
@ -486,7 +486,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the `DefId`, returns the `DefId` of the innermost item that
|
/// Given the `DefId`, returns the `DefId` of the innermost item that
|
||||||
/// has its own type-checking context or "inference enviornment".
|
/// has its own type-checking context or "inference environment".
|
||||||
///
|
///
|
||||||
/// For example, a closure has its own `DefId`, but it is type-checked
|
/// For example, a closure has its own `DefId`, but it is type-checked
|
||||||
/// with the containing item. Similarly, an inline const block has its
|
/// with the containing item. Similarly, an inline const block has its
|
||||||
|
|
|
@ -118,7 +118,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = tcx.hir().body(body_id);
|
let body = tcx.hir().body(body_id);
|
||||||
let (thir, expr) = tcx.thir_body(def);
|
let (thir, expr) = tcx
|
||||||
|
.thir_body(def)
|
||||||
|
.unwrap_or_else(|_| (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)));
|
||||||
// We ran all queries that depended on THIR at the beginning
|
// We ran all queries that depended on THIR at the beginning
|
||||||
// of `mir_build`, so now we can steal it
|
// of `mir_build`, so now we can steal it
|
||||||
let thir = thir.steal();
|
let thir = thir.steal();
|
||||||
|
@ -229,7 +231,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||||
|
|
||||||
let return_ty = typeck_results.node_type(id);
|
let return_ty = typeck_results.node_type(id);
|
||||||
|
|
||||||
let (thir, expr) = tcx.thir_body(def);
|
let (thir, expr) = tcx
|
||||||
|
.thir_body(def)
|
||||||
|
.unwrap_or_else(|_| (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0)));
|
||||||
// We ran all queries that depended on THIR at the beginning
|
// We ran all queries that depended on THIR at the beginning
|
||||||
// of `mir_build`, so now we can steal it
|
// of `mir_build`, so now we can steal it
|
||||||
let thir = thir.steal();
|
let thir = thir.steal();
|
||||||
|
|
|
@ -405,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
ty::WithOptConstParam::unknown(closure_id)
|
ty::WithOptConstParam::unknown(closure_id)
|
||||||
};
|
};
|
||||||
let (closure_thir, expr) = self.tcx.thir_body(closure_def);
|
let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
|
||||||
|
(self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
|
||||||
|
});
|
||||||
let closure_thir = &closure_thir.borrow();
|
let closure_thir = &closure_thir.borrow();
|
||||||
let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
|
let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
|
||||||
let mut closure_visitor =
|
let mut closure_visitor =
|
||||||
|
@ -606,7 +608,10 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (thir, expr) = tcx.thir_body(def);
|
let (thir, expr) = match tcx.thir_body(def) {
|
||||||
|
Ok(body) => body,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
let thir = &thir.borrow();
|
let thir = &thir.borrow();
|
||||||
// If `thir` is empty, a type error occurred, skip this body.
|
// If `thir` is empty, a type error occurred, skip this body.
|
||||||
if thir.exprs.is_empty() {
|
if thir.exprs.is_empty() {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::thir::util::UserAnnotatedTyHelpers;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::steal::Steal;
|
use rustc_data_structures::steal::Steal;
|
||||||
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
|
@ -20,22 +21,25 @@ use rustc_span::Span;
|
||||||
crate fn thir_body<'tcx>(
|
crate fn thir_body<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
owner_def: ty::WithOptConstParam<LocalDefId>,
|
owner_def: ty::WithOptConstParam<LocalDefId>,
|
||||||
) -> (&'tcx Steal<Thir<'tcx>>, ExprId) {
|
) -> Result<(&'tcx Steal<Thir<'tcx>>, ExprId), ErrorGuaranteed> {
|
||||||
let hir = tcx.hir();
|
let hir = tcx.hir();
|
||||||
let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did)));
|
let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did)));
|
||||||
let mut cx = Cx::new(tcx, owner_def);
|
let mut cx = Cx::new(tcx, owner_def);
|
||||||
if cx.typeck_results.tainted_by_errors.is_some() {
|
if let Some(reported) = cx.typeck_results.tainted_by_errors {
|
||||||
return (tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0));
|
return Err(reported);
|
||||||
}
|
}
|
||||||
let expr = cx.mirror_expr(&body.value);
|
let expr = cx.mirror_expr(&body.value);
|
||||||
(tcx.alloc_steal_thir(cx.thir), expr)
|
Ok((tcx.alloc_steal_thir(cx.thir), expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn thir_tree<'tcx>(
|
crate fn thir_tree<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
owner_def: ty::WithOptConstParam<LocalDefId>,
|
owner_def: ty::WithOptConstParam<LocalDefId>,
|
||||||
) -> String {
|
) -> String {
|
||||||
format!("{:#?}", thir_body(tcx, owner_def).0.steal())
|
match thir_body(tcx, owner_def) {
|
||||||
|
Ok((thir, _)) => format!("{:#?}", thir.steal()),
|
||||||
|
Err(_) => "error".into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cx<'tcx> {
|
struct Cx<'tcx> {
|
||||||
|
|
|
@ -194,7 +194,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
self.id,
|
self.id,
|
||||||
self.span,
|
self.span,
|
||||||
|lint| lint.build(&msg).emit(),
|
|lint| {
|
||||||
|
lint.build(&msg).emit();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -272,7 +274,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
|
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| lint.build("floating-point types cannot be used in patterns").emit(),
|
|lint| {
|
||||||
|
lint.build("floating-point types cannot be used in patterns").emit();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
|
@ -284,7 +288,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
tcx.sess.span_err(span, msg);
|
tcx.sess.span_err(span, msg);
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(span, msg)
|
tcx.sess.delay_span_bug(span, msg);
|
||||||
}
|
}
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
|
@ -301,7 +305,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
tcx.sess.span_err(self.span, &msg);
|
tcx.sess.span_err(self.span, &msg);
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(self.span, &msg)
|
tcx.sess.delay_span_bug(self.span, &msg);
|
||||||
}
|
}
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
|
@ -331,7 +335,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
cv.ty(),
|
cv.ty(),
|
||||||
cv.ty(),
|
cv.ty(),
|
||||||
);
|
);
|
||||||
lint.build(&msg).emit()
|
lint.build(&msg).emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -356,7 +360,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
tcx.sess.span_err(span, &msg);
|
tcx.sess.span_err(span, &msg);
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(span, &msg)
|
tcx.sess.delay_span_bug(span, &msg);
|
||||||
}
|
}
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
|
@ -393,7 +397,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
tcx.sess.span_err(span, &msg);
|
tcx.sess.span_err(span, &msg);
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(span, &msg)
|
tcx.sess.delay_span_bug(span, &msg);
|
||||||
}
|
}
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
|
@ -471,7 +475,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
self.id,
|
self.id,
|
||||||
self.span,
|
self.span,
|
||||||
|lint| lint.build(&msg).emit(),
|
|lint| {lint.build(&msg).emit();},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
|
@ -482,7 +486,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
tcx.sess.span_err(span, &msg);
|
tcx.sess.span_err(span, &msg);
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(span, &msg)
|
tcx.sess.delay_span_bug(span, &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
|
@ -523,7 +527,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => {
|
ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => {
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
}
|
}
|
||||||
// FIXME: these can have very suprising behaviour where optimization levels or other
|
// FIXME: these can have very surprising behaviour where optimization levels or other
|
||||||
// compilation choices change the runtime behaviour of the match.
|
// compilation choices change the runtime behaviour of the match.
|
||||||
// See https://github.com/rust-lang/rust/issues/70861 for examples.
|
// See https://github.com/rust-lang/rust/issues/70861 for examples.
|
||||||
ty::FnPtr(..) | ty::RawPtr(..) => {
|
ty::FnPtr(..) | ty::RawPtr(..) => {
|
||||||
|
@ -539,7 +543,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| lint.build(&msg).emit(),
|
|lint| {
|
||||||
|
lint.build(&msg).emit();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
|
@ -550,7 +556,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
tcx.sess.span_err(span, &msg);
|
tcx.sess.span_err(span, &msg);
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(span, &msg)
|
tcx.sess.delay_span_bug(span, &msg);
|
||||||
}
|
}
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
|
@ -575,7 +581,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| lint.build(&msg).emit(),
|
|lint| {
|
||||||
|
lint.build(&msg).emit();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|
||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
const_item: DefId,
|
const_item: DefId,
|
||||||
location: Location,
|
location: Location,
|
||||||
decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b, ()>,
|
decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) -> DiagnosticBuilder<'b, ()>,
|
||||||
) {
|
) {
|
||||||
// Don't lint on borrowing/assigning when a dereference is involved.
|
// Don't lint on borrowing/assigning when a dereference is involved.
|
||||||
// If we 'leave' the temporary via a dereference, we must
|
// If we 'leave' the temporary via a dereference, we must
|
||||||
|
@ -88,7 +88,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|
||||||
|lint| {
|
|lint| {
|
||||||
decorate(lint)
|
decorate(lint)
|
||||||
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
|
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
|
||||||
.emit()
|
.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
does not derive Copy (error E0133)"
|
does not derive Copy (error E0133)"
|
||||||
.to_string()
|
.to_string()
|
||||||
};
|
};
|
||||||
lint.build(&message).emit()
|
lint.build(&message).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
|
||||||
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
|
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
|
||||||
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
|
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
|
||||||
)
|
)
|
||||||
.emit()
|
.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
|
||||||
// temporary holding the static pointer to avoid duplicate errors
|
// temporary holding the static pointer to avoid duplicate errors
|
||||||
// <https://github.com/rust-lang/rust/pull/78068#issuecomment-731753506>.
|
// <https://github.com/rust-lang/rust/pull/78068#issuecomment-731753506>.
|
||||||
if decl.internal && place.projection.first() == Some(&ProjectionElem::Deref) {
|
if decl.internal && place.projection.first() == Some(&ProjectionElem::Deref) {
|
||||||
// If the projection root is an artifical local that we introduced when
|
// If the projection root is an artificial local that we introduced when
|
||||||
// desugaring `static`, give a more specific error message
|
// desugaring `static`, give a more specific error message
|
||||||
// (avoid the general "raw pointer" clause below, that would only be confusing).
|
// (avoid the general "raw pointer" clause below, that would only be confusing).
|
||||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
|
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Consta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut eligable_locals = Vec::new();
|
let mut eligible_locals = Vec::new();
|
||||||
for (local, mutating_uses) in visitor.local_mutating_uses.drain_enumerated(..) {
|
for (local, mutating_uses) in visitor.local_mutating_uses.drain_enumerated(..) {
|
||||||
if mutating_uses != 1 || !locals_to_debuginfo.contains(local) {
|
if mutating_uses != 1 || !locals_to_debuginfo.contains(local) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -78,13 +78,13 @@ fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Consta
|
||||||
&bb.statements[location.statement_index].kind
|
&bb.statements[location.statement_index].kind
|
||||||
{
|
{
|
||||||
if let Some(local) = p.as_local() {
|
if let Some(local) = p.as_local() {
|
||||||
eligable_locals.push((local, *c));
|
eligible_locals.push((local, *c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eligable_locals
|
eligible_locals
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visitor<'_> for LocalUseVisitor {
|
impl Visitor<'_> for LocalUseVisitor {
|
||||||
|
|
|
@ -538,7 +538,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
||||||
let mut err = lint.build(message);
|
let mut err = lint.build(message);
|
||||||
err.span_label(source_info.span, format!("{:?}", panic));
|
err.span_label(source_info.span, format!("{:?}", panic));
|
||||||
err.emit()
|
err.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,7 +359,7 @@ fn verify_candidate_branch<'tcx>(
|
||||||
if branch.statements.len() != 1 {
|
if branch.statements.len() != 1 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// ...assign the descriminant of `place` in that statement
|
// ...assign the discriminant of `place` in that statement
|
||||||
let StatementKind::Assign(boxed) = &branch.statements[0].kind else {
|
let StatementKind::Assign(boxed) = &branch.statements[0].kind else {
|
||||||
return false
|
return false
|
||||||
};
|
};
|
||||||
|
|
|
@ -362,7 +362,7 @@ fn optimization_applies<'tcx>(
|
||||||
return false;
|
return false;
|
||||||
} else if last_assigned_to != opt_info.local_tmp_s1 {
|
} else if last_assigned_to != opt_info.local_tmp_s1 {
|
||||||
trace!(
|
trace!(
|
||||||
"NO: end of assignemnt chain does not match written enum temp: {:?} != {:?}",
|
"NO: end of assignment chain does not match written enum temp: {:?} != {:?}",
|
||||||
last_assigned_to,
|
last_assigned_to,
|
||||||
opt_info.local_tmp_s1
|
opt_info.local_tmp_s1
|
||||||
);
|
);
|
||||||
|
|
|
@ -180,7 +180,7 @@
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
|
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
|
||||||
use rustc_errors::{ErrorGuaranteed, FatalError};
|
use rustc_errors::FatalError;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||||
|
@ -716,9 +716,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
match self.tcx.const_eval_resolve(param_env, ct, None) {
|
match self.tcx.const_eval_resolve(param_env, ct, None) {
|
||||||
// The `monomorphize` call should have evaluated that constant already.
|
// The `monomorphize` call should have evaluated that constant already.
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted) => {
|
Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(ErrorHandled::TooGeneric) => span_bug!(
|
Err(ErrorHandled::TooGeneric) => span_bug!(
|
||||||
self.body.source_info(location).span,
|
self.body.source_info(location).span,
|
||||||
"collection encountered polymorphic constant: {:?}",
|
"collection encountered polymorphic constant: {:?}",
|
||||||
|
@ -750,7 +748,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
substituted_constant,
|
substituted_constant,
|
||||||
val
|
val
|
||||||
),
|
),
|
||||||
Err(ErrorHandled::Reported(ErrorGuaranteed) | ErrorHandled::Linted) => {}
|
Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => {}
|
||||||
Err(ErrorHandled::TooGeneric) => span_bug!(
|
Err(ErrorHandled::TooGeneric) => span_bug!(
|
||||||
self.body.source_info(location).span,
|
self.body.source_info(location).span,
|
||||||
"collection encountered polymorphic constant: {}",
|
"collection encountered polymorphic constant: {}",
|
||||||
|
@ -864,7 +862,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
|
let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
|
||||||
err.span_label(source_info.span, "value moved from here");
|
err.span_label(source_info.span, "value moved from here");
|
||||||
err.emit()
|
err.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ pub(crate) fn emit_unescape_error(
|
||||||
diag.emit();
|
diag.emit();
|
||||||
}
|
}
|
||||||
EscapeError::TooShortHexEscape => {
|
EscapeError::TooShortHexEscape => {
|
||||||
handler.span_err(span, "numeric character escape is too short")
|
handler.span_err(span, "numeric character escape is too short");
|
||||||
}
|
}
|
||||||
EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
|
EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
|
||||||
let (c, span) = last_char();
|
let (c, span) = last_char();
|
||||||
|
|
|
@ -151,7 +151,7 @@ impl<'a> Parser<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
attr_type: OuterAttributeType,
|
attr_type: OuterAttributeType,
|
||||||
) -> Option<Span> {
|
) -> Option<Span> {
|
||||||
let mut snapshot = self.clone();
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||||
let lo = span.lo()
|
let lo = span.lo()
|
||||||
+ BytePos(match attr_type {
|
+ BytePos(match attr_type {
|
||||||
OuterAttributeType::Attribute => 1,
|
OuterAttributeType::Attribute => 1,
|
||||||
|
|
|
@ -5,6 +5,7 @@ use super::{
|
||||||
SemiColonMode, SeqSep, TokenExpectType, TokenType,
|
SemiColonMode, SeqSep, TokenExpectType, TokenType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::lexer::UnmatchedBrace;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
|
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
|
||||||
|
@ -21,6 +22,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult};
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, Ident};
|
use rustc_span::symbol::{kw, Ident};
|
||||||
use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
|
use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use std::mem::take;
|
use std::mem::take;
|
||||||
|
|
||||||
|
@ -154,6 +156,28 @@ impl AttemptLocalParseRecovery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SnapshotParser is used to create a snapshot of the parser
|
||||||
|
// without causing duplicate errors being emitted when the `Parser`
|
||||||
|
// is dropped.
|
||||||
|
pub(super) struct SnapshotParser<'a> {
|
||||||
|
parser: Parser<'a>,
|
||||||
|
unclosed_delims: Vec<UnmatchedBrace>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Deref for SnapshotParser<'a> {
|
||||||
|
type Target = Parser<'a>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.parser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DerefMut for SnapshotParser<'a> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.parser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub(super) fn span_err<S: Into<MultiSpan>>(
|
pub(super) fn span_err<S: Into<MultiSpan>>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -179,6 +203,25 @@ impl<'a> Parser<'a> {
|
||||||
&self.sess.span_diagnostic
|
&self.sess.span_diagnostic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Relace `self` with `snapshot.parser` and extend `unclosed_delims` with `snapshot.unclosed_delims`.
|
||||||
|
/// This is to avoid losing unclosed delims errors `create_snapshot_for_diagnostic` clears.
|
||||||
|
pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) {
|
||||||
|
*self = snapshot.parser;
|
||||||
|
self.unclosed_delims.extend(snapshot.unclosed_delims.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a snapshot of the `Parser`.
|
||||||
|
pub(super) fn create_snapshot_for_diagnostic(&self) -> SnapshotParser<'a> {
|
||||||
|
let mut snapshot = self.clone();
|
||||||
|
let unclosed_delims = self.unclosed_delims.clone();
|
||||||
|
// Clear `unclosed_delims` in snapshot to avoid
|
||||||
|
// duplicate errors being emitted when the `Parser`
|
||||||
|
// is dropped (which may or may not happen, depending
|
||||||
|
// if the parsing the snapshot is created for is successful)
|
||||||
|
snapshot.unclosed_delims.clear();
|
||||||
|
SnapshotParser { parser: snapshot, unclosed_delims }
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
|
pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
|
||||||
self.sess.source_map().span_to_snippet(span)
|
self.sess.source_map().span_to_snippet(span)
|
||||||
}
|
}
|
||||||
|
@ -438,7 +481,7 @@ impl<'a> Parser<'a> {
|
||||||
// fn foo() -> Foo {
|
// fn foo() -> Foo {
|
||||||
// field: value,
|
// field: value,
|
||||||
// }
|
// }
|
||||||
let mut snapshot = self.clone();
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||||
let path =
|
let path =
|
||||||
Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
|
Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
|
||||||
let struct_expr = snapshot.parse_struct_expr(None, path, AttrVec::new(), false);
|
let struct_expr = snapshot.parse_struct_expr(None, path, AttrVec::new(), false);
|
||||||
|
@ -464,7 +507,7 @@ impl<'a> Parser<'a> {
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
let mut tail = self.mk_block(
|
let mut tail = self.mk_block(
|
||||||
vec![self.mk_stmt_err(expr.span)],
|
vec![self.mk_stmt_err(expr.span)],
|
||||||
s,
|
s,
|
||||||
|
@ -678,7 +721,7 @@ impl<'a> Parser<'a> {
|
||||||
/// angle brackets.
|
/// angle brackets.
|
||||||
pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
|
pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
|
||||||
if token::ModSep == self.token.kind && segment.args.is_none() {
|
if token::ModSep == self.token.kind && segment.args.is_none() {
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
self.bump();
|
self.bump();
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
match self.parse_angle_args(None) {
|
match self.parse_angle_args(None) {
|
||||||
|
@ -712,14 +755,14 @@ impl<'a> Parser<'a> {
|
||||||
.emit();
|
.emit();
|
||||||
} else {
|
} else {
|
||||||
// This doesn't look like an invalid turbofish, can't recover parse state.
|
// This doesn't look like an invalid turbofish, can't recover parse state.
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// We couldn't parse generic parameters, unlikely to be a turbofish. Rely on
|
// We couldn't parse generic parameters, unlikely to be a turbofish. Rely on
|
||||||
// generic parse error instead.
|
// generic parse error instead.
|
||||||
err.cancel();
|
err.cancel();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -825,7 +868,7 @@ impl<'a> Parser<'a> {
|
||||||
// `x == y < z`
|
// `x == y < z`
|
||||||
(BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
|
(BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
|
||||||
// Consume `z`/outer-op-rhs.
|
// Consume `z`/outer-op-rhs.
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match self.parse_expr() {
|
match self.parse_expr() {
|
||||||
Ok(r2) => {
|
Ok(r2) => {
|
||||||
// We are sure that outer-op-rhs could be consumed, the suggestion is
|
// We are sure that outer-op-rhs could be consumed, the suggestion is
|
||||||
|
@ -835,14 +878,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Err(expr_err) => {
|
Err(expr_err) => {
|
||||||
expr_err.cancel();
|
expr_err.cancel();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `x > y == z`
|
// `x > y == z`
|
||||||
(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, AssocOp::Equal) => {
|
(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, AssocOp::Equal) => {
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
// At this point it is always valid to enclose the lhs in parentheses, no
|
// At this point it is always valid to enclose the lhs in parentheses, no
|
||||||
// further checks are necessary.
|
// further checks are necessary.
|
||||||
match self.parse_expr() {
|
match self.parse_expr() {
|
||||||
|
@ -852,7 +895,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Err(expr_err) => {
|
Err(expr_err) => {
|
||||||
expr_err.cancel();
|
expr_err.cancel();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -917,7 +960,7 @@ impl<'a> Parser<'a> {
|
||||||
|| outer_op.node == AssocOp::Greater
|
|| outer_op.node == AssocOp::Greater
|
||||||
{
|
{
|
||||||
if outer_op.node == AssocOp::Less {
|
if outer_op.node == AssocOp::Less {
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
self.bump();
|
self.bump();
|
||||||
// So far we have parsed `foo<bar<`, consume the rest of the type args.
|
// So far we have parsed `foo<bar<`, consume the rest of the type args.
|
||||||
let modifiers =
|
let modifiers =
|
||||||
|
@ -929,7 +972,7 @@ impl<'a> Parser<'a> {
|
||||||
{
|
{
|
||||||
// We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
|
// We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
|
||||||
// parser and bail out.
|
// parser and bail out.
|
||||||
*self = snapshot.clone();
|
self.restore_snapshot(snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return if token::ModSep == self.token.kind {
|
return if token::ModSep == self.token.kind {
|
||||||
|
@ -937,7 +980,7 @@ impl<'a> Parser<'a> {
|
||||||
// `foo< bar >::`
|
// `foo< bar >::`
|
||||||
suggest(&mut err);
|
suggest(&mut err);
|
||||||
|
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
self.bump(); // `::`
|
self.bump(); // `::`
|
||||||
|
|
||||||
// Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
|
// Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
|
||||||
|
@ -954,7 +997,7 @@ impl<'a> Parser<'a> {
|
||||||
expr_err.cancel();
|
expr_err.cancel();
|
||||||
// Not entirely sure now, but we bubble the error up with the
|
// Not entirely sure now, but we bubble the error up with the
|
||||||
// suggestion.
|
// suggestion.
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1051,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume_fn_args(&mut self) -> Result<(), ()> {
|
fn consume_fn_args(&mut self) -> Result<(), ()> {
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
self.bump(); // `(`
|
self.bump(); // `(`
|
||||||
|
|
||||||
// Consume the fn call arguments.
|
// Consume the fn call arguments.
|
||||||
|
@ -1018,7 +1061,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
if self.token.kind == token::Eof {
|
if self.token.kind == token::Eof {
|
||||||
// Not entirely sure that what we consumed were fn arguments, rollback.
|
// Not entirely sure that what we consumed were fn arguments, rollback.
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
// 99% certain that the suggestion is correct, continue parsing.
|
// 99% certain that the suggestion is correct, continue parsing.
|
||||||
|
@ -1959,12 +2002,12 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
|
fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
let param = match self.parse_const_param(vec![]) {
|
let param = match self.parse_const_param(vec![]) {
|
||||||
Ok(param) => param,
|
Ok(param) => param,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
err.cancel();
|
err.cancel();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2056,7 +2099,7 @@ impl<'a> Parser<'a> {
|
||||||
// We perform these checks and early return to avoid taking a snapshot unnecessarily.
|
// We perform these checks and early return to avoid taking a snapshot unnecessarily.
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
if is_op_or_dot {
|
if is_op_or_dot {
|
||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
|
@ -2101,7 +2144,7 @@ impl<'a> Parser<'a> {
|
||||||
err.cancel();
|
err.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2161,7 +2204,7 @@ impl<'a> Parser<'a> {
|
||||||
let span = self.token.span;
|
let span = self.token.span;
|
||||||
// We only emit "unexpected `:`" error here if we can successfully parse the
|
// We only emit "unexpected `:`" error here if we can successfully parse the
|
||||||
// whole pattern correctly in that case.
|
// whole pattern correctly in that case.
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
|
|
||||||
// Create error for "unexpected `:`".
|
// Create error for "unexpected `:`".
|
||||||
match self.expected_one_of_not_found(&[], &[]) {
|
match self.expected_one_of_not_found(&[], &[]) {
|
||||||
|
@ -2173,7 +2216,7 @@ impl<'a> Parser<'a> {
|
||||||
// reasonable error.
|
// reasonable error.
|
||||||
inner_err.cancel();
|
inner_err.cancel();
|
||||||
err.cancel();
|
err.cancel();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
}
|
}
|
||||||
Ok(mut pat) => {
|
Ok(mut pat) => {
|
||||||
// We've parsed the rest of the pattern.
|
// We've parsed the rest of the pattern.
|
||||||
|
@ -2252,7 +2295,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Carry on as if we had not done anything. This should be unreachable.
|
// Carry on as if we had not done anything. This should be unreachable.
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
first_pat
|
first_pat
|
||||||
|
|
|
@ -703,7 +703,7 @@ impl<'a> Parser<'a> {
|
||||||
ExprKind::Path(None, ast::Path { segments, .. }),
|
ExprKind::Path(None, ast::Path { segments, .. }),
|
||||||
TokenKind::Ident(kw::For | kw::Loop | kw::While, false),
|
TokenKind::Ident(kw::For | kw::Loop | kw::While, false),
|
||||||
) if segments.len() == 1 => {
|
) if segments.len() == 1 => {
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
let label = Label {
|
let label = Label {
|
||||||
ident: Ident::from_str_and_span(
|
ident: Ident::from_str_and_span(
|
||||||
&format!("'{}", segments[0].ident),
|
&format!("'{}", segments[0].ident),
|
||||||
|
@ -725,7 +725,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
err.cancel();
|
err.cancel();
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1885,7 +1885,7 @@ impl<'a> Parser<'a> {
|
||||||
lo: Span,
|
lo: Span,
|
||||||
attrs: AttrVec,
|
attrs: AttrVec,
|
||||||
) -> Option<P<Expr>> {
|
) -> Option<P<Expr>> {
|
||||||
let mut snapshot = self.clone();
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
|
match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
|
||||||
Ok(arr) => {
|
Ok(arr) => {
|
||||||
let hi = snapshot.prev_token.span;
|
let hi = snapshot.prev_token.span;
|
||||||
|
@ -1901,7 +1901,7 @@ impl<'a> Parser<'a> {
|
||||||
.note("to define an array, one would use square brackets instead of curly braces")
|
.note("to define an array, one would use square brackets instead of curly braces")
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
Some(self.mk_expr_err(arr.span))
|
Some(self.mk_expr_err(arr.span))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -2369,7 +2369,7 @@ impl<'a> Parser<'a> {
|
||||||
if self.token.kind != token::Semi {
|
if self.token.kind != token::Semi {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let start_snapshot = self.clone();
|
let start_snapshot = self.create_snapshot_for_diagnostic();
|
||||||
let semi_sp = self.token.span;
|
let semi_sp = self.token.span;
|
||||||
self.bump(); // `;`
|
self.bump(); // `;`
|
||||||
let mut stmts =
|
let mut stmts =
|
||||||
|
@ -2417,15 +2417,15 @@ impl<'a> Parser<'a> {
|
||||||
return Some(err(self, stmts));
|
return Some(err(self, stmts));
|
||||||
}
|
}
|
||||||
if self.token.kind == token::Comma {
|
if self.token.kind == token::Comma {
|
||||||
*self = start_snapshot;
|
self.restore_snapshot(start_snapshot);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let pre_pat_snapshot = self.clone();
|
let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match self.parse_pat_no_top_alt(None) {
|
match self.parse_pat_no_top_alt(None) {
|
||||||
Ok(_pat) => {
|
Ok(_pat) => {
|
||||||
if self.token.kind == token::FatArrow {
|
if self.token.kind == token::FatArrow {
|
||||||
// Reached arm end.
|
// Reached arm end.
|
||||||
*self = pre_pat_snapshot;
|
self.restore_snapshot(pre_pat_snapshot);
|
||||||
return Some(err(self, stmts));
|
return Some(err(self, stmts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2434,21 +2434,21 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*self = pre_pat_snapshot;
|
self.restore_snapshot(pre_pat_snapshot);
|
||||||
match self.parse_stmt_without_recovery(true, ForceCollect::No) {
|
match self.parse_stmt_without_recovery(true, ForceCollect::No) {
|
||||||
// Consume statements for as long as possible.
|
// Consume statements for as long as possible.
|
||||||
Ok(Some(stmt)) => {
|
Ok(Some(stmt)) => {
|
||||||
stmts.push(stmt);
|
stmts.push(stmt);
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
*self = start_snapshot;
|
self.restore_snapshot(start_snapshot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// We couldn't parse either yet another statement missing it's
|
// We couldn't parse either yet another statement missing it's
|
||||||
// enclosing block nor the next arm's pattern or closing brace.
|
// enclosing block nor the next arm's pattern or closing brace.
|
||||||
Err(stmt_err) => {
|
Err(stmt_err) => {
|
||||||
stmt_err.cancel();
|
stmt_err.cancel();
|
||||||
*self = start_snapshot;
|
self.restore_snapshot(start_snapshot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,10 +212,10 @@ impl<'a> Parser<'a> {
|
||||||
if let Err(mut e) = self.expect_semi() {
|
if let Err(mut e) = self.expect_semi() {
|
||||||
match tree.kind {
|
match tree.kind {
|
||||||
UseTreeKind::Glob => {
|
UseTreeKind::Glob => {
|
||||||
e.note("the wildcard token must be last on the path").emit();
|
e.note("the wildcard token must be last on the path");
|
||||||
}
|
}
|
||||||
UseTreeKind::Nested(..) => {
|
UseTreeKind::Nested(..) => {
|
||||||
e.note("glob-like brace syntax must be last on the path").emit();
|
e.note("glob-like brace syntax must be last on the path");
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -999,11 +999,33 @@ impl<'a> Parser<'a> {
|
||||||
attrs: &mut Vec<Attribute>,
|
attrs: &mut Vec<Attribute>,
|
||||||
unsafety: Unsafe,
|
unsafety: Unsafe,
|
||||||
) -> PResult<'a, ItemInfo> {
|
) -> PResult<'a, ItemInfo> {
|
||||||
|
let sp_start = self.prev_token.span;
|
||||||
let abi = self.parse_abi(); // ABI?
|
let abi = self.parse_abi(); // ABI?
|
||||||
let items = self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?;
|
match self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No)) {
|
||||||
|
Ok(items) => {
|
||||||
let module = ast::ForeignMod { unsafety, abi, items };
|
let module = ast::ForeignMod { unsafety, abi, items };
|
||||||
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
|
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
|
||||||
}
|
}
|
||||||
|
Err(mut err) => {
|
||||||
|
let current_qual_sp = self.prev_token.span;
|
||||||
|
let current_qual_sp = current_qual_sp.to(sp_start);
|
||||||
|
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
|
||||||
|
if err.message() == "expected `{`, found keyword `unsafe`" {
|
||||||
|
let invalid_qual_sp = self.token.uninterpolated_span();
|
||||||
|
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
|
||||||
|
|
||||||
|
err.span_suggestion(
|
||||||
|
current_qual_sp.to(invalid_qual_sp),
|
||||||
|
&format!("`{}` must come before `{}`", invalid_qual, current_qual),
|
||||||
|
format!("{} {}", invalid_qual, current_qual),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a foreign item (one in an `extern { ... }` block).
|
/// Parses a foreign item (one in an `extern { ... }` block).
|
||||||
pub fn parse_foreign_item(
|
pub fn parse_foreign_item(
|
||||||
|
@ -1485,7 +1507,7 @@ impl<'a> Parser<'a> {
|
||||||
// Make sure an error was emitted (either by recovering an angle bracket,
|
// Make sure an error was emitted (either by recovering an angle bracket,
|
||||||
// or by finding an identifier as the next token), since we're
|
// or by finding an identifier as the next token), since we're
|
||||||
// going to continue parsing
|
// going to continue parsing
|
||||||
assert!(self.sess.span_diagnostic.has_errors());
|
assert!(self.sess.span_diagnostic.has_errors().is_some());
|
||||||
} else {
|
} else {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
@ -1948,7 +1970,7 @@ impl<'a> Parser<'a> {
|
||||||
// We use an over-approximation here.
|
// We use an over-approximation here.
|
||||||
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
|
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
|
||||||
// `pub` is added in case users got confused with the ordering like `async pub fn`,
|
// `pub` is added in case users got confused with the ordering like `async pub fn`,
|
||||||
// only if it wasn't preceeded by `default` as `default pub` is invalid.
|
// only if it wasn't preceded by `default` as `default pub` is invalid.
|
||||||
let quals: &[Symbol] = if check_pub {
|
let quals: &[Symbol] = if check_pub {
|
||||||
&[kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
|
&[kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -624,9 +624,18 @@ impl<'a> Parser<'a> {
|
||||||
GenericArg::Const(self.parse_const_arg()?)
|
GenericArg::Const(self.parse_const_arg()?)
|
||||||
} else if self.check_type() {
|
} else if self.check_type() {
|
||||||
// Parse type argument.
|
// Parse type argument.
|
||||||
|
let is_const_fn = self.look_ahead(1, |t| t.kind == token::OpenDelim(token::Paren));
|
||||||
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match self.parse_ty() {
|
match self.parse_ty() {
|
||||||
Ok(ty) => GenericArg::Type(ty),
|
Ok(ty) => GenericArg::Type(ty),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
if is_const_fn {
|
||||||
|
if let Ok(expr) = (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None)
|
||||||
|
{
|
||||||
|
self.restore_snapshot(snapshot);
|
||||||
|
return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
|
||||||
|
}
|
||||||
|
}
|
||||||
// Try to recover from possible `const` arg without braces.
|
// Try to recover from possible `const` arg without braces.
|
||||||
return self.recover_const_arg(start, err).map(Some);
|
return self.recover_const_arg(start, err).map(Some);
|
||||||
}
|
}
|
||||||
|
@ -636,7 +645,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
// Fall back by trying to parse a const-expr expression. If we successfully do so,
|
// Fall back by trying to parse a const-expr expression. If we successfully do so,
|
||||||
// then we should report an error that it needs to be wrapped in braces.
|
// then we should report an error that it needs to be wrapped in braces.
|
||||||
let snapshot = self.clone();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
|
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
return Ok(Some(self.dummy_const_arg_needs_braces(
|
return Ok(Some(self.dummy_const_arg_needs_braces(
|
||||||
|
@ -645,7 +654,7 @@ impl<'a> Parser<'a> {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
*self = snapshot;
|
self.restore_snapshot(snapshot);
|
||||||
err.cancel();
|
err.cancel();
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
|
ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
|
||||||
};
|
};
|
||||||
lint.build(msg).emit()
|
lint.build(msg).emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
||||||
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
|
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
|
||||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||||
lint.build("`#[inline]` is ignored on function prototypes").emit()
|
lint.build("`#[inline]` is ignored on function prototypes").emit();
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1588,7 +1588,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
||||||
shorthands,
|
shorthands,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
err.emit()
|
err.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1611,7 +1611,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
||||||
non_shorthands,
|
non_shorthands,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
err.emit()
|
err.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
String::new(),
|
String::new(),
|
||||||
rustc_errors::Applicability::MachineApplicable,
|
rustc_errors::Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit()
|
.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,10 +728,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
||||||
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
||||||
item.hir_id(),
|
item.hir_id(),
|
||||||
span,
|
span,
|
||||||
|lint| lint
|
|lint| {lint
|
||||||
.build("an `#[unstable]` annotation here has no effect")
|
.build("an `#[unstable]` annotation here has no effect")
|
||||||
.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
|
.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
|
||||||
.emit()
|
.emit();}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1742,7 +1742,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
||||||
descr,
|
descr,
|
||||||
self.tcx.crate_name(def_id.krate)
|
self.tcx.crate_name(def_id.krate)
|
||||||
))
|
))
|
||||||
.emit()
|
.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1786,7 +1786,9 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
||||||
lint::builtin::PRIVATE_IN_PUBLIC,
|
lint::builtin::PRIVATE_IN_PUBLIC,
|
||||||
hir_id,
|
hir_id,
|
||||||
span,
|
span,
|
||||||
|lint| lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(),
|
|lint| {
|
||||||
|
lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1997,7 +1997,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
db.emit()
|
db.emit();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2002,7 +2002,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) {
|
if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) {
|
||||||
continue 'lifetimes;
|
continue 'lifetimes;
|
||||||
}
|
}
|
||||||
// We want to do this only if the liftime identifier is already defined
|
// We want to do this only if the lifetime identifier is already defined
|
||||||
// in the async function that generated this. Otherwise it could be
|
// in the async function that generated this. Otherwise it could be
|
||||||
// an opaque type defined by the developer and we still want this
|
// an opaque type defined by the developer and we still want this
|
||||||
// lint to fail compilation
|
// lint to fail compilation
|
||||||
|
@ -3143,10 +3143,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
for bound in lifetime_i.bounds {
|
for bound in lifetime_i.bounds {
|
||||||
match bound {
|
match bound {
|
||||||
hir::GenericBound::Outlives(ref lt) => match lt.name {
|
hir::GenericBound::Outlives(ref lt) => match lt.name {
|
||||||
hir::LifetimeName::Underscore => self.tcx.sess.delay_span_bug(
|
hir::LifetimeName::Underscore => {
|
||||||
|
self.tcx.sess.delay_span_bug(
|
||||||
lt.span,
|
lt.span,
|
||||||
"use of `'_` in illegal place, but not caught by lowering",
|
"use of `'_` in illegal place, but not caught by lowering",
|
||||||
),
|
);
|
||||||
|
}
|
||||||
hir::LifetimeName::Static => {
|
hir::LifetimeName::Static => {
|
||||||
self.insert_lifetime(lt, Region::Static);
|
self.insert_lifetime(lt, Region::Static);
|
||||||
self.tcx
|
self.tcx
|
||||||
|
@ -3172,7 +3174,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
lt.span,
|
lt.span,
|
||||||
"lowering generated `ImplicitObjectLifetimeDefault` \
|
"lowering generated `ImplicitObjectLifetimeDefault` \
|
||||||
outside of an object type",
|
outside of an object type",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
hir::LifetimeName::Error => {
|
hir::LifetimeName::Error => {
|
||||||
// No need to do anything, error already reported.
|
// No need to do anything, error already reported.
|
||||||
|
|
|
@ -223,7 +223,7 @@ top_level_options!(
|
||||||
/// `true` if we're emitting a JSON blob containing the unused externs
|
/// `true` if we're emitting a JSON blob containing the unused externs
|
||||||
json_unused_externs: bool [UNTRACKED],
|
json_unused_externs: bool [UNTRACKED],
|
||||||
|
|
||||||
/// `true` if we're emitting a JSON job containg a future-incompat report for lints
|
/// `true` if we're emitting a JSON job containing a future-incompat report for lints
|
||||||
json_future_incompat: bool [TRACKED],
|
json_future_incompat: bool [TRACKED],
|
||||||
|
|
||||||
pretty: Option<PpMode> [UNTRACKED],
|
pretty: Option<PpMode> [UNTRACKED],
|
||||||
|
|
|
@ -100,7 +100,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
|
||||||
match sp {
|
match sp {
|
||||||
Some(sp) => sess.span_err(sp, s),
|
Some(sp) => sess.span_err(sp, s),
|
||||||
None => sess.err(s),
|
None => sess.err(s),
|
||||||
}
|
};
|
||||||
err_count += 1;
|
err_count += 1;
|
||||||
};
|
};
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub struct SymbolGallery {
|
||||||
|
|
||||||
impl SymbolGallery {
|
impl SymbolGallery {
|
||||||
/// Insert a symbol and its span into symbol gallery.
|
/// Insert a symbol and its span into symbol gallery.
|
||||||
/// If the symbol has occurred before, ignore the new occurrance.
|
/// If the symbol has occurred before, ignore the new occurrence.
|
||||||
pub fn insert(&self, symbol: Symbol, span: Span) {
|
pub fn insert(&self, symbol: Symbol, span: Span) {
|
||||||
self.symbols.lock().entry(symbol).or_insert(span);
|
self.symbols.lock().entry(symbol).or_insert(span);
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
diag.emit();
|
diag.emit();
|
||||||
// If we should err, make sure we did.
|
// If we should err, make sure we did.
|
||||||
if must_err && !self.has_errors() {
|
if must_err && !self.has_errors().is_some() {
|
||||||
// We have skipped a feature gate, and not run into other errors... reject.
|
// We have skipped a feature gate, and not run into other errors... reject.
|
||||||
self.err(
|
self.err(
|
||||||
"`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \
|
"`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \
|
||||||
|
@ -404,13 +404,13 @@ impl Session {
|
||||||
self.span_err(sp, msg);
|
self.span_err(sp, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed {
|
||||||
self.diagnostic().span_err(sp, msg)
|
self.diagnostic().span_err(sp, msg)
|
||||||
}
|
}
|
||||||
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
|
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
|
||||||
self.diagnostic().span_err_with_code(sp, &msg, code)
|
self.diagnostic().span_err_with_code(sp, &msg, code)
|
||||||
}
|
}
|
||||||
pub fn err(&self, msg: &str) {
|
pub fn err(&self, msg: &str) -> ErrorGuaranteed {
|
||||||
self.diagnostic().err(msg)
|
self.diagnostic().err(msg)
|
||||||
}
|
}
|
||||||
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
|
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
|
||||||
|
@ -420,7 +420,7 @@ impl Session {
|
||||||
pub fn err_count(&self) -> usize {
|
pub fn err_count(&self) -> usize {
|
||||||
self.diagnostic().err_count()
|
self.diagnostic().err_count()
|
||||||
}
|
}
|
||||||
pub fn has_errors(&self) -> bool {
|
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
|
||||||
self.diagnostic().has_errors()
|
self.diagnostic().has_errors()
|
||||||
}
|
}
|
||||||
pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
|
pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
|
||||||
|
@ -430,9 +430,9 @@ impl Session {
|
||||||
self.diagnostic().abort_if_errors();
|
self.diagnostic().abort_if_errors();
|
||||||
}
|
}
|
||||||
pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
|
pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
|
||||||
if self.diagnostic().has_errors_or_lint_errors() {
|
if let Some(reported) = self.diagnostic().has_errors_or_lint_errors() {
|
||||||
self.diagnostic().emit_stashed_diagnostics();
|
let _ = self.diagnostic().emit_stashed_diagnostics();
|
||||||
Err(ErrorGuaranteed)
|
Err(reported)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -444,7 +444,11 @@ impl Session {
|
||||||
{
|
{
|
||||||
let old_count = self.err_count();
|
let old_count = self.err_count();
|
||||||
let result = f();
|
let result = f();
|
||||||
if self.err_count() == old_count { Ok(result) } else { Err(ErrorGuaranteed) }
|
if self.err_count() == old_count {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
||||||
self.diagnostic().span_warn(sp, msg)
|
self.diagnostic().span_warn(sp, msg)
|
||||||
|
@ -457,7 +461,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
/// Delay a span_bug() call until abort_if_errors()
|
/// Delay a span_bug() call until abort_if_errors()
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed {
|
||||||
self.diagnostic().delay_span_bug(sp, msg)
|
self.diagnostic().delay_span_bug(sp, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,12 +1391,18 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
||||||
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
|
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
|
||||||
match unsupported_sanitizers.into_iter().count() {
|
match unsupported_sanitizers.into_iter().count() {
|
||||||
0 => {}
|
0 => {}
|
||||||
1 => sess
|
1 => {
|
||||||
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
|
sess.err(&format!(
|
||||||
_ => sess.err(&format!(
|
"{} sanitizer is not supported for this target",
|
||||||
|
unsupported_sanitizers
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
sess.err(&format!(
|
||||||
"{} sanitizers are not supported for this target",
|
"{} sanitizers are not supported for this target",
|
||||||
unsupported_sanitizers
|
unsupported_sanitizers
|
||||||
)),
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Cannot mix and match sanitizers.
|
// Cannot mix and match sanitizers.
|
||||||
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
|
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
|
||||||
|
@ -1446,7 +1456,7 @@ pub enum IncrCompSession {
|
||||||
InvalidBecauseOfErrors { session_directory: PathBuf },
|
InvalidBecauseOfErrors { session_directory: PathBuf },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) {
|
pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
|
||||||
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
let emitter: Box<dyn Emitter + sync::Send> = match output {
|
||||||
config::ErrorOutputType::HumanReadable(kind) => {
|
config::ErrorOutputType::HumanReadable(kind) => {
|
||||||
let (short, color_config) = kind.unzip();
|
let (short, color_config) = kind.unzip();
|
||||||
|
@ -1457,7 +1467,8 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
|
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
|
||||||
handler.struct_fatal(msg).emit();
|
let reported = handler.struct_fatal(msg).emit();
|
||||||
|
reported
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
||||||
|
|
|
@ -29,14 +29,14 @@ pub enum NativeLibKind {
|
||||||
/// Dynamic library (e.g. `libfoo.so` on Linux)
|
/// Dynamic library (e.g. `libfoo.so` on Linux)
|
||||||
/// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
|
/// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
|
||||||
Dylib {
|
Dylib {
|
||||||
/// Whether the dynamic library will be linked only if it satifies some undefined symbols
|
/// Whether the dynamic library will be linked only if it satisfies some undefined symbols
|
||||||
as_needed: Option<bool>,
|
as_needed: Option<bool>,
|
||||||
},
|
},
|
||||||
/// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
|
/// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
|
||||||
RawDylib,
|
RawDylib,
|
||||||
/// A macOS-specific kind of dynamic libraries.
|
/// A macOS-specific kind of dynamic libraries.
|
||||||
Framework {
|
Framework {
|
||||||
/// Whether the framework will be linked only if it satifies some undefined symbols
|
/// Whether the framework will be linked only if it satisfies some undefined symbols
|
||||||
as_needed: Option<bool>,
|
as_needed: Option<bool>,
|
||||||
},
|
},
|
||||||
/// The library kind wasn't specified, `Dylib` is currently used as a default.
|
/// The library kind wasn't specified, `Dylib` is currently used as a default.
|
||||||
|
|
|
@ -563,6 +563,7 @@ symbols! {
|
||||||
delay_span_bug_from_inside_query,
|
delay_span_bug_from_inside_query,
|
||||||
deny,
|
deny,
|
||||||
deprecated,
|
deprecated,
|
||||||
|
deprecated_safe,
|
||||||
deprecated_suggestion,
|
deprecated_suggestion,
|
||||||
deref,
|
deref,
|
||||||
deref_method,
|
deref_method,
|
||||||
|
|
|
@ -226,7 +226,7 @@ fn compute_symbol_name<'tcx>(
|
||||||
|
|
||||||
// If we're dealing with an instance of a function that's inlined from
|
// If we're dealing with an instance of a function that's inlined from
|
||||||
// another crate but we're marking it as globally shared to our
|
// another crate but we're marking it as globally shared to our
|
||||||
// compliation (aka we're not making an internal copy in each of our
|
// compilation (aka we're not making an internal copy in each of our
|
||||||
// codegen units) then this symbol may become an exported (but hidden
|
// codegen units) then this symbol may become an exported (but hidden
|
||||||
// visibility) symbol. This means that multiple crates may do the same
|
// visibility) symbol. This means that multiple crates may do the same
|
||||||
// and we want to be sure to avoid any symbol conflicts here.
|
// and we want to be sure to avoid any symbol conflicts here.
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ impl Niche {
|
||||||
|
|
||||||
// Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
|
// Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
|
||||||
// Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
|
// Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
|
||||||
// This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
|
// This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
|
||||||
// Having `None` in niche zero can enable some special optimizations.
|
// Having `None` in niche zero can enable some special optimizations.
|
||||||
//
|
//
|
||||||
// Bound selection criteria:
|
// Bound selection criteria:
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
|
||||||
// leading to an ambiguous result. So report this as an
|
// leading to an ambiguous result. So report this as an
|
||||||
// overflow bug, since I believe this is the only case
|
// overflow bug, since I believe this is the only case
|
||||||
// where ambiguity can result.
|
// where ambiguity can result.
|
||||||
infcx.tcx.sess.delay_span_bug(
|
let reported = infcx.tcx.sess.delay_span_bug(
|
||||||
rustc_span::DUMMY_SP,
|
rustc_span::DUMMY_SP,
|
||||||
&format!(
|
&format!(
|
||||||
"encountered ambiguity selecting `{:?}` during codegen, presuming due to \
|
"encountered ambiguity selecting `{:?}` during codegen, presuming due to \
|
||||||
|
@ -59,21 +59,21 @@ pub fn codegen_fulfill_obligation<'tcx>(
|
||||||
trait_ref
|
trait_ref
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
Err(Unimplemented) => {
|
Err(Unimplemented) => {
|
||||||
// This can trigger when we probe for the source of a `'static` lifetime requirement
|
// This can trigger when we probe for the source of a `'static` lifetime requirement
|
||||||
// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
|
// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
|
||||||
// This can also trigger when we have a global bound that is not actually satisfied,
|
// This can also trigger when we have a global bound that is not actually satisfied,
|
||||||
// but was included during typeck due to the trivial_bounds feature.
|
// but was included during typeck due to the trivial_bounds feature.
|
||||||
infcx.tcx.sess.delay_span_bug(
|
let guar = infcx.tcx.sess.delay_span_bug(
|
||||||
rustc_span::DUMMY_SP,
|
rustc_span::DUMMY_SP,
|
||||||
&format!(
|
&format!(
|
||||||
"Encountered error `Unimplemented` selecting `{:?}` during codegen",
|
"Encountered error `Unimplemented` selecting `{:?}` during codegen",
|
||||||
trait_ref
|
trait_ref
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Err(ErrorGuaranteed);
|
return Err(guar);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
|
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
|
||||||
|
|
|
@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::thir;
|
use rustc_middle::thir;
|
||||||
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
|
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
|
||||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, DelaySpanBugEmitted, TyCtxt, TypeFoldable};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -177,8 +177,9 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||||
false => NotConstEvaluatable::MentionsParam,
|
false => NotConstEvaluatable::MentionsParam,
|
||||||
}),
|
}),
|
||||||
Err(ErrorHandled::Linted) => {
|
Err(ErrorHandled::Linted) => {
|
||||||
|
let reported =
|
||||||
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
|
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
|
||||||
Err(NotConstEvaluatable::Error(ErrorGuaranteed))
|
Err(NotConstEvaluatable::Error(reported))
|
||||||
}
|
}
|
||||||
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
|
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
|
@ -244,7 +245,7 @@ impl<'tcx> AbstractConst<'tcx> {
|
||||||
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
|
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
|
||||||
match ct.val() {
|
match ct.val() {
|
||||||
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
|
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
|
||||||
ty::ConstKind::Error(_) => Err(ErrorGuaranteed),
|
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,17 +281,19 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
|
fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
|
||||||
self.tcx
|
let reported = self
|
||||||
|
.tcx
|
||||||
.sess
|
.sess
|
||||||
.struct_span_err(self.root_span(), "overly complex generic constant")
|
.struct_span_err(self.root_span(), "overly complex generic constant")
|
||||||
.span_label(span, msg)
|
.span_label(span, msg)
|
||||||
.help("consider moving this anonymous constant into a `const` function")
|
.help("consider moving this anonymous constant into a `const` function")
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
Err(ErrorGuaranteed)
|
Err(reported)
|
||||||
}
|
}
|
||||||
fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
|
fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGuaranteed> {
|
||||||
self.tcx
|
let reported = self
|
||||||
|
.tcx
|
||||||
.sess
|
.sess
|
||||||
.struct_span_err(self.root_span(), "overly complex generic constant")
|
.struct_span_err(self.root_span(), "overly complex generic constant")
|
||||||
.span_label(span, msg)
|
.span_label(span, msg)
|
||||||
|
@ -298,7 +301,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
.note("this operation may be supported in the future")
|
.note("this operation may be supported in the future")
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
Err(ErrorGuaranteed)
|
Err(reported)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
|
@ -553,11 +556,7 @@ pub(super) fn thir_abstract_const<'tcx>(
|
||||||
_ => return Ok(None),
|
_ => return Ok(None),
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = tcx.thir_body(def);
|
let body = tcx.thir_body(def)?;
|
||||||
if body.0.borrow().exprs.is_empty() {
|
|
||||||
// type error in constant, there is no thir
|
|
||||||
return Err(ErrorGuaranteed);
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
|
AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
|
||||||
.map(AbstractConstBuilder::build)
|
.map(AbstractConstBuilder::build)
|
||||||
|
@ -580,7 +579,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
})()
|
})()
|
||||||
.unwrap_or_else(|ErrorGuaranteed| true)
|
.unwrap_or_else(|_: ErrorGuaranteed| true)
|
||||||
// FIXME(generic_const_exprs): We should instead have this
|
// FIXME(generic_const_exprs): We should instead have this
|
||||||
// method return the resulting `ty::Const` and return `ConstKind::Error`
|
// method return the resulting `ty::Const` and return `ConstKind::Error`
|
||||||
// on `ErrorGuaranteed`.
|
// on `ErrorGuaranteed`.
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub trait InferCtxtExt<'tcx> {
|
||||||
errors: &[FulfillmentError<'tcx>],
|
errors: &[FulfillmentError<'tcx>],
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
fallback_has_occurred: bool,
|
fallback_has_occurred: bool,
|
||||||
);
|
) -> ErrorGuaranteed;
|
||||||
|
|
||||||
fn report_overflow_error<T>(
|
fn report_overflow_error<T>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -111,7 +111,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
errors: &[FulfillmentError<'tcx>],
|
errors: &[FulfillmentError<'tcx>],
|
||||||
body_id: Option<hir::BodyId>,
|
body_id: Option<hir::BodyId>,
|
||||||
fallback_has_occurred: bool,
|
fallback_has_occurred: bool,
|
||||||
) {
|
) -> ErrorGuaranteed {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ErrorDescriptor<'tcx> {
|
struct ErrorDescriptor<'tcx> {
|
||||||
predicate: ty::Predicate<'tcx>,
|
predicate: ty::Predicate<'tcx>,
|
||||||
|
@ -190,6 +190,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
self.report_fulfillment_error(error, body_id, fallback_has_occurred);
|
self.report_fulfillment_error(error, body_id, fallback_has_occurred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fullfillment errors")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reports that an overflow has occurred and halts compilation. We
|
/// Reports that an overflow has occurred and halts compilation. We
|
||||||
|
@ -312,7 +314,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let predicate_is_const = ty::BoundConstness::ConstIfConst
|
let predicate_is_const = ty::BoundConstness::ConstIfConst
|
||||||
== trait_predicate.skip_binder().constness;
|
== trait_predicate.skip_binder().constness;
|
||||||
|
|
||||||
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
|
if self.tcx.sess.has_errors().is_some()
|
||||||
|
&& trait_predicate.references_error()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||||
|
@ -919,7 +923,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already reported in the query.
|
// Already reported in the query.
|
||||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorGuaranteed)) => {
|
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) => {
|
||||||
// FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token.
|
// FIXME(eddyb) remove this once `ErrorGuaranteed` becomes a proof token.
|
||||||
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
|
self.tcx.sess.delay_span_bug(span, "`ErrorGuaranteed` without an error");
|
||||||
return;
|
return;
|
||||||
|
@ -1857,7 +1861,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
// Same hacky approach as above to avoid deluging user
|
// Same hacky approach as above to avoid deluging user
|
||||||
// with error messages.
|
// with error messages.
|
||||||
if arg.references_error()
|
if arg.references_error()
|
||||||
|| self.tcx.sess.has_errors()
|
|| self.tcx.sess.has_errors().is_some()
|
||||||
|| self.is_tainted_by_errors()
|
|| self.is_tainted_by_errors()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1868,7 +1872,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
ty::PredicateKind::Subtype(data) => {
|
ty::PredicateKind::Subtype(data) => {
|
||||||
if data.references_error()
|
if data.references_error()
|
||||||
|| self.tcx.sess.has_errors()
|
|| self.tcx.sess.has_errors().is_some()
|
||||||
|| self.is_tainted_by_errors()
|
|| self.is_tainted_by_errors()
|
||||||
{
|
{
|
||||||
// no need to overload user in such cases
|
// no need to overload user in such cases
|
||||||
|
@ -1910,7 +1914,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
if self.tcx.sess.has_errors() || self.is_tainted_by_errors() {
|
if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
|
|
|
@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::obligation_forest::ProcessResult;
|
use rustc_data_structures::obligation_forest::ProcessResult;
|
||||||
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
||||||
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
|
||||||
use rustc_infer::traits::ProjectionCacheKey;
|
use rustc_infer::traits::ProjectionCacheKey;
|
||||||
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
|
@ -630,14 +629,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Err(ErrorHandled::Reported(ErrorGuaranteed)), _)
|
(Err(ErrorHandled::Reported(reported)), _)
|
||||||
| (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => {
|
| (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
|
||||||
ProcessResult::Error(CodeSelectionError(
|
CodeSelectionError(SelectionError::NotConstEvaluatable(
|
||||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(
|
NotConstEvaluatable::Error(reported),
|
||||||
ErrorGuaranteed,
|
|
||||||
)),
|
)),
|
||||||
))
|
),
|
||||||
}
|
|
||||||
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
|
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
obligation.cause.span(self.selcx.tcx()),
|
obligation.cause.span(self.selcx.tcx()),
|
||||||
|
|
|
@ -231,8 +231,8 @@ fn do_normalize_predicates<'tcx>(
|
||||||
match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
|
match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, predicates) {
|
||||||
Ok(predicates) => predicates,
|
Ok(predicates) => predicates,
|
||||||
Err(errors) => {
|
Err(errors) => {
|
||||||
infcx.report_fulfillment_errors(&errors, None, false);
|
let reported = infcx.report_fulfillment_errors(&errors, None, false);
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -258,13 +258,15 @@ fn do_normalize_predicates<'tcx>(
|
||||||
// represents a legitimate failure due to some kind of
|
// represents a legitimate failure due to some kind of
|
||||||
// unconstrained variable, and it seems better not to ICE,
|
// unconstrained variable, and it seems better not to ICE,
|
||||||
// all things considered.
|
// all things considered.
|
||||||
tcx.sess.span_err(span, &fixup_err.to_string());
|
let reported = tcx.sess.span_err(span, &fixup_err.to_string());
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if predicates.needs_infer() {
|
if predicates.needs_infer() {
|
||||||
tcx.sess.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
|
let reported = tcx
|
||||||
Err(ErrorGuaranteed)
|
.sess
|
||||||
|
.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
|
||||||
|
Err(reported)
|
||||||
} else {
|
} else {
|
||||||
Ok(predicates)
|
Ok(predicates)
|
||||||
}
|
}
|
||||||
|
@ -536,7 +538,7 @@ fn prepare_vtable_segments<'tcx, T>(
|
||||||
|
|
||||||
// the main traversal loop:
|
// the main traversal loop:
|
||||||
// basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
|
// basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
|
||||||
// that each node is emited after all its descendents have been emitted.
|
// that each node is emitted after all its descendents have been emitted.
|
||||||
// so we convert the directed graph into a tree by skipping all previously visted nodes using a visited set.
|
// so we convert the directed graph into a tree by skipping all previously visted nodes using a visited set.
|
||||||
// this is done on the fly.
|
// this is done on the fly.
|
||||||
// Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
|
// Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
|
||||||
|
@ -551,10 +553,10 @@ fn prepare_vtable_segments<'tcx, T>(
|
||||||
// Starting point 0 stack [D]
|
// Starting point 0 stack [D]
|
||||||
// Loop run #0: Stack after diving in is [D B A], A is "childless"
|
// Loop run #0: Stack after diving in is [D B A], A is "childless"
|
||||||
// after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
|
// after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
|
||||||
// Loop run #0: Emiting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
|
// Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
|
||||||
// Loop run #0: Stack after exiting out is [D C], C is the next starting point.
|
// Loop run #0: Stack after exiting out is [D C], C is the next starting point.
|
||||||
// Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
|
// Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
|
||||||
// Loop run #1: Emiting the slice [D C] (in reverse order). No one has a next-sibling node.
|
// Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
|
||||||
// Loop run #1: Stack after exiting out is []. Now the function exits.
|
// Loop run #1: Stack after exiting out is []. Now the function exits.
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
|
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
|
||||||
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
|
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct OnUnimplementedFormatString(Symbol);
|
pub struct OnUnimplementedFormatString(Symbol);
|
||||||
|
@ -47,8 +47,7 @@ fn parse_error(
|
||||||
if let Some(note) = note {
|
if let Some(note) = note {
|
||||||
diag.note(note);
|
diag.note(note);
|
||||||
}
|
}
|
||||||
diag.emit();
|
diag.emit()
|
||||||
ErrorGuaranteed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> OnUnimplementedDirective {
|
impl<'tcx> OnUnimplementedDirective {
|
||||||
|
@ -59,7 +58,7 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
span: Span,
|
span: Span,
|
||||||
is_root: bool,
|
is_root: bool,
|
||||||
) -> Result<Self, ErrorGuaranteed> {
|
) -> Result<Self, ErrorGuaranteed> {
|
||||||
let mut errored = false;
|
let mut errored = None;
|
||||||
let mut item_iter = items.iter();
|
let mut item_iter = items.iter();
|
||||||
|
|
||||||
let parse_value = |value_str| {
|
let parse_value = |value_str| {
|
||||||
|
@ -91,8 +90,8 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
|
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
|
||||||
if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
|
if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
|
||||||
errored = true;
|
errored = Some(guar);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
@ -134,13 +133,10 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
&& note.is_none()
|
&& note.is_none()
|
||||||
{
|
{
|
||||||
if let Some(items) = item.meta_item_list() {
|
if let Some(items) = item.meta_item_list() {
|
||||||
if let Ok(subcommand) =
|
match Self::parse(tcx, item_def_id, &items, item.span(), false) {
|
||||||
Self::parse(tcx, item_def_id, &items, item.span(), false)
|
Ok(subcommand) => subcommands.push(subcommand),
|
||||||
{
|
Err(reported) => errored = Some(reported),
|
||||||
subcommands.push(subcommand);
|
};
|
||||||
} else {
|
|
||||||
errored = true;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
|
} else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
|
||||||
|
@ -163,8 +159,8 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if errored {
|
if let Some(reported) = errored {
|
||||||
Err(ErrorGuaranteed)
|
Err(reported)
|
||||||
} else {
|
} else {
|
||||||
Ok(OnUnimplementedDirective {
|
Ok(OnUnimplementedDirective {
|
||||||
condition,
|
condition,
|
||||||
|
@ -203,7 +199,9 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
append_const_msg: None,
|
append_const_msg: None,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
return Err(ErrorGuaranteed);
|
let reported =
|
||||||
|
tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str");
|
||||||
|
return Err(reported);
|
||||||
};
|
};
|
||||||
debug!("of_item({:?}) = {:?}", item_def_id, result);
|
debug!("of_item({:?}) = {:?}", item_def_id, result);
|
||||||
result
|
result
|
||||||
|
@ -327,7 +325,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||||
match generics.params.iter().find(|param| param.name == s) {
|
match generics.params.iter().find(|param| param.name == s) {
|
||||||
Some(_) => (),
|
Some(_) => (),
|
||||||
None => {
|
None => {
|
||||||
struct_span_err!(
|
let reported = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
span,
|
span,
|
||||||
E0230,
|
E0230,
|
||||||
|
@ -340,20 +338,20 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
result = Err(ErrorGuaranteed);
|
result = Err(reported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `{:1}` and `{}` are not to be used
|
// `{:1}` and `{}` are not to be used
|
||||||
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
|
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
|
||||||
struct_span_err!(
|
let reported = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
span,
|
span,
|
||||||
E0231,
|
E0231,
|
||||||
"only named substitution parameters are allowed"
|
"only named substitution parameters are allowed"
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
result = Err(ErrorGuaranteed);
|
result = Err(reported);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1396,7 +1396,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
// `rustc_ty_utils::instance::resolve_associated_item()`.
|
// `rustc_ty_utils::instance::resolve_associated_item()`.
|
||||||
let node_item =
|
let node_item =
|
||||||
assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
|
assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
|
||||||
.map_err(|ErrorGuaranteed| ())?;
|
.map_err(|ErrorGuaranteed { .. }| ())?;
|
||||||
|
|
||||||
if node_item.is_final() {
|
if node_item.is_final() {
|
||||||
// Non-specializable items are always projectable.
|
// Non-specializable items are always projectable.
|
||||||
|
|
|
@ -719,7 +719,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
||||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
||||||
// See `assemble_candidates_for_unsizing` for more info.
|
// See `assemble_candidates_for_unsizing` for more info.
|
||||||
// We already checked the compatiblity of auto traits within `assemble_candidates_for_unsizing`.
|
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||||
let principal_a = data_a.principal().unwrap();
|
let principal_a = data_a.principal().unwrap();
|
||||||
source_trait_ref = principal_a.with_self_ty(tcx, source);
|
source_trait_ref = principal_a.with_self_ty(tcx, source);
|
||||||
upcast_trait_ref = util::supertraits(tcx, source_trait_ref).nth(idx).unwrap();
|
upcast_trait_ref = util::supertraits(tcx, source_trait_ref).nth(idx).unwrap();
|
||||||
|
@ -823,7 +823,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
|
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
|
||||||
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
|
||||||
// See `assemble_candidates_for_unsizing` for more info.
|
// See `assemble_candidates_for_unsizing` for more info.
|
||||||
// We already checked the compatiblity of auto traits within `assemble_candidates_for_unsizing`.
|
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||||
let iter = data_a
|
let iter = data_a
|
||||||
.principal()
|
.principal()
|
||||||
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
|
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
|
||||||
|
@ -1084,7 +1084,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
| ty::Foreign(_) => {}
|
| ty::Foreign(_) => {}
|
||||||
|
|
||||||
// These types are built-in, so we can fast-track by registering
|
// These types are built-in, so we can fast-track by registering
|
||||||
// nested predicates for their constituient type(s)
|
// nested predicates for their constituent type(s)
|
||||||
ty::Array(ty, _) | ty::Slice(ty) => {
|
ty::Array(ty, _) | ty::Slice(ty) => {
|
||||||
stack.push(ty);
|
stack.push(ty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::traits::project::ProjectionCacheKeyExt;
|
||||||
use crate::traits::ProjectionCacheKey;
|
use crate::traits::ProjectionCacheKey;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_errors::{Diagnostic, ErrorGuaranteed};
|
use rustc_errors::Diagnostic;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||||
|
@ -553,7 +553,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
match project::poly_project_and_unify_type(self, &project_obligation) {
|
match project::poly_project_and_unify_type(self, &project_obligation) {
|
||||||
Ok(Ok(Some(mut subobligations))) => {
|
Ok(Ok(Some(mut subobligations))) => {
|
||||||
'compute_res: {
|
'compute_res: {
|
||||||
// If we've previously marked this projection as 'complete', thne
|
// If we've previously marked this projection as 'complete', then
|
||||||
// use the final cached result (either `EvaluatedToOk` or
|
// use the final cached result (either `EvaluatedToOk` or
|
||||||
// `EvaluatedToOkModuloRegions`), and skip re-evaluating the
|
// `EvaluatedToOkModuloRegions`), and skip re-evaluating the
|
||||||
// sub-obligations.
|
// sub-obligations.
|
||||||
|
@ -674,8 +674,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
Err(_) => Ok(EvaluatedToErr),
|
Err(_) => Ok(EvaluatedToErr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Err(ErrorHandled::Reported(ErrorGuaranteed)), _)
|
(Err(ErrorHandled::Reported(_)), _)
|
||||||
| (_, Err(ErrorHandled::Reported(ErrorGuaranteed))) => Ok(EvaluatedToErr),
|
| (_, Err(ErrorHandled::Reported(_))) => Ok(EvaluatedToErr),
|
||||||
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
|
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
obligation.cause.span(self.tcx()),
|
obligation.cause.span(self.tcx()),
|
||||||
|
|
|
@ -16,14 +16,14 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||||
use crate::traits::select::IntercrateAmbiguityCause;
|
use crate::traits::select::IntercrateAmbiguityCause;
|
||||||
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
|
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::{struct_span_err, EmissionGuarantee};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
|
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
|
||||||
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
|
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
use super::util::impl_trait_ref_and_oblig;
|
use super::util::impl_trait_ref_and_oblig;
|
||||||
use super::{FulfillmentContext, SelectionContext};
|
use super::{FulfillmentContext, SelectionContext};
|
||||||
|
@ -377,8 +377,7 @@ fn report_negative_positive_conflict(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sg.has_errored = true;
|
sg.has_errored = Some(err.emit());
|
||||||
err.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_conflicting_impls(
|
fn report_conflicting_impls(
|
||||||
|
@ -394,7 +393,13 @@ fn report_conflicting_impls(
|
||||||
// Work to be done after we've built the DiagnosticBuilder. We have to define it
|
// Work to be done after we've built the DiagnosticBuilder. We have to define it
|
||||||
// now because the struct_lint methods don't return back the DiagnosticBuilder
|
// now because the struct_lint methods don't return back the DiagnosticBuilder
|
||||||
// that's passed in.
|
// that's passed in.
|
||||||
let decorate = |err: LintDiagnosticBuilder<'_>| {
|
fn decorate<G: EmissionGuarantee>(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
overlap: OverlapError,
|
||||||
|
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
|
||||||
|
impl_span: Span,
|
||||||
|
err: LintDiagnosticBuilder<'_, G>,
|
||||||
|
) -> G {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"conflicting implementations of trait `{}`{}{}",
|
"conflicting implementations of trait `{}`{}{}",
|
||||||
overlap.trait_desc,
|
overlap.trait_desc,
|
||||||
|
@ -440,17 +445,25 @@ fn report_conflicting_impls(
|
||||||
coherence::add_placeholder_note(&mut err);
|
coherence::add_placeholder_note(&mut err);
|
||||||
}
|
}
|
||||||
err.emit()
|
err.emit()
|
||||||
};
|
}
|
||||||
|
|
||||||
match used_to_be_allowed {
|
match used_to_be_allowed {
|
||||||
None => {
|
None => {
|
||||||
sg.has_errored = true;
|
let reported = if overlap.with_impl.is_local()
|
||||||
if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) {
|
|| !tcx.orphan_check_crate(()).contains(&impl_def_id)
|
||||||
|
{
|
||||||
let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
|
let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
|
||||||
decorate(LintDiagnosticBuilder::new(err.forget_guarantee()));
|
Some(decorate(
|
||||||
|
tcx,
|
||||||
|
overlap,
|
||||||
|
used_to_be_allowed,
|
||||||
|
impl_span,
|
||||||
|
LintDiagnosticBuilder::new(err),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check");
|
Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
|
||||||
}
|
};
|
||||||
|
sg.has_errored = reported;
|
||||||
}
|
}
|
||||||
Some(kind) => {
|
Some(kind) => {
|
||||||
let lint = match kind {
|
let lint = match kind {
|
||||||
|
@ -461,8 +474,10 @@ fn report_conflicting_impls(
|
||||||
lint,
|
lint,
|
||||||
tcx.hir().local_def_id_to_hir_id(impl_def_id),
|
tcx.hir().local_def_id_to_hir_id(impl_def_id),
|
||||||
impl_span,
|
impl_span,
|
||||||
decorate,
|
|ldb| {
|
||||||
)
|
decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,9 +306,9 @@ fn resolve_associated_item<'tcx>(
|
||||||
resolved_ty,
|
resolved_ty,
|
||||||
);
|
);
|
||||||
let span = tcx.def_span(leaf_def.item.def_id);
|
let span = tcx.def_span(leaf_def.item.def_id);
|
||||||
tcx.sess.delay_span_bug(span, &msg);
|
let reported = tcx.sess.delay_span_bug(span, &msg);
|
||||||
|
|
||||||
return Err(ErrorGuaranteed);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
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