Auto merge of #3263 - rust-lang:rustup-2024-01-10, r=saethlin
Automatic Rustup
This commit is contained in:
commit
2dc23e7952
869 changed files with 15164 additions and 9250 deletions
19
.github/ISSUE_TEMPLATE/diagnostics.yaml
vendored
19
.github/ISSUE_TEMPLATE/diagnostics.yaml
vendored
|
|
@ -52,10 +52,23 @@ body:
|
|||
render: Rust
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
value: |
|
||||
If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition.
|
||||
label: Rust Version
|
||||
description: Please provide the `rustc` version, `rustc --version --verbose`. Make sure that you're using the latest version of the compiler, and not an outdated stable or nightly release!
|
||||
placeholder: |
|
||||
$ rustc --version --verbose
|
||||
rustc 1.XX.Y (SHORTHASH DATE)
|
||||
binary: rustc
|
||||
commit-hash: LONGHASHVALUE
|
||||
commit-date: DATE
|
||||
host: PLATFORMTRIPLE
|
||||
release: 1.XX.Y
|
||||
LLVM version: XX.YY.ZZ
|
||||
render: Shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: extra
|
||||
attributes:
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/ice.yaml
vendored
2
.github/ISSUE_TEMPLATE/ice.yaml
vendored
|
|
@ -40,7 +40,7 @@ body:
|
|||
id: version
|
||||
attributes:
|
||||
label: Rust Version
|
||||
description: Please provide the `rustc` version, `rustc --version --verbose`
|
||||
description: Please provide the `rustc` version, `rustc --version --verbose`. Make sure that you're using the latest version of the compiler, and not an outdated stable or nightly release!
|
||||
placeholder: |
|
||||
$ rustc --version --verbose
|
||||
rustc 1.XX.Y (SHORTHASH DATE)
|
||||
|
|
|
|||
|
|
@ -704,9 +704,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
|
|||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.103"
|
||||
version = "0.1.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242"
|
||||
checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
|
|
@ -3738,6 +3738,7 @@ dependencies = [
|
|||
"rustc_trait_selection",
|
||||
"rustc_ty_utils",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"time",
|
||||
"tracing",
|
||||
"windows",
|
||||
|
|
@ -3797,7 +3798,6 @@ dependencies = [
|
|||
name = "rustc_expand"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"rustc_ast",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
|
|
@ -3877,6 +3877,7 @@ dependencies = [
|
|||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_lint_defs",
|
||||
|
|
@ -4644,6 +4645,7 @@ dependencies = [
|
|||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,14 @@ gimli.debug = 0
|
|||
miniz_oxide.debug = 0
|
||||
object.debug = 0
|
||||
|
||||
# These are very thin wrappers around executing lld with the right binary name.
|
||||
# Basically nothing within them can go wrong without having been explicitly logged anyway.
|
||||
# We ship these in every rustc tarball and even after compression they add up
|
||||
# to around 0.6MB of data every user needs to download (and 15MB on disk).
|
||||
[profile.release.package.lld-wrapper]
|
||||
debug = 0
|
||||
strip = true
|
||||
|
||||
[patch.crates-io]
|
||||
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
|
||||
# here
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_data_structures::stable_hasher::StableOrd;
|
|||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::HashStable_Generic;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_macros::{Decodable_Generic, Encodable_Generic};
|
||||
#[cfg(feature = "nightly")]
|
||||
use std::iter::Step;
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ pub use layout::LayoutCalculator;
|
|||
pub trait HashStableContext {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Default)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||
pub struct ReprFlags(u8);
|
||||
|
||||
bitflags! {
|
||||
|
|
@ -52,7 +52,7 @@ bitflags! {
|
|||
rustc_data_structures::external_bitflags_debug! { ReprFlags }
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||
pub enum IntegerType {
|
||||
/// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g.
|
||||
/// `Pointer(true)` means `isize`.
|
||||
|
|
@ -73,7 +73,7 @@ impl IntegerType {
|
|||
|
||||
/// Represents the repr options provided by the user.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||
pub struct ReprOptions {
|
||||
pub int: Option<IntegerType>,
|
||||
pub align: Option<Align>,
|
||||
|
|
@ -412,7 +412,7 @@ impl FromStr for Endian {
|
|||
|
||||
/// Size of a type in bytes.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||
pub struct Size {
|
||||
raw: u64,
|
||||
}
|
||||
|
|
@ -636,7 +636,7 @@ impl Step for Size {
|
|||
|
||||
/// Alignment of a type in bytes (always a power of two).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||
pub struct Align {
|
||||
pow2: u8,
|
||||
}
|
||||
|
|
@ -777,7 +777,7 @@ impl AbiAndPrefAlign {
|
|||
|
||||
/// Integers, also used for enum discriminants.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||
pub enum Integer {
|
||||
I8,
|
||||
I16,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
pub use crate::format::*;
|
||||
pub use crate::util::parser::ExprPrecedence;
|
||||
pub use rustc_span::AttrId;
|
||||
pub use GenericArgs::*;
|
||||
pub use UnsafeSource::*;
|
||||
|
||||
|
|
@ -30,7 +31,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||
|
|
@ -2682,22 +2682,6 @@ pub enum AttrStyle {
|
|||
Inner,
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[orderable]
|
||||
#[debug_format = "AttrId({})"]
|
||||
pub struct AttrId {}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for AttrId {
|
||||
fn encode(&self, _s: &mut S) {}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for AttrId {
|
||||
default fn decode(_: &mut D) -> AttrId {
|
||||
panic!("cannot decode `AttrId` with `{}`", std::any::type_name::<D>());
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of attributes.
|
||||
pub type AttrVec = ThinVec<Attribute>;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ use crate::AttrVec;
|
|||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::{sym, Span, SpanDecoder, SpanEncoder, Symbol, DUMMY_SP};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
|
@ -150,14 +150,14 @@ impl fmt::Debug for LazyAttrTokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for LazyAttrTokenStream {
|
||||
impl<S: SpanEncoder> Encodable<S> for LazyAttrTokenStream {
|
||||
fn encode(&self, s: &mut S) {
|
||||
// Used by AST json printing.
|
||||
Encodable::encode(&self.to_attr_token_stream(), s);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for LazyAttrTokenStream {
|
||||
impl<D: SpanDecoder> Decodable<D> for LazyAttrTokenStream {
|
||||
fn decode(_d: &mut D) -> Self {
|
||||
panic!("Attempted to decode LazyAttrTokenStream");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ ast_lowering_bad_return_type_notation_output =
|
|||
|
||||
ast_lowering_base_expression_double_dot =
|
||||
base expression required after `..`
|
||||
.label = add a base expression here
|
||||
.suggestion = add a base expression here
|
||||
|
||||
ast_lowering_clobber_abi_not_supported =
|
||||
`clobber_abi` is not supported on this target
|
||||
|
|
@ -106,7 +106,8 @@ ast_lowering_misplaced_double_dot =
|
|||
.note = only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
ast_lowering_misplaced_impl_trait =
|
||||
`impl Trait` only allowed in function and inherent method argument and return types, not in {$position}
|
||||
`impl Trait` is not allowed in {$position}
|
||||
.note = `impl Trait` is only allowed in arguments and return types of functions and methods
|
||||
|
||||
ast_lowering_misplaced_relax_trait_bound =
|
||||
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ pub enum AssocTyParenthesesSub {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
|
||||
#[note]
|
||||
pub struct MisplacedImplTrait<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -113,10 +114,10 @@ pub struct UnderscoreExprLhsAssign {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering_base_expression_double_dot)]
|
||||
#[diag(ast_lowering_base_expression_double_dot, code = "E0797")]
|
||||
pub struct BaseExpressionDoubleDot {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::PredicateOrigin;
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
|
|
@ -182,7 +183,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
|
||||
}
|
||||
ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
|
||||
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
|
||||
let (ty, body_id) =
|
||||
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
||||
hir::ItemKind::Static(ty, *m, body_id)
|
||||
}
|
||||
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
||||
|
|
@ -191,7 +193,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Const::No,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_const_item(ty, span, expr.as_deref()),
|
||||
|this| {
|
||||
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
|
||||
},
|
||||
);
|
||||
hir::ItemKind::Const(ty, generics, body_id)
|
||||
}
|
||||
|
|
@ -448,8 +452,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ty: &Ty,
|
||||
span: Span,
|
||||
body: Option<&Expr>,
|
||||
impl_trait_position: ImplTraitPosition,
|
||||
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
|
||||
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
||||
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(impl_trait_position));
|
||||
(ty, self.lower_const_body(span, body))
|
||||
}
|
||||
|
||||
|
|
@ -572,23 +577,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// This is used to track which lifetimes have already been defined,
|
||||
// and which need to be replicated when lowering an async fn.
|
||||
|
||||
match parent_hir.node().expect_item().kind {
|
||||
let generics = match parent_hir.node().expect_item().kind {
|
||||
hir::ItemKind::Impl(impl_) => {
|
||||
self.is_in_trait_impl = impl_.of_trait.is_some();
|
||||
&impl_.generics
|
||||
}
|
||||
hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => {
|
||||
self.host_param_id = generics
|
||||
.params
|
||||
.iter()
|
||||
.find(|param| {
|
||||
matches!(
|
||||
param.kind,
|
||||
hir::GenericParamKind::Const { is_host_effect: true, .. }
|
||||
)
|
||||
})
|
||||
.map(|param| param.def_id);
|
||||
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
|
||||
kind => {
|
||||
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
if self.tcx.features().effects {
|
||||
self.host_param_id = generics
|
||||
.params
|
||||
.iter()
|
||||
.find(|param| {
|
||||
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
|
||||
})
|
||||
.map(|param| param.def_id);
|
||||
}
|
||||
|
||||
match ctxt {
|
||||
|
|
|
|||
|
|
@ -304,8 +304,6 @@ enum ImplTraitPosition {
|
|||
ClosureParam,
|
||||
PointerParam,
|
||||
FnTraitParam,
|
||||
TraitParam,
|
||||
ImplParam,
|
||||
ExternFnReturn,
|
||||
ClosureReturn,
|
||||
PointerReturn,
|
||||
|
|
@ -324,29 +322,27 @@ impl std::fmt::Display for ImplTraitPosition {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
ImplTraitPosition::Path => "paths",
|
||||
ImplTraitPosition::Variable => "variable bindings",
|
||||
ImplTraitPosition::Variable => "the type of variable bindings",
|
||||
ImplTraitPosition::Trait => "traits",
|
||||
ImplTraitPosition::AsyncBlock => "async blocks",
|
||||
ImplTraitPosition::Bound => "bounds",
|
||||
ImplTraitPosition::Generic => "generics",
|
||||
ImplTraitPosition::ExternFnParam => "`extern fn` params",
|
||||
ImplTraitPosition::ClosureParam => "closure params",
|
||||
ImplTraitPosition::PointerParam => "`fn` pointer params",
|
||||
ImplTraitPosition::FnTraitParam => "`Fn` trait params",
|
||||
ImplTraitPosition::TraitParam => "trait method params",
|
||||
ImplTraitPosition::ImplParam => "`impl` method params",
|
||||
ImplTraitPosition::ExternFnParam => "`extern fn` parameters",
|
||||
ImplTraitPosition::ClosureParam => "closure parameters",
|
||||
ImplTraitPosition::PointerParam => "`fn` pointer parameters",
|
||||
ImplTraitPosition::FnTraitParam => "the parameters of `Fn` trait bounds",
|
||||
ImplTraitPosition::ExternFnReturn => "`extern fn` return types",
|
||||
ImplTraitPosition::ClosureReturn => "closure return types",
|
||||
ImplTraitPosition::PointerReturn => "`fn` pointer return types",
|
||||
ImplTraitPosition::FnTraitReturn => "`Fn` trait return types",
|
||||
ImplTraitPosition::FnTraitReturn => "the return type of `Fn` trait bounds",
|
||||
ImplTraitPosition::GenericDefault => "generic parameter defaults",
|
||||
ImplTraitPosition::ConstTy => "const types",
|
||||
ImplTraitPosition::StaticTy => "static types",
|
||||
ImplTraitPosition::AssocTy => "associated types",
|
||||
ImplTraitPosition::FieldTy => "field types",
|
||||
ImplTraitPosition::Cast => "cast types",
|
||||
ImplTraitPosition::Cast => "cast expression types",
|
||||
ImplTraitPosition::ImplSelf => "impl headers",
|
||||
ImplTraitPosition::OffsetOf => "`offset_of!` params",
|
||||
ImplTraitPosition::OffsetOf => "`offset_of!` parameters",
|
||||
};
|
||||
|
||||
write!(f, "{name}")
|
||||
|
|
@ -364,19 +360,6 @@ enum FnDeclKind {
|
|||
Impl,
|
||||
}
|
||||
|
||||
impl FnDeclKind {
|
||||
fn param_impl_trait_allowed(&self) -> bool {
|
||||
matches!(self, FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait)
|
||||
}
|
||||
|
||||
fn return_impl_trait_allowed(&self) -> bool {
|
||||
match self {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum AstOwner<'a> {
|
||||
NonOwner,
|
||||
|
|
@ -1842,19 +1825,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
inputs = &inputs[..inputs.len() - 1];
|
||||
}
|
||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
||||
let itctx = if kind.param_impl_trait_allowed() {
|
||||
ImplTraitContext::Universal
|
||||
} else {
|
||||
ImplTraitContext::Disallowed(match kind {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||
unreachable!("fn should allow APIT")
|
||||
}
|
||||
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
|
||||
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
|
||||
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
|
||||
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
|
||||
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
|
||||
})
|
||||
let itctx = match kind {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => {
|
||||
ImplTraitContext::Universal
|
||||
}
|
||||
FnDeclKind::ExternFn => {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam)
|
||||
}
|
||||
FnDeclKind::Closure => {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam)
|
||||
}
|
||||
FnDeclKind::Pointer => {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam)
|
||||
}
|
||||
};
|
||||
self.lower_ty_direct(¶m.ty, &itctx)
|
||||
}));
|
||||
|
|
@ -1866,26 +1849,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
None => match &decl.output {
|
||||
FnRetTy::Ty(ty) => {
|
||||
let context = if kind.return_impl_trait_allowed() {
|
||||
let fn_def_id = self.local_def_id(fn_node_id);
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
let itctx = match kind {
|
||||
FnDeclKind::Fn
|
||||
| FnDeclKind::Inherent
|
||||
| FnDeclKind::Trait
|
||||
| FnDeclKind::Impl => ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)),
|
||||
fn_kind: kind,
|
||||
},
|
||||
FnDeclKind::ExternFn => {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn)
|
||||
}
|
||||
FnDeclKind::Closure => {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ClosureReturn)
|
||||
}
|
||||
FnDeclKind::Pointer => {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn)
|
||||
}
|
||||
} else {
|
||||
ImplTraitContext::Disallowed(match kind {
|
||||
FnDeclKind::Fn
|
||||
| FnDeclKind::Inherent
|
||||
| FnDeclKind::Trait
|
||||
| FnDeclKind::Impl => {
|
||||
unreachable!("fn should allow return-position impl trait in traits")
|
||||
}
|
||||
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn,
|
||||
FnDeclKind::Closure => ImplTraitPosition::ClosureReturn,
|
||||
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
||||
})
|
||||
};
|
||||
hir::FnRetTy::Return(self.lower_ty(ty, &context))
|
||||
hir::FnRetTy::Return(self.lower_ty(ty, &itctx))
|
||||
}
|
||||
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ macro_rules! gate {
|
|||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
|
||||
.help($help)
|
||||
.help_mv($help)
|
||||
.emit();
|
||||
}
|
||||
}};
|
||||
|
|
|
|||
|
|
@ -54,13 +54,12 @@ pub(crate) struct UnknownMetaItem<'a> {
|
|||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item);
|
||||
diag.span(self.span);
|
||||
diag.code(error_code!(E0541));
|
||||
diag.arg("item", self.item);
|
||||
diag.arg("expected", expected.join(", "));
|
||||
diag.span_label(self.span, fluent::attr_label);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item)
|
||||
.span_mv(self.span)
|
||||
.code_mv(error_code!(E0541))
|
||||
.arg_mv("item", self.item)
|
||||
.arg_mv("expected", expected.join(", "))
|
||||
.span_label_mv(self.span, fluent::attr_label)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,17 +31,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
borrow_span: Span,
|
||||
borrow_desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0503,
|
||||
"cannot use {} because it was mutably borrowed",
|
||||
desc,
|
||||
);
|
||||
|
||||
err.span_label(borrow_span, format!("{borrow_desc} is borrowed here"));
|
||||
err.span_label(span, format!("use of borrowed {borrow_desc}"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(borrow_span, format!("{borrow_desc} is borrowed here"))
|
||||
.span_label_mv(span, format!("use of borrowed {borrow_desc}"))
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_mutably_borrow_multiply(
|
||||
|
|
@ -238,17 +236,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
borrow_span: Span,
|
||||
desc: &str,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0506,
|
||||
"cannot assign to {} because it is borrowed",
|
||||
desc,
|
||||
);
|
||||
|
||||
err.span_label(borrow_span, format!("{desc} is borrowed here"));
|
||||
err.span_label(span, format!("{desc} is assigned to here but it was already borrowed"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(borrow_span, format!("{desc} is borrowed here"))
|
||||
.span_label_mv(span, format!("{desc} is assigned to here but it was already borrowed"))
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_reassign_immutable(
|
||||
|
|
@ -287,16 +283,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
(&ty::Slice(_), _) => "slice",
|
||||
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
|
||||
};
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
E0508,
|
||||
"cannot move out of type `{}`, a non-copy {}",
|
||||
ty,
|
||||
type_name,
|
||||
);
|
||||
err.span_label(move_from_span, "cannot move out of here");
|
||||
err
|
||||
)
|
||||
.span_label_mv(move_from_span, "cannot move out of here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_move_out_of_interior_of_drop(
|
||||
|
|
@ -304,15 +299,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
move_from_span: Span,
|
||||
container_ty: Ty<'_>,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
E0509,
|
||||
"cannot move out of type `{}`, which implements the `Drop` trait",
|
||||
container_ty,
|
||||
);
|
||||
err.span_label(move_from_span, "cannot move out of here");
|
||||
err
|
||||
)
|
||||
.span_label_mv(move_from_span, "cannot move out of here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_act_on_moved_value(
|
||||
|
|
@ -352,7 +346,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
immutable_section: &str,
|
||||
action: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
mutate_span,
|
||||
E0510,
|
||||
|
|
@ -360,10 +354,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
action,
|
||||
immutable_place,
|
||||
immutable_section,
|
||||
);
|
||||
err.span_label(mutate_span, format!("cannot {action}"));
|
||||
err.span_label(immutable_span, format!("value is immutable in {immutable_section}"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(mutate_span, format!("cannot {action}"))
|
||||
.span_label_mv(immutable_span, format!("value is immutable in {immutable_section}"))
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_coroutine_yield(
|
||||
|
|
@ -372,14 +365,13 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
yield_span: Span,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0626,
|
||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
||||
);
|
||||
err.span_label(yield_span, "possible yield occurs here");
|
||||
err
|
||||
)
|
||||
.span_label_mv(yield_span, "possible yield occurs here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_destructor(
|
||||
|
|
@ -409,7 +401,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
reference_desc: &str,
|
||||
path_desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0515,
|
||||
|
|
@ -417,14 +409,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
RETURN = return_kind,
|
||||
REFERENCE = reference_desc,
|
||||
LOCAL = path_desc,
|
||||
);
|
||||
|
||||
err.span_label(
|
||||
)
|
||||
.span_label_mv(
|
||||
span,
|
||||
format!("{return_kind}s a {reference_desc} data owned by the current function"),
|
||||
);
|
||||
|
||||
err
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_capture_in_long_lived_closure(
|
||||
|
|
@ -435,16 +424,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
capture_span: Span,
|
||||
scope: &str,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.dcx(),
|
||||
closure_span,
|
||||
E0373,
|
||||
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
|
||||
which is owned by the current {scope}",
|
||||
);
|
||||
err.span_label(capture_span, format!("{borrowed_path} is borrowed here"))
|
||||
.span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"));
|
||||
err
|
||||
)
|
||||
.span_label_mv(capture_span, format!("{borrowed_path} is borrowed here"))
|
||||
.span_label_mv(closure_span, format!("may outlive borrowed value {borrowed_path}"))
|
||||
}
|
||||
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(
|
||||
|
|
|
|||
|
|
@ -2218,15 +2218,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
drop_span, borrow_span
|
||||
);
|
||||
|
||||
let mut err = self.thread_local_value_does_not_live_long_enough(borrow_span);
|
||||
|
||||
err.span_label(
|
||||
borrow_span,
|
||||
"thread-local variables cannot be borrowed beyond the end of the function",
|
||||
);
|
||||
err.span_label(drop_span, "end of enclosing function is here");
|
||||
|
||||
err
|
||||
self.thread_local_value_does_not_live_long_enough(borrow_span)
|
||||
.span_label_mv(
|
||||
borrow_span,
|
||||
"thread-local variables cannot be borrowed beyond the end of the function",
|
||||
)
|
||||
.span_label_mv(drop_span, "end of enclosing function is here")
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
|
|
|||
|
|
@ -329,15 +329,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if let PlaceRef { local, projection: [] } = deref_base {
|
||||
let decl = &self.body.local_decls[local];
|
||||
if decl.is_ref_for_guard() {
|
||||
let mut err = self.cannot_move_out_of(
|
||||
span,
|
||||
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
|
||||
);
|
||||
err.note(
|
||||
"variables bound in patterns cannot be moved from \
|
||||
return self
|
||||
.cannot_move_out_of(
|
||||
span,
|
||||
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
|
||||
)
|
||||
.note_mv(
|
||||
"variables bound in patterns cannot be moved from \
|
||||
until after the end of the pattern guard",
|
||||
);
|
||||
return err;
|
||||
);
|
||||
} else if decl.is_ref_to_static() {
|
||||
return self.report_cannot_move_from_static(move_place, span);
|
||||
}
|
||||
|
|
@ -381,15 +381,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
closure_kind_ty, closure_kind, place_description,
|
||||
);
|
||||
|
||||
let mut diag = self.cannot_move_out_of(span, &place_description);
|
||||
|
||||
diag.span_label(upvar_span, "captured outer variable");
|
||||
diag.span_label(
|
||||
self.infcx.tcx.def_span(def_id),
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
);
|
||||
|
||||
diag
|
||||
self.cannot_move_out_of(span, &place_description)
|
||||
.span_label_mv(upvar_span, "captured outer variable")
|
||||
.span_label_mv(
|
||||
self.infcx.tcx.def_span(def_id),
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let source = self.borrowed_content_source(deref_base);
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
||||
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
let mut diag = unexpected_hidden_region_diagnostic(
|
||||
let diag = unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
span,
|
||||
named_ty,
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ fn check_opaque_type_parameter_valid(
|
|||
return Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.span_note(spans, format!("{descr} used multiple times"))
|
||||
.span_note_mv(spans, format!("{descr} used multiple times"))
|
||||
.emit());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||
match expr_to_spanned_string(ecx, template_expr, msg) {
|
||||
Ok(template_part) => template_part,
|
||||
Err(err) => {
|
||||
if let Some((mut err, _)) = err {
|
||||
if let Some((err, _)) = err {
|
||||
err.emit();
|
||||
}
|
||||
return None;
|
||||
|
|
@ -693,13 +693,14 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||
0 => {}
|
||||
1 => {
|
||||
let (sp, msg) = unused_operands.into_iter().next().unwrap();
|
||||
let mut err = ecx.dcx().struct_span_err(sp, msg);
|
||||
err.span_label(sp, msg);
|
||||
err.help(format!(
|
||||
"if this argument is intentionally unused, \
|
||||
consider using it in an asm comment: `\"/*{help_str} */\"`"
|
||||
));
|
||||
err.emit();
|
||||
ecx.dcx()
|
||||
.struct_span_err(sp, msg)
|
||||
.span_label_mv(sp, msg)
|
||||
.help_mv(format!(
|
||||
"if this argument is intentionally unused, \
|
||||
consider using it in an asm comment: `\"/*{help_str} */\"`"
|
||||
))
|
||||
.emit();
|
||||
}
|
||||
_ => {
|
||||
let mut err = ecx.dcx().struct_span_err(
|
||||
|
|
@ -747,7 +748,7 @@ pub(super) fn expand_asm<'cx>(
|
|||
};
|
||||
MacEager::expr(expr)
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
|
@ -779,7 +780,7 @@ pub(super) fn expand_global_asm<'cx>(
|
|||
DummyResult::any(sp)
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub fn expand_assert<'cx>(
|
|||
) -> Box<dyn MacResult + 'cx> {
|
||||
let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
|
||||
Ok(assert) => assert,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub fn expand_cfg(
|
|||
);
|
||||
MacEager::expr(cx.expr_bool(sp, matches_cfg))
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ impl CfgEval<'_, '_> {
|
|||
parser.capture_cfg = true;
|
||||
match parse_annotatable_with(&mut parser) {
|
||||
Ok(a) => annotatable = a,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return Some(annotatable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
|
|||
let start_span = parser.token.span;
|
||||
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
Ok(ai) => ai,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -803,24 +803,23 @@ pub(crate) struct AsmClobberNoReg {
|
|||
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_no_reg,
|
||||
);
|
||||
diag.span(self.spans.clone());
|
||||
// eager translation as `span_labels` takes `AsRef<str>`
|
||||
let lbl1 = dcx.eagerly_translate_to_string(
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_abi,
|
||||
[].into_iter(),
|
||||
);
|
||||
diag.span_labels(self.clobbers, &lbl1);
|
||||
let lbl2 = dcx.eagerly_translate_to_string(
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_outputs,
|
||||
[].into_iter(),
|
||||
);
|
||||
diag.span_labels(self.spans, &lbl2);
|
||||
diag
|
||||
DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
crate::fluent_generated::builtin_macros_asm_clobber_no_reg,
|
||||
)
|
||||
.span_mv(self.spans.clone())
|
||||
.span_labels_mv(self.clobbers, &lbl1)
|
||||
.span_labels_mv(self.spans, &lbl2)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
|||
}
|
||||
|
||||
match p.expect(&token::Comma) {
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
match token::TokenKind::Comma.similar_tokens() {
|
||||
Some(tks) if tks.contains(&p.token.kind) => {
|
||||
// If a similar token is found, then it may be a typo. We
|
||||
|
|
@ -630,8 +630,7 @@ fn report_missing_placeholders(
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
if !placeholders.is_empty() {
|
||||
if let Some(mut new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders)
|
||||
{
|
||||
if let Some(new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders) {
|
||||
diag.cancel();
|
||||
new_diag.emit();
|
||||
return;
|
||||
|
|
@ -976,7 +975,7 @@ fn expand_format_args_impl<'cx>(
|
|||
MacEager::expr(DummyResult::raw_expr(sp, true))
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
DummyResult::any(sp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||
|
||||
self.dcx
|
||||
.struct_span_err(attr.span, msg)
|
||||
.span_label(prev_attr.span, "previous attribute here")
|
||||
.span_label_mv(prev_attr.span, "previous attribute here")
|
||||
.emit();
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ pub fn expand_include<'cx>(
|
|||
// The file will be added to the code map by the parser
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ pub fn expand_include<'cx>(
|
|||
let mut ret = SmallVec::new();
|
||||
loop {
|
||||
match self.p.parse_item(ForceCollect::No) {
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ pub fn expand_include_str(
|
|||
};
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ pub fn expand_include_bytes(
|
|||
};
|
||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -409,8 +409,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
|
|||
),
|
||||
);
|
||||
}
|
||||
err.span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
|
||||
.span_suggestion(attr_sp,
|
||||
err.span_label_mv(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
|
||||
.span_suggestion_mv(attr_sp,
|
||||
"replace with conditional compilation to make the item only exist when tests are being run",
|
||||
"#[cfg(test)]",
|
||||
Applicability::MaybeIncorrect)
|
||||
|
|
@ -480,7 +480,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
|
|||
"argument must be of the form: \
|
||||
`expected = \"error message\"`",
|
||||
)
|
||||
.note(
|
||||
.note_mv(
|
||||
"errors in this attribute were erroneously \
|
||||
allowed and will become a hard error in a \
|
||||
future release",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub fn expand_type_ascribe(
|
|||
) -> Box<dyn base::MacResult + 'static> {
|
||||
let (expr, ty) = match parse_ascribe(cx, tts) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,9 @@ fn start<T: Termination + 'static>(
|
|||
}
|
||||
|
||||
static mut NUM: u8 = 6 * 7;
|
||||
|
||||
// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
|
||||
#[allow(static_mut_ref)]
|
||||
static NUM_REF: &'static u8 = unsafe { &NUM };
|
||||
|
||||
unsafe fn zeroed<T>() -> T {
|
||||
|
|
|
|||
|
|
@ -68,15 +68,7 @@ impl DebugContext {
|
|||
// In order to have a good line stepping behavior in debugger, we overwrite debug
|
||||
// locations of macro expansions with that of the outermost expansion site (when the macro is
|
||||
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
||||
let span = if tcx.should_collapse_debuginfo(span) {
|
||||
span
|
||||
} else {
|
||||
// Walk up the macro expansion chain until we reach a non-expanded span.
|
||||
// We also stop at the function body level because no line stepping can occur
|
||||
// at the level above that.
|
||||
rustc_span::hygiene::walk_chain(span, function_span.ctxt())
|
||||
};
|
||||
|
||||
let span = tcx.collapsed_debuginfo(span, function_span);
|
||||
match tcx.sess.source_map().lookup_line(span.lo()) {
|
||||
Ok(SourceFileAndLine { sf: file, line }) => {
|
||||
let line_pos = file.lines()[line];
|
||||
|
|
|
|||
|
|
@ -321,9 +321,10 @@ fn dep_symbol_lookup_fn(
|
|||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static => {
|
||||
let name = crate_info.crate_name[&cnum];
|
||||
let mut err = sess.dcx().struct_err(format!("Can't load static lib {}", name));
|
||||
err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
|
||||
err.emit();
|
||||
sess.dcx()
|
||||
.struct_err(format!("Can't load static lib {}", name))
|
||||
.note("rustc_codegen_cranelift can only load dylibs in JIT mode.")
|
||||
.emit();
|
||||
}
|
||||
Linkage::Dynamic => {
|
||||
dylib_paths.push(src.dylib.as_ref().unwrap().0.clone());
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ fn start<T: Termination + 'static>(
|
|||
}
|
||||
|
||||
static mut NUM: u8 = 6 * 7;
|
||||
|
||||
// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
|
||||
#[allow(static_mut_ref)]
|
||||
static NUM_REF: &'static u8 = unsafe { &NUM };
|
||||
|
||||
macro_rules! assert {
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@ fn create_wrapper_function(
|
|||
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
|
||||
}
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
let uwtable = attributes::uwtable_attr(llcx);
|
||||
let uwtable =
|
||||
attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
|
||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,11 +95,12 @@ pub fn sanitize_attrs<'ll>(
|
|||
|
||||
/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
|
||||
#[inline]
|
||||
pub fn uwtable_attr(llcx: &llvm::Context) -> &Attribute {
|
||||
pub fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option<bool>) -> &Attribute {
|
||||
// NOTE: We should determine if we even need async unwind tables, as they
|
||||
// take have more overhead and if we can use sync unwind tables we
|
||||
// probably should.
|
||||
llvm::CreateUWTableAttr(llcx, true)
|
||||
let async_unwind = !use_sync_unwind.unwrap_or(false);
|
||||
llvm::CreateUWTableAttr(llcx, async_unwind)
|
||||
}
|
||||
|
||||
pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
|
||||
|
|
@ -333,7 +334,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||
// You can also find more info on why Windows always requires uwtables here:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
|
||||
if cx.sess().must_emit_unwind_tables() {
|
||||
to_add.push(uwtable_attr(cx.llcx));
|
||||
to_add.push(uwtable_attr(cx.llcx, cx.sess().opts.unstable_opts.use_sync_unwind));
|
||||
}
|
||||
|
||||
if cx.sess().opts.unstable_opts.profile_sample_use.is_some() {
|
||||
|
|
|
|||
|
|
@ -105,10 +105,8 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_
|
|||
let (message, _) = diag.messages().first().expect("`LlvmError` with no message");
|
||||
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
|
||||
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config);
|
||||
diag.arg("error", message);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
|
||||
.arg_mv("error", message)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,10 +202,10 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> {
|
|||
PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
|
||||
ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
|
||||
};
|
||||
let mut diag = self.0.into_diagnostic(dcx, level);
|
||||
diag.primary_message(msg_with_llvm_err);
|
||||
diag.arg("llvm_err", self.1);
|
||||
diag
|
||||
self.0
|
||||
.into_diagnostic(dcx, level)
|
||||
.primary_message_mv(msg_with_llvm_err)
|
||||
.arg_mv("llvm_err", self.1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -303,14 +303,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
// This exception needs to be kept in sync with allowing
|
||||
// `#[target_feature]` on `main` and `start`.
|
||||
} else if !tcx.features().target_feature_11 {
|
||||
let mut err = feature_err(
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::target_feature_11,
|
||||
attr.span,
|
||||
"`#[target_feature(..)]` can only be applied to `unsafe` functions",
|
||||
);
|
||||
err.span_label(tcx.def_span(did), "not an `unsafe` function");
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(tcx.def_span(did), "not an `unsafe` function")
|
||||
.emit();
|
||||
} else {
|
||||
check_target_feature_trait_unsafe(tcx, did, attr.span);
|
||||
}
|
||||
|
|
@ -477,7 +477,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
InlineAttr::Never
|
||||
} else {
|
||||
struct_span_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
|
||||
.help("valid inline arguments are `always` and `never`")
|
||||
.help_mv("valid inline arguments are `always` and `never`")
|
||||
.emit();
|
||||
|
||||
InlineAttr::None
|
||||
|
|
@ -662,7 +662,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
|
|||
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
|
||||
tcx.dcx()
|
||||
.struct_span_err(attr.span, msg)
|
||||
.note("the value may not exceed `u16::MAX`")
|
||||
.note_mv("the value may not exceed `u16::MAX`")
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,192 +212,124 @@ pub struct ThorinErrorWrapper(pub thorin::Error);
|
|||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let build = |msg| DiagnosticBuilder::new(dcx, level, msg);
|
||||
let mut diag;
|
||||
match self.0 {
|
||||
thorin::Error::ReadInput(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_read_input_failure);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ReadInput(_) => build(fluent::codegen_ssa_thorin_read_input_failure),
|
||||
thorin::Error::ParseFileKind(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_input_file_kind)
|
||||
}
|
||||
thorin::Error::ParseObjectFile(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_object_file);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_input_object_file)
|
||||
}
|
||||
thorin::Error::ParseArchiveFile(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_input_archive_file)
|
||||
}
|
||||
thorin::Error::ParseArchiveMember(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_archive_member);
|
||||
diag
|
||||
}
|
||||
thorin::Error::InvalidInputKind => {
|
||||
diag = build(fluent::codegen_ssa_thorin_invalid_input_kind);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DecompressData(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_decompress_data);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_archive_member)
|
||||
}
|
||||
thorin::Error::InvalidInputKind => build(fluent::codegen_ssa_thorin_invalid_input_kind),
|
||||
thorin::Error::DecompressData(_) => build(fluent::codegen_ssa_thorin_decompress_data),
|
||||
thorin::Error::NamelessSection(_, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_section_without_name);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_section_without_name)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::MultipleRelocations(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_relocations);
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_multiple_relocations)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::UnsupportedRelocation(section, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_unsupported_relocation);
|
||||
diag.arg("section", section);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_dwo_name);
|
||||
diag.arg("id", format!("0x{id:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_unsupported_relocation)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => build(fluent::codegen_ssa_thorin_missing_dwo_name)
|
||||
.arg_mv("id", format!("0x{id:08x}")),
|
||||
thorin::Error::NoCompilationUnits => {
|
||||
diag = build(fluent::codegen_ssa_thorin_no_compilation_units);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoDie => {
|
||||
diag = build(fluent::codegen_ssa_thorin_no_die);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_no_compilation_units)
|
||||
}
|
||||
thorin::Error::NoDie => build(fluent::codegen_ssa_thorin_no_die),
|
||||
thorin::Error::TopLevelDieNotUnit => {
|
||||
diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_top_level_die_not_unit)
|
||||
}
|
||||
thorin::Error::MissingRequiredSection(section) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_required_section);
|
||||
diag.arg("section", section);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_missing_required_section)
|
||||
.arg_mv("section", section)
|
||||
}
|
||||
thorin::Error::ParseUnitAbbreviations(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_unit_abbreviations)
|
||||
}
|
||||
thorin::Error::ParseUnitAttribute(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_unit_attribute)
|
||||
}
|
||||
thorin::Error::ParseUnitHeader(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_header);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnit(_) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_unit_header)
|
||||
}
|
||||
thorin::Error::ParseUnit(_) => build(fluent::codegen_ssa_thorin_parse_unit),
|
||||
thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_incompatible_index_version);
|
||||
diag.arg("section", section);
|
||||
diag.arg("actual", actual);
|
||||
diag.arg("format", format);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_incompatible_index_version)
|
||||
.arg_mv("section", section)
|
||||
.arg_mv("actual", actual)
|
||||
.arg_mv("format", format)
|
||||
}
|
||||
thorin::Error::OffsetAtIndex(_, index) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_offset_at_index);
|
||||
diag.arg("index", index);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_offset_at_index).arg_mv("index", index)
|
||||
}
|
||||
thorin::Error::StrAtOffset(_, offset) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_str_at_offset);
|
||||
diag.arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_str_at_offset)
|
||||
.arg_mv("offset", format!("0x{offset:08x}"))
|
||||
}
|
||||
thorin::Error::ParseIndex(_, section) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_index);
|
||||
diag.arg("section", section);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_parse_index).arg_mv("section", section)
|
||||
}
|
||||
thorin::Error::UnitNotInIndex(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_unit_not_in_index);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_unit_not_in_index)
|
||||
.arg_mv("unit", format!("0x{unit:08x}"))
|
||||
}
|
||||
thorin::Error::RowNotInIndex(_, row) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_row_not_in_index);
|
||||
diag.arg("row", row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::SectionNotInRow => {
|
||||
diag = build(fluent::codegen_ssa_thorin_section_not_in_row);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_row_not_in_index).arg_mv("row", row)
|
||||
}
|
||||
thorin::Error::SectionNotInRow => build(fluent::codegen_ssa_thorin_section_not_in_row),
|
||||
thorin::Error::EmptyUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_empty_unit);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_empty_unit).arg_mv("unit", format!("0x{unit:08x}"))
|
||||
}
|
||||
thorin::Error::MultipleDebugInfoSection => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_multiple_debug_info_section)
|
||||
}
|
||||
thorin::Error::MultipleDebugTypesSection => {
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NotSplitUnit => {
|
||||
diag = build(fluent::codegen_ssa_thorin_not_split_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DuplicateUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_duplicate_unit);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_multiple_debug_types_section)
|
||||
}
|
||||
thorin::Error::NotSplitUnit => build(fluent::codegen_ssa_thorin_not_split_unit),
|
||||
thorin::Error::DuplicateUnit(unit) => build(fluent::codegen_ssa_thorin_duplicate_unit)
|
||||
.arg_mv("unit", format!("0x{unit:08x}")),
|
||||
thorin::Error::MissingReferencedUnit(unit) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit);
|
||||
diag.arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_missing_referenced_unit)
|
||||
.arg_mv("unit", format!("0x{unit:08x}"))
|
||||
}
|
||||
thorin::Error::NoOutputObjectCreated => {
|
||||
diag = build(fluent::codegen_ssa_thorin_not_output_object_created);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_not_output_object_created)
|
||||
}
|
||||
thorin::Error::MixedInputEncodings => {
|
||||
diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings);
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_mixed_input_encodings)
|
||||
}
|
||||
thorin::Error::Io(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_io);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_io).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::ObjectRead(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_object_read);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_object_read).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::ObjectWrite(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_object_write);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_object_write).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::GimliRead(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_read);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_gimli_read).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
thorin::Error::GimliWrite(e) => {
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_write);
|
||||
diag.arg("error", format!("{e}"));
|
||||
diag
|
||||
build(fluent::codegen_ssa_thorin_gimli_write).arg_mv("error", format!("{e}"))
|
||||
}
|
||||
_ => unimplemented!("Untranslated thorin error"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,21 +228,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
/// In order to have a good line stepping behavior in debugger, we overwrite debug
|
||||
/// locations of macro expansions with that of the outermost expansion site (when the macro is
|
||||
/// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
||||
fn adjust_span_for_debugging(&self, mut span: Span) -> Span {
|
||||
fn adjust_span_for_debugging(&self, span: Span) -> Span {
|
||||
// Bail out if debug info emission is not enabled.
|
||||
if self.debug_context.is_none() {
|
||||
return span;
|
||||
}
|
||||
|
||||
if self.cx.tcx().should_collapse_debuginfo(span) {
|
||||
// Walk up the macro expansion chain until we reach a non-expanded span.
|
||||
// We also stop at the function body level because no line stepping can occur
|
||||
// at the level above that.
|
||||
// Use span of the outermost expansion site, while keeping the original lexical scope.
|
||||
span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
|
||||
}
|
||||
|
||||
span
|
||||
// Walk up the macro expansion chain until we reach a non-expanded span.
|
||||
// We also stop at the function body level because no line stepping can occur
|
||||
// at the level above that.
|
||||
// Use span of the outermost expansion site, while keeping the original lexical scope.
|
||||
self.cx.tcx().collapsed_debuginfo(span, self.mir.span)
|
||||
}
|
||||
|
||||
fn spill_operand_to_stack(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub fn from_target_feature(
|
|||
let code = "enable = \"..\"";
|
||||
tcx.dcx()
|
||||
.struct_span_err(span, msg)
|
||||
.span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
|
||||
.span_suggestion_mv(span, "must be of the form", code, Applicability::HasPlaceholders)
|
||||
.emit();
|
||||
};
|
||||
let rust_features = tcx.features();
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut err = op.build_error(self.ccx, span);
|
||||
let err = op.build_error(self.ccx, span);
|
||||
assert!(err.is_error());
|
||||
|
||||
match op.importance() {
|
||||
|
|
|
|||
|
|
@ -157,9 +157,7 @@ impl Qualif for NeedsNonConstDrop {
|
|||
// FIXME(effects): If `destruct` is not a `const_trait`,
|
||||
// or effects are disabled in this crate, then give up.
|
||||
let destruct_def_id = cx.tcx.require_lang_item(LangItem::Destruct, Some(cx.body.span));
|
||||
if cx.tcx.generics_of(destruct_def_id).host_effect_index.is_none()
|
||||
|| !cx.tcx.features().effects
|
||||
{
|
||||
if !cx.tcx.has_host_param(destruct_def_id) || !cx.tcx.features().effects {
|
||||
return NeedsDrop::in_any_value_of_ty(cx, ty);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
pub mod check_consts;
|
||||
pub mod promote_consts;
|
||||
pub mod validate;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ pub type StdEntry<'a, K, V> = std::collections::hash_map::Entry<'a, K, V>;
|
|||
pub type FxIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
|
||||
pub type IndexEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>;
|
||||
pub type IndexOccupiedEntry<'a, K, V> = indexmap::map::OccupiedEntry<'a, K, V>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! define_id_collections {
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@ impl<Node: Idx> Dominators<Node> {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if `b` is unreachable.
|
||||
#[inline]
|
||||
pub fn dominates(&self, a: Node, b: Node) -> bool {
|
||||
match &self.kind {
|
||||
Kind::Path => a.index() <= b.index(),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub use index_map::SortedIndexMultiMap;
|
|||
/// stores data in a more compact way. It also supports accessing contiguous
|
||||
/// ranges of elements as a slice, and slices of already sorted elements can be
|
||||
/// inserted efficiently.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable_Generic, Decodable_Generic)]
|
||||
pub struct SortedMap<K, V> {
|
||||
data: Vec<(K, V)>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use std::fmt;
|
|||
|
||||
use crate::stable_hasher;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, Hash)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable_Generic, Decodable_Generic, Hash)]
|
||||
pub struct Svh {
|
||||
hash: Fingerprint,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,9 +56,6 @@ mod parallel;
|
|||
pub use parallel::scope;
|
||||
pub use parallel::{join, par_for_each_in, par_map, parallel_guard, try_par_for_each_in};
|
||||
|
||||
pub use std::sync::atomic::Ordering;
|
||||
pub use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
pub use vec::{AppendOnlyIndexVec, AppendOnlyVec};
|
||||
|
||||
mod vec;
|
||||
|
|
@ -67,8 +64,7 @@ mod freeze;
|
|||
pub use freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
|
||||
|
||||
mod mode {
|
||||
use super::Ordering;
|
||||
use std::sync::atomic::AtomicU8;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
const UNINITIALIZED: u8 = 0;
|
||||
const DYN_NOT_THREAD_SAFE: u8 = 1;
|
||||
|
|
@ -113,6 +109,7 @@ cfg_match! {
|
|||
cfg(not(parallel_compiler)) => {
|
||||
use std::ops::Add;
|
||||
use std::cell::Cell;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub unsafe auto trait Send {}
|
||||
pub unsafe auto trait Sync {}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ trait UnordCollection {}
|
|||
///
|
||||
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
|
||||
/// for more information.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Encodable_Generic, Decodable_Generic)]
|
||||
pub struct UnordSet<V: Eq + Hash> {
|
||||
inner: FxHashSet<V>,
|
||||
}
|
||||
|
|
@ -417,7 +417,7 @@ impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
|
|||
///
|
||||
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
|
||||
/// for more information.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Encodable_Generic, Decodable_Generic)]
|
||||
pub struct UnordMap<K: Eq + Hash, V> {
|
||||
inner: FxHashMap<K, V>,
|
||||
}
|
||||
|
|
@ -626,7 +626,7 @@ impl<HCX, K: Hash + Eq + HashStable<HCX>, V: HashStable<HCX>> HashStable<HCX> fo
|
|||
///
|
||||
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
|
||||
/// for more information.
|
||||
#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
|
||||
#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable_Generic, Decodable_Generic)]
|
||||
pub struct UnordBag<V> {
|
||||
inner: Vec<V>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ rustc_target = { path = "../rustc_target" }
|
|||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||
serde_json = "1.0.59"
|
||||
shlex = "1.0"
|
||||
time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] }
|
||||
tracing = { version = "0.1.35" }
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -5,18 +5,92 @@ use std::io;
|
|||
|
||||
use rustc_session::EarlyDiagCtxt;
|
||||
|
||||
fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
|
||||
if let Some(path) = arg.strip_prefix('@') {
|
||||
let file = match fs::read_to_string(path) {
|
||||
Ok(file) => file,
|
||||
Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
|
||||
return Err(Error::Utf8Error(Some(path.to_string())));
|
||||
/// Expands argfiles in command line arguments.
|
||||
#[derive(Default)]
|
||||
struct Expander {
|
||||
shell_argfiles: bool,
|
||||
next_is_unstable_option: bool,
|
||||
expanded: Vec<String>,
|
||||
}
|
||||
|
||||
impl Expander {
|
||||
/// Handles the next argument. If the argument is an argfile, it is expanded
|
||||
/// inline.
|
||||
fn arg(&mut self, arg: &str) -> Result<(), Error> {
|
||||
if let Some(argfile) = arg.strip_prefix('@') {
|
||||
match argfile.split_once(':') {
|
||||
Some(("shell", path)) if self.shell_argfiles => {
|
||||
shlex::split(&Self::read_file(path)?)
|
||||
.ok_or_else(|| Error::ShellParseError(path.to_string()))?
|
||||
.into_iter()
|
||||
.for_each(|arg| self.push(arg));
|
||||
}
|
||||
_ => {
|
||||
let contents = Self::read_file(argfile)?;
|
||||
contents.lines().for_each(|arg| self.push(arg.to_string()));
|
||||
}
|
||||
}
|
||||
Err(err) => return Err(Error::IOError(path.to_string(), err)),
|
||||
};
|
||||
Ok(file.lines().map(ToString::to_string).collect())
|
||||
} else {
|
||||
Ok(vec![arg])
|
||||
} else {
|
||||
self.push(arg.to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds a command line argument verbatim with no argfile expansion.
|
||||
fn push(&mut self, arg: String) {
|
||||
// Unfortunately, we have to do some eager argparsing to handle unstable
|
||||
// options which change the behavior of argfile arguments.
|
||||
//
|
||||
// Normally, all of the argfile arguments (e.g. `@args.txt`) are
|
||||
// expanded into our arguments list *and then* the whole list of
|
||||
// arguments are passed on to be parsed. However, argfile parsing
|
||||
// options like `-Zshell_argfiles` need to change the behavior of that
|
||||
// argument expansion. So we have to do a little parsing on our own here
|
||||
// instead of leaning on the existing logic.
|
||||
//
|
||||
// All we care about are unstable options, so we parse those out and
|
||||
// look for any that affect how we expand argfiles. This argument
|
||||
// inspection is very conservative; we only change behavior when we see
|
||||
// exactly the options we're looking for and everything gets passed
|
||||
// through.
|
||||
|
||||
if self.next_is_unstable_option {
|
||||
self.inspect_unstable_option(&arg);
|
||||
self.next_is_unstable_option = false;
|
||||
} else if let Some(unstable_option) = arg.strip_prefix("-Z") {
|
||||
if unstable_option.is_empty() {
|
||||
self.next_is_unstable_option = true;
|
||||
} else {
|
||||
self.inspect_unstable_option(unstable_option);
|
||||
}
|
||||
}
|
||||
|
||||
self.expanded.push(arg);
|
||||
}
|
||||
|
||||
/// Consumes the `Expander`, returning the expanded arguments.
|
||||
fn finish(self) -> Vec<String> {
|
||||
self.expanded
|
||||
}
|
||||
|
||||
/// Parses any relevant unstable flags specified on the command line.
|
||||
fn inspect_unstable_option(&mut self, option: &str) {
|
||||
match option {
|
||||
"shell-argfiles" => self.shell_argfiles = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the contents of a file as UTF-8.
|
||||
fn read_file(path: &str) -> Result<String, Error> {
|
||||
fs::read_to_string(path).map_err(|e| {
|
||||
if e.kind() == io::ErrorKind::InvalidData {
|
||||
Error::Utf8Error(Some(path.to_string()))
|
||||
} else {
|
||||
Error::IOError(path.to_string(), e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -24,20 +98,20 @@ fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
|
|||
/// If this function is intended to be used with command line arguments,
|
||||
/// `argv[0]` must be removed prior to calling it manually.
|
||||
pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> {
|
||||
let mut args = Vec::new();
|
||||
let mut expander = Expander::default();
|
||||
for arg in at_args {
|
||||
match arg_expand(arg.clone()) {
|
||||
Ok(arg) => args.extend(arg),
|
||||
Err(err) => early_dcx.early_fatal(format!("Failed to load argument file: {err}")),
|
||||
if let Err(err) = expander.arg(arg) {
|
||||
early_dcx.early_fatal(format!("Failed to load argument file: {err}"));
|
||||
}
|
||||
}
|
||||
args
|
||||
expander.finish()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Utf8Error(Option<String>),
|
||||
IOError(String, io::Error),
|
||||
ShellParseError(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
|
|
@ -46,6 +120,7 @@ impl fmt::Display for Error {
|
|||
Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
|
||||
Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
|
||||
Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
|
||||
Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
|
|||
use rustc_data_structures::profiling::{
|
||||
get_resident_set_size, print_time_passes_entry, TimePassesFormat,
|
||||
};
|
||||
use rustc_data_structures::sync::SeqCst;
|
||||
use rustc_errors::registry::{InvalidErrorCode, Registry};
|
||||
use rustc_errors::{markdown, ColorConfig};
|
||||
use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult};
|
||||
|
|
@ -476,7 +475,7 @@ fn run_compiler(
|
|||
eprintln!(
|
||||
"Fuel used by {}: {}",
|
||||
sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
|
||||
sess.print_fuel.load(SeqCst)
|
||||
sess.print_fuel.load(Ordering::SeqCst)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -716,7 +715,7 @@ fn print_crate_info(
|
|||
let result = parse_crate_attrs(sess);
|
||||
match result {
|
||||
Ok(attrs) => Some(attrs),
|
||||
Err(mut parse_error) => {
|
||||
Err(parse_error) => {
|
||||
parse_error.emit();
|
||||
return Compilation::Stop;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -515,6 +515,8 @@ E0792: include_str!("./error_codes/E0792.md"),
|
|||
E0793: include_str!("./error_codes/E0793.md"),
|
||||
E0794: include_str!("./error_codes/E0794.md"),
|
||||
E0795: include_str!("./error_codes/E0795.md"),
|
||||
E0796: include_str!("./error_codes/E0796.md"),
|
||||
E0797: include_str!("./error_codes/E0797.md"),
|
||||
}
|
||||
|
||||
// Undocumented removed error codes. Note that many removed error codes are kept in the list above
|
||||
|
|
|
|||
|
|
@ -10,35 +10,31 @@ async fn foo(n: usize) {
|
|||
}
|
||||
```
|
||||
|
||||
To perform async recursion, the `async fn` needs to be desugared such that the
|
||||
`Future` is explicit in the return type:
|
||||
|
||||
```edition2018,compile_fail,E0720
|
||||
use std::future::Future;
|
||||
fn foo_desugared(n: usize) -> impl Future<Output = ()> {
|
||||
async move {
|
||||
if n > 0 {
|
||||
foo_desugared(n - 1).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, the future is wrapped in a pinned box:
|
||||
The recursive invocation can be boxed:
|
||||
|
||||
```edition2018
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(async move {
|
||||
if n > 0 {
|
||||
foo_recursive(n - 1).await;
|
||||
}
|
||||
})
|
||||
async fn foo(n: usize) {
|
||||
if n > 0 {
|
||||
Box::pin(foo(n - 1)).await;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `Box<...>` ensures that the result is of known size, and the pin is
|
||||
required to keep it in the same place in memory.
|
||||
|
||||
Alternatively, the body can be boxed:
|
||||
|
||||
```edition2018
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
fn foo(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(async move {
|
||||
if n > 0 {
|
||||
foo(n - 1).await;
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
[`async`]: https://doc.rust-lang.org/std/keyword.async.html
|
||||
|
|
|
|||
22
compiler/rustc_error_codes/src/error_codes/E0796.md
Normal file
22
compiler/rustc_error_codes/src/error_codes/E0796.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Reference of mutable static.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,edition2024,E0796
|
||||
static mut X: i32 = 23;
|
||||
static mut Y: i32 = 24;
|
||||
|
||||
unsafe {
|
||||
let y = &X;
|
||||
let ref x = X;
|
||||
let (x, y) = (&X, &Y);
|
||||
foo(&X);
|
||||
}
|
||||
|
||||
fn foo<'a>(_x: &'a i32) {}
|
||||
```
|
||||
|
||||
Mutable statics can be written to by multiple threads: aliasing violations or
|
||||
data races will cause undefined behavior.
|
||||
|
||||
Reference of mutable static is a hard error from 2024 edition.
|
||||
26
compiler/rustc_error_codes/src/error_codes/E0797.md
Normal file
26
compiler/rustc_error_codes/src/error_codes/E0797.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
Struct update syntax was used without a base expression.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0797
|
||||
struct Foo {
|
||||
fizz: u8,
|
||||
buzz: u8
|
||||
}
|
||||
|
||||
let f1 = Foo { fizz: 10, buzz: 1};
|
||||
let f2 = Foo { fizz: 10, .. }; // error
|
||||
```
|
||||
|
||||
Using struct update syntax requires a 'base expression'.
|
||||
This will be used to fill remaining fields.
|
||||
|
||||
```
|
||||
struct Foo {
|
||||
fizz: u8,
|
||||
buzz: u8
|
||||
}
|
||||
|
||||
let f1 = Foo { fizz: 10, buzz: 1};
|
||||
let f2 = Foo { fizz: 10, ..f1 };
|
||||
```
|
||||
|
|
@ -30,57 +30,44 @@ where
|
|||
G: EmissionGuarantee,
|
||||
{
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = self.node.into_diagnostic(dcx, level);
|
||||
diag.span(self.span);
|
||||
diag
|
||||
self.node.into_diagnostic(dcx, level).span_mv(self.span)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for emitting structured error messages and other diagnostic information.
|
||||
/// Each constructed `DiagnosticBuilder` must be consumed by a function such as
|
||||
/// `emit`, `cancel`, `delay_as_bug`, or `into_diagnostic`. A panic occurrs if a
|
||||
/// `DiagnosticBuilder` is dropped without being consumed by one of these
|
||||
/// functions.
|
||||
///
|
||||
/// If there is some state in a downstream crate you would like to
|
||||
/// access in the methods of `DiagnosticBuilder` here, consider
|
||||
/// extending `DiagCtxtFlags`.
|
||||
#[must_use]
|
||||
#[derive(Clone)]
|
||||
pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> {
|
||||
state: DiagnosticBuilderState<'a>,
|
||||
pub dcx: &'a DiagCtxt,
|
||||
|
||||
/// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a
|
||||
/// return value, especially within the frequently-used `PResult` type.
|
||||
/// In theory, return value optimization (RVO) should avoid unnecessary
|
||||
/// copying. In practice, it does not (at the time of writing).
|
||||
diagnostic: Box<Diagnostic>,
|
||||
/// Why the `Option`? It is always `Some` until the `DiagnosticBuilder` is
|
||||
/// consumed via `emit`, `cancel`, etc. At that point it is consumed and
|
||||
/// replaced with `None`. Then `drop` checks that it is `None`; if not, it
|
||||
/// panics because a diagnostic was built but not used.
|
||||
///
|
||||
/// Why the Box? `Diagnostic` is a large type, and `DiagnosticBuilder` is
|
||||
/// often used as a return value, especially within the frequently-used
|
||||
/// `PResult` type. In theory, return value optimization (RVO) should avoid
|
||||
/// unnecessary copying. In practice, it does not (at the time of writing).
|
||||
diag: Option<Box<Diagnostic>>,
|
||||
|
||||
_marker: PhantomData<G>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum DiagnosticBuilderState<'a> {
|
||||
/// Initial state of a `DiagnosticBuilder`, before `.emit()` or `.cancel()`.
|
||||
///
|
||||
/// The `Diagnostic` will be emitted through this `DiagCtxt`.
|
||||
Emittable(&'a DiagCtxt),
|
||||
// Cloning a `DiagnosticBuilder` is a recipe for a diagnostic being emitted
|
||||
// twice, which would be bad.
|
||||
impl<G> !Clone for DiagnosticBuilder<'_, G> {}
|
||||
|
||||
/// State of a `DiagnosticBuilder`, after `.emit()` or *during* `.cancel()`.
|
||||
///
|
||||
/// The `Diagnostic` will be ignored when calling `.emit()`, and it can be
|
||||
/// assumed that `.emit()` was previously called, to end up in this state.
|
||||
///
|
||||
/// While this is also used by `.cancel()`, this state is only observed by
|
||||
/// the `Drop` `impl` of `DiagnosticBuilder`, because `.cancel()` takes
|
||||
/// `self` by-value specifically to prevent any attempts to `.emit()`.
|
||||
///
|
||||
// FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`,
|
||||
// despite that being potentially lossy, if important information is added
|
||||
// *after* the original `.emit()` call.
|
||||
AlreadyEmittedOrDuringCancellation,
|
||||
}
|
||||
|
||||
// `DiagnosticBuilderState` should be pointer-sized.
|
||||
rustc_data_structures::static_assert_size!(
|
||||
DiagnosticBuilderState<'_>,
|
||||
std::mem::size_of::<&DiagCtxt>()
|
||||
DiagnosticBuilder<'_, ()>,
|
||||
2 * std::mem::size_of::<usize>()
|
||||
);
|
||||
|
||||
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
|
||||
|
|
@ -94,68 +81,50 @@ pub trait EmissionGuarantee: Sized {
|
|||
/// `impl` of `EmissionGuarantee`, to make it impossible to create a value
|
||||
/// of `Self::EmitResult` without actually performing the emission.
|
||||
#[track_caller]
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult;
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult;
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// Takes the diagnostic. For use by methods that consume the
|
||||
/// DiagnosticBuilder: `emit`, `cancel`, etc. Afterwards, `drop` is the
|
||||
/// only code that will be run on `self`.
|
||||
fn take_diag(&mut self) -> Diagnostic {
|
||||
Box::into_inner(self.diag.take().unwrap())
|
||||
}
|
||||
|
||||
/// Most `emit_producing_guarantee` functions use this as a starting point.
|
||||
fn emit_producing_nothing(&mut self) {
|
||||
match self.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
dcx.emit_diagnostic_without_consuming(&mut self.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
fn emit_producing_nothing(mut self) {
|
||||
let diag = self.take_diag();
|
||||
self.dcx.emit_diagnostic(diag);
|
||||
}
|
||||
|
||||
/// `ErrorGuaranteed::emit_producing_guarantee` uses this.
|
||||
// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`.
|
||||
fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed {
|
||||
let diag = self.take_diag();
|
||||
|
||||
// Only allow a guarantee if the `level` wasn't switched to a
|
||||
// non-error. The field isn't `pub`, but the whole `Diagnostic` can be
|
||||
// overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
diag.is_error(),
|
||||
"emitted non-error ({:?}) diagnostic from `DiagnosticBuilder<ErrorGuaranteed>`",
|
||||
diag.level,
|
||||
);
|
||||
|
||||
let guar = self.dcx.emit_diagnostic(diag);
|
||||
guar.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`.
|
||||
impl EmissionGuarantee for ErrorGuaranteed {
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
// Contrast this with `emit_producing_nothing`.
|
||||
match db.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
let guar = dcx.emit_diagnostic_without_consuming(&mut db.diagnostic);
|
||||
|
||||
// Only allow a guarantee if the `level` wasn't switched to a
|
||||
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
||||
// can be overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
db.diagnostic.is_error(),
|
||||
"emitted non-error ({:?}) diagnostic \
|
||||
from `DiagnosticBuilder<ErrorGuaranteed>`",
|
||||
db.diagnostic.level,
|
||||
);
|
||||
guar.unwrap()
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it,
|
||||
// but can take advantage of the previous `.emit()`'s guarantee
|
||||
// still being applicable (i.e. as a form of idempotency).
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
|
||||
// Only allow a guarantee if the `level` wasn't switched to a
|
||||
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
||||
// can be overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
db.diagnostic.is_error(),
|
||||
"`DiagnosticBuilder<ErrorGuaranteed>`'s diagnostic \
|
||||
became non-error ({:?}), after original `.emit()`",
|
||||
db.diagnostic.level,
|
||||
);
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
}
|
||||
}
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_error_guaranteed()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well?
|
||||
impl EmissionGuarantee for () {
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
}
|
||||
}
|
||||
|
|
@ -168,7 +137,7 @@ pub struct BugAbort;
|
|||
impl EmissionGuarantee for BugAbort {
|
||||
type EmitResult = !;
|
||||
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
|
|
@ -182,37 +151,48 @@ pub struct FatalAbort;
|
|||
impl EmissionGuarantee for FatalAbort {
|
||||
type EmitResult = !;
|
||||
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
crate::FatalError.raise()
|
||||
}
|
||||
}
|
||||
|
||||
impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
rustc_span::fatal_error::FatalError
|
||||
}
|
||||
}
|
||||
|
||||
/// In general, the `DiagnosticBuilder` uses deref to allow access to
|
||||
/// the fields and methods of the embedded `diagnostic` in a
|
||||
/// transparent way. *However,* many of the methods are intended to
|
||||
/// be used in a chained way, and hence ought to return `self`. In
|
||||
/// that case, we can't just naively forward to the method on the
|
||||
/// `diagnostic`, because the return type would be a `&Diagnostic`
|
||||
/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes
|
||||
/// it easy to declare such methods on the builder.
|
||||
/// `DiagnosticBuilder` impls `DerefMut`, which allows access to the fields and
|
||||
/// methods of the embedded `Diagnostic`. However, that doesn't allow method
|
||||
/// chaining at the `DiagnosticBuilder` level. Each use of this macro defines
|
||||
/// two builder methods at that level, both of which wrap the equivalent method
|
||||
/// in `Diagnostic`.
|
||||
/// - A `&mut self -> &mut Self` method, with the same name as the underlying
|
||||
/// `Diagnostic` method. It is mostly to modify existing diagnostics, either
|
||||
/// in a standalone fashion, e.g. `err.code(code)`, or in a chained fashion
|
||||
/// to make multiple modifications, e.g. `err.code(code).span(span)`.
|
||||
/// - A `self -> Self` method, with `_mv` suffix added (short for "move").
|
||||
/// It is mostly used in a chained fashion when producing a new diagnostic,
|
||||
/// e.g. `let err = struct_err(msg).code_mv(code)`, or when emitting a new
|
||||
/// diagnostic , e.g. `struct_err(msg).code_mv(code).emit()`.
|
||||
///
|
||||
/// Although the latter method can be used to modify an existing diagnostic,
|
||||
/// e.g. `err = err.code_mv(code)`, this should be avoided because the former
|
||||
/// method give shorter code, e.g. `err.code(code)`.
|
||||
macro_rules! forward {
|
||||
// Forward pattern for &mut self -> &mut Self
|
||||
(
|
||||
$(#[$attrs:meta])*
|
||||
pub fn $n:ident(&mut self $(, $name:ident: $ty:ty)* $(,)?) -> &mut Self
|
||||
($n:ident, $n_mv:ident)($($name:ident: $ty:ty),* $(,)?)
|
||||
) => {
|
||||
$(#[$attrs])*
|
||||
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
|
||||
pub fn $n(&mut self $(, $name: $ty)*) -> &mut Self {
|
||||
self.diagnostic.$n($($name),*);
|
||||
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
|
||||
self.diag.as_mut().unwrap().$n($($name),*);
|
||||
self
|
||||
}
|
||||
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
|
||||
pub fn $n_mv(mut self, $($name: $ty),*) -> Self {
|
||||
self.diag.as_mut().unwrap().$n($($name),*);
|
||||
self
|
||||
}
|
||||
};
|
||||
|
|
@ -222,13 +202,13 @@ impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> {
|
|||
type Target = Diagnostic;
|
||||
|
||||
fn deref(&self) -> &Diagnostic {
|
||||
&self.diagnostic
|
||||
self.diag.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> {
|
||||
fn deref_mut(&mut self) -> &mut Diagnostic {
|
||||
&mut self.diagnostic
|
||||
self.diag.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -242,20 +222,14 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
/// Creates a new `DiagnosticBuilder` with an already constructed
|
||||
/// diagnostic.
|
||||
#[track_caller]
|
||||
pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self {
|
||||
pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diag: Diagnostic) -> Self {
|
||||
debug!("Created new diagnostic");
|
||||
Self {
|
||||
state: DiagnosticBuilderState::Emittable(dcx),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Emit the diagnostic. Does not consume `self`, which may be surprising,
|
||||
/// but there are various places that rely on continuing to use `self`
|
||||
/// after calling `emit`.
|
||||
/// Emit and consume the diagnostic.
|
||||
#[track_caller]
|
||||
pub fn emit(&mut self) -> G::EmitResult {
|
||||
pub fn emit(self) -> G::EmitResult {
|
||||
G::emit_producing_guarantee(self)
|
||||
}
|
||||
|
||||
|
|
@ -264,21 +238,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
///
|
||||
/// See `emit` and `delay_as_bug` for details.
|
||||
#[track_caller]
|
||||
pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult {
|
||||
pub fn emit_unless(mut self, delay: bool) -> G::EmitResult {
|
||||
if delay {
|
||||
self.downgrade_to_delayed_bug();
|
||||
}
|
||||
self.emit()
|
||||
}
|
||||
|
||||
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
|
||||
/// Cancel and consume the diagnostic. (A diagnostic must either be emitted or
|
||||
/// cancelled or it will panic when dropped).
|
||||
///
|
||||
/// This method takes `self` by-value to disallow calling `.emit()` on it,
|
||||
/// which may be expected to *guarantee* the emission of an error, either
|
||||
/// at the time of the call, or through a prior `.emit()` call.
|
||||
pub fn cancel(mut self) {
|
||||
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
self.diag = None;
|
||||
drop(self);
|
||||
}
|
||||
|
||||
|
|
@ -294,44 +264,20 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
}
|
||||
|
||||
/// Converts the builder to a `Diagnostic` for later emission,
|
||||
/// unless dcx has disabled such buffering, or `.emit()` was called.
|
||||
/// unless dcx has disabled such buffering.
|
||||
pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> {
|
||||
let dcx = match self.state {
|
||||
// No `.emit()` calls, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => dcx,
|
||||
// `.emit()` was previously called, nothing we can do.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
if dcx.inner.lock().flags.dont_buffer_diagnostics
|
||||
|| dcx.inner.lock().flags.treat_err_as_bug.is_some()
|
||||
{
|
||||
if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() {
|
||||
self.emit();
|
||||
return None;
|
||||
}
|
||||
|
||||
// Take the `Diagnostic` by replacing it with a dummy.
|
||||
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from(""));
|
||||
let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy);
|
||||
|
||||
// Disable the ICE on `Drop`.
|
||||
self.cancel();
|
||||
let diag = self.take_diag();
|
||||
|
||||
// Logging here is useful to help track down where in logs an error was
|
||||
// actually emitted.
|
||||
debug!("buffer: diagnostic={:?}", diagnostic);
|
||||
debug!("buffer: diag={:?}", diag);
|
||||
|
||||
Some((diagnostic, dcx))
|
||||
}
|
||||
|
||||
/// Retrieves the [`DiagCtxt`] if available
|
||||
pub fn dcx(&self) -> Option<&DiagCtxt> {
|
||||
match self.state {
|
||||
DiagnosticBuilderState::Emittable(dcx) => Some(dcx),
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None,
|
||||
}
|
||||
Some((diag, self.dcx))
|
||||
}
|
||||
|
||||
/// Buffers the diagnostic for later emission,
|
||||
|
|
@ -351,170 +297,157 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
/// In the meantime, though, callsites are required to deal with the "bug"
|
||||
/// locally in whichever way makes the most sense.
|
||||
#[track_caller]
|
||||
pub fn delay_as_bug(&mut self) -> G::EmitResult {
|
||||
pub fn delay_as_bug(mut self) -> G::EmitResult {
|
||||
self.downgrade_to_delayed_bug();
|
||||
self.emit()
|
||||
}
|
||||
|
||||
forward!(pub fn span_label(
|
||||
&mut self,
|
||||
forward!((span_label, span_label_mv)(
|
||||
span: Span,
|
||||
label: impl Into<SubdiagnosticMessage>
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_labels(
|
||||
&mut self,
|
||||
label: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_labels, span_labels_mv)(
|
||||
spans: impl IntoIterator<Item = Span>,
|
||||
label: &str,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn note_expected_found(
|
||||
&mut self,
|
||||
));
|
||||
forward!((note_expected_found, note_expected_found_mv)(
|
||||
expected_label: &dyn fmt::Display,
|
||||
expected: DiagnosticStyledString,
|
||||
found_label: &dyn fmt::Display,
|
||||
found: DiagnosticStyledString,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn note_expected_found_extra(
|
||||
&mut self,
|
||||
));
|
||||
forward!((note_expected_found_extra, note_expected_found_extra_mv)(
|
||||
expected_label: &dyn fmt::Display,
|
||||
expected: DiagnosticStyledString,
|
||||
found_label: &dyn fmt::Display,
|
||||
found: DiagnosticStyledString,
|
||||
expected_extra: &dyn fmt::Display,
|
||||
found_extra: &dyn fmt::Display,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_note(
|
||||
&mut self,
|
||||
));
|
||||
forward!((note, note_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((note_once, note_once_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_note, span_note_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_note_once(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_note_once, span_note_once_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_warn(
|
||||
&mut self,
|
||||
));
|
||||
forward!((warn, warn_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_warn, span_warn_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span_help(
|
||||
&mut self,
|
||||
));
|
||||
forward!((help, help_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((help_once, help_once_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
));
|
||||
forward!((span_help, span_help_once_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn is_lint(&mut self) -> &mut Self);
|
||||
forward!(pub fn disable_suggestions(&mut self) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((multipart_suggestion, multipart_suggestion_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestion_verbose(
|
||||
&mut self,
|
||||
));
|
||||
forward!((multipart_suggestion_verbose, multipart_suggestion_verbose_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn tool_only_multipart_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((tool_only_multipart_suggestion, tool_only_multipart_suggestion_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: Vec<(Span, String)>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion, span_suggestion_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestions(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestions, span_suggestions_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestions: impl IntoIterator<Item = String>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn multipart_suggestions(
|
||||
&mut self,
|
||||
));
|
||||
forward!((multipart_suggestions, multipart_suggestions_mv)(
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion_short(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion_short, span_suggestion_short_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion_verbose(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion_verbose, span_suggestion_verbose_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn span_suggestion_hidden(
|
||||
&mut self,
|
||||
));
|
||||
forward!((span_suggestion_hidden, span_suggestion_hidden_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn tool_only_span_suggestion(
|
||||
&mut self,
|
||||
));
|
||||
forward!((tool_only_span_suggestion, tool_only_span_suggestion_mv)(
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestion: impl ToString,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self);
|
||||
forward!(pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self);
|
||||
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
|
||||
forward!(pub fn arg(
|
||||
&mut self,
|
||||
name: impl Into<Cow<'static, str>>,
|
||||
arg: impl IntoDiagnosticArg,
|
||||
) -> &mut Self);
|
||||
forward!(pub fn subdiagnostic(
|
||||
&mut self,
|
||||
subdiagnostic: impl crate::AddToDiagnostic
|
||||
) -> &mut Self);
|
||||
));
|
||||
forward!((primary_message, primary_message_mv)(
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
));
|
||||
forward!((span, span_mv)(
|
||||
sp: impl Into<MultiSpan>,
|
||||
));
|
||||
forward!((code, code_mv)(
|
||||
s: DiagnosticId,
|
||||
));
|
||||
forward!((arg, arg_mv)(
|
||||
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
|
||||
));
|
||||
forward!((subdiagnostic, subdiagnostic_mv)(
|
||||
subdiagnostic: impl crate::AddToDiagnostic,
|
||||
));
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.diagnostic.fmt(f)
|
||||
self.diag.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
|
||||
/// or we emit a bug.
|
||||
/// Destructor bomb: every `DiagnosticBuilder` must be consumed (emitted,
|
||||
/// cancelled, etc.) or we emit a bug.
|
||||
impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
|
||||
fn drop(&mut self) {
|
||||
match self.state {
|
||||
// No `.emit()` or `.cancel()` calls.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
if !panicking() {
|
||||
dcx.emit_diagnostic(Diagnostic::new(
|
||||
Level::Bug,
|
||||
DiagnosticMessage::from(
|
||||
"the following error was constructed but not emitted",
|
||||
),
|
||||
));
|
||||
dcx.emit_diagnostic_without_consuming(&mut self.diagnostic);
|
||||
panic!("error was constructed but not emitted");
|
||||
}
|
||||
match self.diag.take() {
|
||||
Some(diag) if !panicking() => {
|
||||
self.dcx.emit_diagnostic(Diagnostic::new(
|
||||
Level::Bug,
|
||||
DiagnosticMessage::from("the following error was constructed but not emitted"),
|
||||
));
|
||||
self.dcx.emit_diagnostic(*diag);
|
||||
panic!("error was constructed but not emitted");
|
||||
}
|
||||
// `.emit()` was previously called, or maybe we're during `.cancel()`.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -522,11 +455,11 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
|
|||
#[macro_export]
|
||||
macro_rules! struct_span_err {
|
||||
($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
|
||||
$dcx.struct_span_err_with_code(
|
||||
$dcx.struct_span_err(
|
||||
$span,
|
||||
format!($($message)*),
|
||||
$crate::error_code!($code),
|
||||
)
|
||||
.code_mv($crate::error_code!($code))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,60 +249,43 @@ impl<Id> IntoDiagnosticArg for hir::def::Res<Id> {
|
|||
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag;
|
||||
match self {
|
||||
TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
|
||||
diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space);
|
||||
diag.arg("addr_space", addr_space);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space)
|
||||
.arg_mv("addr_space", addr_space)
|
||||
.arg_mv("cause", cause)
|
||||
.arg_mv("err", err)
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits);
|
||||
diag.arg("kind", kind);
|
||||
diag.arg("bit", bit);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits)
|
||||
.arg_mv("kind", kind)
|
||||
.arg_mv("bit", bit)
|
||||
.arg_mv("cause", cause)
|
||||
.arg_mv("err", err)
|
||||
}
|
||||
TargetDataLayoutErrors::MissingAlignment { cause } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment);
|
||||
diag.arg("cause", cause);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment)
|
||||
.arg_mv("cause", cause)
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment);
|
||||
diag.arg("cause", cause);
|
||||
diag.arg("err_kind", err.diag_ident());
|
||||
diag.arg("align", err.align());
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment)
|
||||
.arg_mv("cause", cause)
|
||||
.arg_mv("err_kind", err.diag_ident())
|
||||
.arg_mv("align", err.align())
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
|
||||
diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::errors_target_inconsistent_architecture,
|
||||
);
|
||||
diag.arg("dl", dl);
|
||||
diag.arg("target", target);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_inconsistent_architecture)
|
||||
.arg_mv("dl", dl)
|
||||
.arg_mv("target", target)
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
|
||||
diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::errors_target_inconsistent_pointer_width,
|
||||
);
|
||||
diag.arg("pointer_size", pointer_size);
|
||||
diag.arg("target", target);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_inconsistent_pointer_width)
|
||||
.arg_mv("pointer_size", pointer_size)
|
||||
.arg_mv("target", target)
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBitsSize { err } => {
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size);
|
||||
diag.arg("err", err);
|
||||
diag
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size)
|
||||
.arg_mv("err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
#![feature(rustdoc_internals)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_into_inner)]
|
||||
#![feature(extract_if)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(yeet_expr)]
|
||||
|
|
@ -507,11 +509,11 @@ pub enum StashKey {
|
|||
Cycle,
|
||||
}
|
||||
|
||||
fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
|
||||
(*f)(d)
|
||||
fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
|
||||
(*f)(diag)
|
||||
}
|
||||
|
||||
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&mut Diagnostic, &mut dyn FnMut(&mut Diagnostic))> =
|
||||
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
|
||||
AtomicRef::new(&(default_track_diagnostic as _));
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
|
|
@ -522,9 +524,6 @@ pub struct DiagCtxtFlags {
|
|||
/// If Some, the Nth error-level diagnostic is upgraded to bug-level.
|
||||
/// (rustc: see `-Z treat-err-as-bug`)
|
||||
pub treat_err_as_bug: Option<NonZeroUsize>,
|
||||
/// If true, immediately emit diagnostics that would otherwise be buffered.
|
||||
/// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`)
|
||||
pub dont_buffer_diagnostics: bool,
|
||||
/// Show macro backtraces.
|
||||
/// (rustc: see `-Z macro-backtrace`)
|
||||
pub macro_backtrace: bool,
|
||||
|
|
@ -728,24 +727,7 @@ impl DiagCtxt {
|
|||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_warn(msg);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
|
||||
/// Also include a code.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_warn_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_span_warn(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
self.struct_warn(msg).span_mv(span)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level with the `msg`.
|
||||
|
|
@ -785,23 +767,7 @@ impl DiagCtxt {
|
|||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_err_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_span_err(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
self.struct_err(msg).span_mv(span)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level with the `msg`.
|
||||
|
|
@ -812,32 +778,6 @@ impl DiagCtxt {
|
|||
DiagnosticBuilder::new(self, Error, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level with the `msg` and the `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_err_with_code(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.code(code);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warn` level with the `msg` and the `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_warn_with_code(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_warn(msg);
|
||||
result.code(code);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
|
|
@ -846,23 +786,7 @@ impl DiagCtxt {
|
|||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_fatal(msg);
|
||||
result.span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_fatal_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_span_fatal(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
self.struct_fatal(msg).span_mv(span)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level with the `msg`.
|
||||
|
|
@ -903,9 +827,7 @@ impl DiagCtxt {
|
|||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, BugAbort> {
|
||||
let mut result = self.struct_bug(msg);
|
||||
result.span(span);
|
||||
result
|
||||
self.struct_bug(msg).span_mv(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
|
|
@ -914,17 +836,6 @@ impl DiagCtxt {
|
|||
self.struct_span_fatal(span, msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_fatal_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> ! {
|
||||
self.struct_span_fatal_with_code(span, msg, code).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err(
|
||||
|
|
@ -935,34 +846,12 @@ impl DiagCtxt {
|
|||
self.struct_span_err(span, msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> ErrorGuaranteed {
|
||||
self.struct_span_err_with_code(span, msg, code).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
|
||||
self.struct_span_warn(span, msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn_with_code(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) {
|
||||
self.struct_span_warn_with_code(span, msg, code).emit()
|
||||
}
|
||||
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
self.struct_span_bug(span, msg).emit()
|
||||
}
|
||||
|
|
@ -1020,9 +909,7 @@ impl DiagCtxt {
|
|||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut db = DiagnosticBuilder::new(self, Note, msg);
|
||||
db.span(span);
|
||||
db
|
||||
DiagnosticBuilder::new(self, Note, msg).span_mv(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
|
|
@ -1184,17 +1071,8 @@ impl DiagCtxt {
|
|||
self.inner.borrow_mut().emitter.emit_diagnostic(&db);
|
||||
}
|
||||
|
||||
pub fn emit_diagnostic(&self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
self.emit_diagnostic_without_consuming(&mut diagnostic)
|
||||
}
|
||||
|
||||
// It's unfortunate this exists. `emit_diagnostic` is preferred, because it
|
||||
// consumes the diagnostic, thus ensuring it is emitted just once.
|
||||
pub(crate) fn emit_diagnostic_without_consuming(
|
||||
&self,
|
||||
diagnostic: &mut Diagnostic,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow_mut().emit_diagnostic_without_consuming(diagnostic)
|
||||
pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow_mut().emit_diagnostic(diagnostic)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
@ -1383,13 +1261,6 @@ impl DiagCtxtInner {
|
|||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
|
||||
self.emit_diagnostic_without_consuming(&mut diagnostic)
|
||||
}
|
||||
|
||||
fn emit_diagnostic_without_consuming(
|
||||
&mut self,
|
||||
diagnostic: &mut Diagnostic,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() {
|
||||
diagnostic.level = Bug;
|
||||
}
|
||||
|
|
@ -1445,7 +1316,7 @@ impl DiagCtxtInner {
|
|||
}
|
||||
|
||||
let mut guaranteed = None;
|
||||
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| {
|
||||
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |mut diagnostic| {
|
||||
if let Some(ref code) = diagnostic.code {
|
||||
self.emitted_diagnostic_codes.insert(code.clone());
|
||||
}
|
||||
|
|
@ -1481,7 +1352,7 @@ impl DiagCtxtInner {
|
|||
);
|
||||
}
|
||||
|
||||
self.emitter.emit_diagnostic(diagnostic);
|
||||
self.emitter.emit_diagnostic(&diagnostic);
|
||||
if diagnostic.is_error() {
|
||||
self.deduplicated_err_count += 1;
|
||||
} else if let Warning(_) = diagnostic.level {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ doctest = false
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
crossbeam-channel = "0.5.0"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_passes = { path = "../rustc_ast_passes" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
|
|
|
|||
|
|
@ -1232,7 +1232,7 @@ pub fn expr_to_string(
|
|||
) -> Option<(Symbol, ast::StrStyle)> {
|
||||
expr_to_spanned_string(cx, expr, err_msg)
|
||||
.map_err(|err| {
|
||||
err.map(|(mut err, _)| {
|
||||
err.map(|(err, _)| {
|
||||
err.emit();
|
||||
})
|
||||
})
|
||||
|
|
@ -1254,7 +1254,7 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str
|
|||
pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
|
||||
match p.parse_expr() {
|
||||
Ok(e) => return Some(e),
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) {
|
||||
let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) {
|
||||
Ok(meta_item) => meta_item,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return (true, None);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -735,7 +735,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
fragment_kind.expect_from_annotatables(items)
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
fragment_kind.dummy(span)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -679,8 +679,8 @@ impl TtParser {
|
|||
// We use the span of the metavariable declaration to determine any
|
||||
// edition-specific matching behavior for non-terminals.
|
||||
let nt = match parser.to_mut().parse_nonterminal(kind) {
|
||||
Err(mut err) => {
|
||||
let guarantee = err.span_label(
|
||||
Err(err) => {
|
||||
let guarantee = err.span_label_mv(
|
||||
span,
|
||||
format!(
|
||||
"while parsing argument for this `{kind}` macro fragment"
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ fn expand_macro<'cx>(
|
|||
// rhs has holes ( `$id` and `$(...)` that need filled)
|
||||
let tts = match transcribe(cx, &named_matches, rhs, rhs_span, transparency) {
|
||||
Ok(tts) => tts,
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
return DummyResult::any(arm_span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ pub(super) fn parse(
|
|||
// `SyntaxContext::root()` from a foreign crate will
|
||||
// have the edition of that crate (which we manually
|
||||
// retrieve via the `edition` parameter).
|
||||
if span.ctxt().is_root() {
|
||||
if !span.from_expansion() {
|
||||
edition
|
||||
} else {
|
||||
span.edition()
|
||||
|
|
@ -86,7 +86,7 @@ pub(super) fn parse(
|
|||
);
|
||||
sess.dcx
|
||||
.struct_span_err(span, msg)
|
||||
.help(VALID_FRAGMENT_NAMES_MSG)
|
||||
.help_mv(VALID_FRAGMENT_NAMES_MSG)
|
||||
.emit();
|
||||
token::NonterminalKind::Ident
|
||||
},
|
||||
|
|
@ -175,7 +175,7 @@ fn parse_tree<'a>(
|
|||
// of a meta-variable expression (e.g. `${count(ident)}`).
|
||||
// Try to parse the meta-variable expression.
|
||||
match MetaVarExpr::parse(tts, delim_span.entire(), sess) {
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
// Returns early the same read `$` to avoid spanning
|
||||
// unrelated diagnostics that could be performed afterwards
|
||||
|
|
|
|||
|
|
@ -13,19 +13,28 @@ use rustc_errors::DiagnosticBuilder;
|
|||
use rustc_errors::{pluralize, PResult};
|
||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, SyntaxContext};
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::mem;
|
||||
|
||||
// A Marker adds the given mark to the syntax context.
|
||||
struct Marker(LocalExpnId, Transparency);
|
||||
struct Marker(LocalExpnId, Transparency, FxHashMap<SyntaxContext, SyntaxContext>);
|
||||
|
||||
impl MutVisitor for Marker {
|
||||
const VISIT_TOKENS: bool = true;
|
||||
|
||||
fn visit_span(&mut self, span: &mut Span) {
|
||||
*span = span.apply_mark(self.0.to_expn_id(), self.1)
|
||||
// `apply_mark` is a relatively expensive operation, both due to taking hygiene lock, and
|
||||
// by itself. All tokens in a macro body typically have the same syntactic context, unless
|
||||
// it's some advanced case with macro-generated macros. So if we cache the marked version
|
||||
// of that context once, we'll typically have a 100% cache hit rate after that.
|
||||
let Marker(expn_id, transparency, ref mut cache) = *self;
|
||||
let data = span.data();
|
||||
let marked_ctxt = *cache
|
||||
.entry(data.ctxt)
|
||||
.or_insert_with(|| data.ctxt.apply_mark(expn_id.to_expn_id(), transparency));
|
||||
*span = data.with_ctxt(marked_ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +132,7 @@ pub(super) fn transcribe<'a>(
|
|||
// again, and we are done transcribing.
|
||||
let mut result: Vec<TokenTree> = Vec::new();
|
||||
let mut result_stack = Vec::new();
|
||||
let mut marker = Marker(cx.current_expansion.id, transparency);
|
||||
let mut marker = Marker(cx.current_expansion.id, transparency, Default::default());
|
||||
|
||||
loop {
|
||||
// Look at the last frame on the stack.
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ impl ModError<'_> {
|
|||
secondary_path: secondary_path.display().to_string(),
|
||||
})
|
||||
}
|
||||
ModError::ParserError(mut err) => err.emit(),
|
||||
ModError::ParserError(err) => err.emit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@ use rustc_session::config::ProcMacroExecutionStrategy;
|
|||
use rustc_span::profiling::SpannedEventArgRecorder;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
struct CrossbeamMessagePipe<T> {
|
||||
tx: crossbeam_channel::Sender<T>,
|
||||
rx: crossbeam_channel::Receiver<T>,
|
||||
struct MessagePipe<T> {
|
||||
tx: std::sync::mpsc::SyncSender<T>,
|
||||
rx: std::sync::mpsc::Receiver<T>,
|
||||
}
|
||||
|
||||
impl<T> pm::bridge::server::MessagePipe<T> for CrossbeamMessagePipe<T> {
|
||||
impl<T> pm::bridge::server::MessagePipe<T> for MessagePipe<T> {
|
||||
fn new() -> (Self, Self) {
|
||||
let (tx1, rx1) = crossbeam_channel::bounded(1);
|
||||
let (tx2, rx2) = crossbeam_channel::bounded(1);
|
||||
(CrossbeamMessagePipe { tx: tx1, rx: rx2 }, CrossbeamMessagePipe { tx: tx2, rx: rx1 })
|
||||
let (tx1, rx1) = std::sync::mpsc::sync_channel(1);
|
||||
let (tx2, rx2) = std::sync::mpsc::sync_channel(1);
|
||||
(MessagePipe { tx: tx1, rx: rx2 }, MessagePipe { tx: tx2, rx: rx1 })
|
||||
}
|
||||
|
||||
fn send(&mut self, value: T) {
|
||||
|
|
@ -35,7 +35,7 @@ impl<T> pm::bridge::server::MessagePipe<T> for CrossbeamMessagePipe<T> {
|
|||
}
|
||||
|
||||
fn exec_strategy(ecx: &ExtCtxt<'_>) -> impl pm::bridge::server::ExecutionStrategy {
|
||||
pm::bridge::server::MaybeCrossThread::<CrossbeamMessagePipe<_>>::new(
|
||||
pm::bridge::server::MaybeCrossThread::<MessagePipe<_>>::new(
|
||||
ecx.sess.opts.unstable_opts.proc_macro_execution_strategy
|
||||
== ProcMacroExecutionStrategy::CrossThread,
|
||||
)
|
||||
|
|
@ -171,7 +171,7 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
items.push(Annotatable::Item(item));
|
||||
}
|
||||
}
|
||||
Err(mut err) => {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ impl server::TokenStream for Rustc<'_, '_> {
|
|||
}
|
||||
expr
|
||||
};
|
||||
let expr = expr.map_err(|mut err| {
|
||||
let expr = expr.map_err(|err| {
|
||||
err.emit();
|
||||
})?;
|
||||
|
||||
|
|
|
|||
|
|
@ -1361,6 +1361,12 @@ impl CoroutineKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl CoroutineKind {
|
||||
pub fn is_fn_like(self) -> bool {
|
||||
matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CoroutineKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
|
@ -1997,7 +2003,7 @@ pub enum LocalSource {
|
|||
AsyncFn,
|
||||
/// A desugared `<expr>.await`.
|
||||
AwaitDesugar,
|
||||
/// A desugared `expr = expr`, where the LHS is a tuple, struct or array.
|
||||
/// A desugared `expr = expr`, where the LHS is a tuple, struct, array or underscore expression.
|
||||
/// The span is that of the `=` sign.
|
||||
AssignDesugar(Span),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ rustc_errors = { path = "../rustc_errors" }
|
|||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
|
|
|
|||
|
|
@ -346,6 +346,20 @@ hir_analysis_start_not_target_feature = `#[start]` function is not allowed to ha
|
|||
hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]`
|
||||
.label = `#[start]` function is not allowed to be `#[track_caller]`
|
||||
|
||||
hir_analysis_static_mut_ref = reference of mutable static is disallowed
|
||||
.label = reference of mutable static
|
||||
.note = mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
|
||||
.suggestion = shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
|
||||
.suggestion_mut = mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
|
||||
|
||||
hir_analysis_static_mut_ref_lint = {$shared}reference of mutable static is discouraged
|
||||
.label = shared reference of mutable static
|
||||
.label_mut = mutable reference of mutable static
|
||||
.suggestion = shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
|
||||
.suggestion_mut = mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
|
||||
.note = reference of mutable static is a hard error from 2024 edition
|
||||
.why_note = mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
|
||||
|
||||
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
|
||||
|
||||
hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
binding.span,
|
||||
format!("{} `{}` is private", assoc_item.kind, binding.item_name),
|
||||
)
|
||||
.span_label(binding.span, format!("private {}", assoc_item.kind))
|
||||
.span_label_mv(binding.span, format!("private {}", assoc_item.kind))
|
||||
.emit();
|
||||
}
|
||||
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
if !trait_def.paren_sugar {
|
||||
if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
|
||||
// For now, require that parenthetical notation be used only with `Fn()` etc.
|
||||
let mut err = feature_err(
|
||||
feature_err(
|
||||
&self.tcx().sess.parse_sess,
|
||||
sym::unboxed_closures,
|
||||
span,
|
||||
"parenthetical notation is only stable when used with `Fn`-family traits",
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ fn generic_arg_mismatch_err(
|
|||
Res::Err => {
|
||||
add_braces_suggestion(arg, &mut err);
|
||||
return err
|
||||
.primary_message("unresolved item provided when a constant was expected")
|
||||
.primary_message_mv("unresolved item provided when a constant was expected")
|
||||
.emit();
|
||||
}
|
||||
Res::Def(DefKind::TyParam, src_def_id) => {
|
||||
|
|
@ -650,9 +650,9 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
|||
if position == GenericArgPosition::Value
|
||||
&& args.num_lifetime_params() != param_counts.lifetimes
|
||||
{
|
||||
let mut err = struct_span_err!(tcx.dcx(), span, E0794, "{}", msg);
|
||||
err.span_note(span_late, note);
|
||||
err.emit();
|
||||
struct_span_err!(tcx.dcx(), span, E0794, "{}", msg)
|
||||
.span_note_mv(span_late, note)
|
||||
.emit();
|
||||
} else {
|
||||
let mut multispan = MultiSpan::from_span(span);
|
||||
multispan.push_span_label(span_late, note);
|
||||
|
|
|
|||
|
|
@ -1032,7 +1032,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.trait_defines_associated_item_named(r.def_id(), assoc_kind, assoc_name)
|
||||
});
|
||||
|
||||
let Some(mut bound) = matching_candidates.next() else {
|
||||
let Some(bound) = matching_candidates.next() else {
|
||||
let reported = self.complain_about_assoc_item_not_found(
|
||||
all_candidates,
|
||||
&ty_param_name.to_string(),
|
||||
|
|
@ -1046,38 +1046,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
};
|
||||
debug!(?bound);
|
||||
|
||||
// look for a candidate that is not the same as our first bound, disregarding
|
||||
// whether the bound is const.
|
||||
let mut next_cand = matching_candidates.next();
|
||||
while let Some(mut bound2) = next_cand {
|
||||
debug!(?bound2);
|
||||
if bound2.bound_vars() != bound.bound_vars() {
|
||||
break;
|
||||
}
|
||||
|
||||
let generics = tcx.generics_of(bound.def_id());
|
||||
let Some(host_index) = generics.host_effect_index else { break };
|
||||
|
||||
// always return the bound that contains the host param.
|
||||
if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() {
|
||||
(bound, bound2) = (bound2, bound);
|
||||
}
|
||||
|
||||
let unconsted_args = bound
|
||||
.skip_binder()
|
||||
.args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg });
|
||||
|
||||
if unconsted_args.eq(bound2.skip_binder().args.iter()) {
|
||||
next_cand = matching_candidates.next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(bound2) = next_cand {
|
||||
if let Some(bound2) = matching_candidates.next() {
|
||||
debug!(?bound2);
|
||||
|
||||
let assoc_kind_str = assoc_kind_str(assoc_kind);
|
||||
|
|
@ -1647,9 +1616,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let msg = format!("{kind} `{name}` is private");
|
||||
let def_span = tcx.def_span(item);
|
||||
tcx.dcx()
|
||||
.struct_span_err_with_code(span, msg, rustc_errors::error_code!(E0624))
|
||||
.span_label(span, format!("private {kind}"))
|
||||
.span_label(def_span, format!("{kind} defined here"))
|
||||
.struct_span_err(span, msg)
|
||||
.code_mv(rustc_errors::error_code!(E0624))
|
||||
.span_label_mv(span, format!("private {kind}"))
|
||||
.span_label_mv(def_span, format!("{kind} defined here"))
|
||||
.emit();
|
||||
}
|
||||
tcx.check_stability(item, Some(block), span, None);
|
||||
|
|
|
|||
|
|
@ -290,19 +290,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
if references_self {
|
||||
let def_id = i.bottom().0.def_id();
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
tcx.dcx(),
|
||||
i.bottom().1,
|
||||
E0038,
|
||||
"the {} `{}` cannot be made into an object",
|
||||
tcx.def_descr(def_id),
|
||||
tcx.item_name(def_id),
|
||||
);
|
||||
err.note(
|
||||
)
|
||||
.note_mv(
|
||||
rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
|
||||
.error_msg(),
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
|
||||
|
|
@ -375,7 +375,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.ast_region_to_region(lifetime, None)
|
||||
} else {
|
||||
self.re_infer(None, span).unwrap_or_else(|| {
|
||||
let mut err = struct_span_err!(
|
||||
let err = struct_span_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0228,
|
||||
|
|
|
|||
|
|
@ -45,24 +45,6 @@ impl<'tcx> Bounds<'tcx> {
|
|||
polarity: ty::ImplPolarity,
|
||||
) {
|
||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||
|
||||
// push a non-const (`host = true`) version of the bound if it is `~const`.
|
||||
if tcx.features().effects
|
||||
&& let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index
|
||||
&& trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_
|
||||
{
|
||||
let generics = tcx.generics_of(trait_ref.def_id());
|
||||
let Some(host_index) = generics.host_effect_index else { return };
|
||||
let trait_ref = trait_ref.map_bound(|mut trait_ref| {
|
||||
trait_ref.args =
|
||||
tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| {
|
||||
if host_index == n { tcx.consts.true_.into() } else { arg }
|
||||
}));
|
||||
trait_ref
|
||||
});
|
||||
|
||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_trait_bound_inner(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use rustc_middle::middle::stability::EvalResult;
|
|||
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::ty::{
|
||||
AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
|
|
@ -213,13 +213,12 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
return;
|
||||
}
|
||||
|
||||
let args = GenericArgs::identity_for_item(tcx, item.owner_id);
|
||||
let span = tcx.def_span(item.owner_id.def_id);
|
||||
|
||||
if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
|
||||
return;
|
||||
}
|
||||
if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, origin).is_err() {
|
||||
if check_opaque_for_cycles(tcx, item.owner_id.def_id, span).is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -230,19 +229,36 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
pub(super) fn check_opaque_for_cycles<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
span: Span,
|
||||
origin: &hir::OpaqueTyOrigin,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
|
||||
let reported = match origin {
|
||||
hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
|
||||
_ => opaque_type_cycle_error(tcx, def_id, span),
|
||||
};
|
||||
Err(reported)
|
||||
} else {
|
||||
Ok(())
|
||||
let args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
|
||||
// First, try to look at any opaque expansion cycles, considering coroutine fields
|
||||
// (even though these aren't necessarily true errors).
|
||||
if tcx
|
||||
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
|
||||
.is_err()
|
||||
{
|
||||
// Look for true opaque expansion cycles, but ignore coroutines.
|
||||
// This will give us any true errors. Coroutines are only problematic
|
||||
// if they cause layout computation errors.
|
||||
if tcx
|
||||
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
|
||||
.is_err()
|
||||
{
|
||||
let reported = opaque_type_cycle_error(tcx, def_id, span);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
// And also look for cycle errors in the layout of coroutines.
|
||||
if let Err(&LayoutError::Cycle(guar)) =
|
||||
tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args)))
|
||||
{
|
||||
return Err(guar);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
|
||||
|
|
@ -550,8 +566,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
E0044,
|
||||
"foreign items may not have {kinds} parameters",
|
||||
)
|
||||
.span_label(item.span, format!("can't have {kinds} parameters"))
|
||||
.help(
|
||||
.span_label_mv(item.span, format!("can't have {kinds} parameters"))
|
||||
.help_mv(
|
||||
// FIXME: once we start storing spans for type arguments, turn this
|
||||
// into a suggestion.
|
||||
format!(
|
||||
|
|
@ -788,7 +804,7 @@ fn check_impl_items_against_trait<'tcx>(
|
|||
};
|
||||
tcx.dcx()
|
||||
.struct_span_err(tcx.def_span(def_id), msg)
|
||||
.note(format!(
|
||||
.note_mv(format!(
|
||||
"specialization behaves in inconsistent and \
|
||||
surprising ways with {feature}, \
|
||||
and for now is disallowed"
|
||||
|
|
@ -830,7 +846,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
|||
let e = fields[FieldIdx::from_u32(0)].ty(tcx, args);
|
||||
if !fields.iter().all(|f| f.ty(tcx, args) == e) {
|
||||
struct_span_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous")
|
||||
.span_label(sp, "SIMD elements must have the same type")
|
||||
.span_label_mv(sp, "SIMD elements must have the same type")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
|
@ -1107,7 +1123,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
E0084,
|
||||
"unsupported representation for zero-variant enum"
|
||||
)
|
||||
.span_label(tcx.def_span(def_id), "zero-variant enum")
|
||||
.span_label_mv(tcx.def_span(def_id), "zero-variant enum")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -1140,13 +1156,13 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var));
|
||||
|
||||
if disr_non_unit || (disr_units && has_non_units) {
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
tcx.dcx(),
|
||||
tcx.def_span(def_id),
|
||||
E0732,
|
||||
"`#[repr(inttype)]` must be specified"
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1249,7 +1265,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(mut e) = error {
|
||||
if let Some(e) = error {
|
||||
e.emit();
|
||||
}
|
||||
|
||||
|
|
@ -1294,22 +1310,12 @@ pub(super) fn check_type_params_are_used<'tcx>(
|
|||
{
|
||||
let span = tcx.def_span(param.def_id);
|
||||
struct_span_err!(tcx.dcx(), span, E0091, "type parameter `{}` is unused", param.name,)
|
||||
.span_label(span, "unused type parameter")
|
||||
.span_label_mv(span, "unused type parameter")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
|
||||
struct_span_err!(tcx.dcx(), span, E0733, "recursion in an `async fn` requires boxing")
|
||||
.span_label(span, "recursive `async fn`")
|
||||
.note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
|
||||
.note(
|
||||
"consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
|
||||
)
|
||||
.emit()
|
||||
}
|
||||
|
||||
/// Emit an error for recursive opaque types.
|
||||
///
|
||||
/// If this is a return `impl Trait`, find the item's return expressions and point at them. For
|
||||
|
|
|
|||
|
|
@ -934,12 +934,12 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
|||
return_span,
|
||||
"return type captures more lifetimes than trait definition",
|
||||
)
|
||||
.span_label(self.tcx.def_span(def_id), "this lifetime was captured")
|
||||
.span_note(
|
||||
.span_label_mv(self.tcx.def_span(def_id), "this lifetime was captured")
|
||||
.span_note_mv(
|
||||
self.tcx.def_span(self.def_id),
|
||||
"hidden type must only reference lifetimes captured by this impl trait",
|
||||
)
|
||||
.note(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.note_mv(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.emit()
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -1371,7 +1371,7 @@ fn compare_number_of_generics<'tcx>(
|
|||
let spans = arg_spans(impl_.kind, impl_item.generics);
|
||||
let span = spans.first().copied();
|
||||
|
||||
let mut err = tcx.dcx().struct_span_err_with_code(
|
||||
let mut err = tcx.dcx().struct_span_err(
|
||||
spans,
|
||||
format!(
|
||||
"{} `{}` has {} {kind} parameter{} but its trait \
|
||||
|
|
@ -1384,8 +1384,8 @@ fn compare_number_of_generics<'tcx>(
|
|||
pluralize!(trait_count),
|
||||
kind = kind,
|
||||
),
|
||||
DiagnosticId::Error("E0049".into()),
|
||||
);
|
||||
err.code(DiagnosticId::Error("E0049".into()));
|
||||
|
||||
let msg =
|
||||
format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
"`Drop` impl requires `{root_predicate}` \
|
||||
but the {self_descr} it is implemented for does not",
|
||||
)
|
||||
.span_note(item_span, "the implementor must specify the same requirement")
|
||||
.span_note_mv(item_span, "the implementor must specify the same requirement")
|
||||
.emit(),
|
||||
);
|
||||
}
|
||||
|
|
@ -193,7 +193,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
"`Drop` impl requires `{outlives}` \
|
||||
but the {self_descr} it is implemented for does not",
|
||||
)
|
||||
.span_note(item_span, "the implementor must specify the same requirement")
|
||||
.span_note_mv(item_span, "the implementor must specify the same requirement")
|
||||
.emit(),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
97
compiler/rustc_hir_analysis/src/check/errs.rs
Normal file
97
compiler/rustc_hir_analysis/src/check/errs.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir_pretty::qpath_to_string;
|
||||
use rustc_lint_defs::builtin::STATIC_MUT_REF;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::Span;
|
||||
use rustc_type_ir::Mutability;
|
||||
|
||||
use crate::errors;
|
||||
|
||||
/// Check for shared or mutable references of `static mut` inside expression
|
||||
pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
|
||||
let span = expr.span;
|
||||
let hir_id = expr.hir_id;
|
||||
if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
|
||||
&& matches!(borrow_kind, hir::BorrowKind::Ref)
|
||||
&& let Some(var) = is_path_static_mut(*expr)
|
||||
{
|
||||
handle_static_mut_ref(
|
||||
tcx,
|
||||
span,
|
||||
var,
|
||||
span.edition().at_least_rust_2024(),
|
||||
matches!(m, Mutability::Mut),
|
||||
hir_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check for shared or mutable references of `static mut` inside statement
|
||||
pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
|
||||
if let hir::StmtKind::Local(loc) = stmt.kind
|
||||
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
|
||||
&& matches!(ba.0, rustc_ast::ByRef::Yes)
|
||||
&& let Some(init) = loc.init
|
||||
&& let Some(var) = is_path_static_mut(*init)
|
||||
{
|
||||
handle_static_mut_ref(
|
||||
tcx,
|
||||
init.span,
|
||||
var,
|
||||
loc.span.edition().at_least_rust_2024(),
|
||||
matches!(ba.1, Mutability::Mut),
|
||||
stmt.hir_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_path_static_mut(expr: hir::Expr<'_>) -> Option<String> {
|
||||
if let hir::ExprKind::Path(qpath) = expr.kind
|
||||
&& let hir::QPath::Resolved(_, path) = qpath
|
||||
&& let hir::def::Res::Def(def_kind, _) = path.res
|
||||
&& let hir::def::DefKind::Static(mt) = def_kind
|
||||
&& matches!(mt, Mutability::Mut)
|
||||
{
|
||||
return Some(qpath_to_string(&qpath));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_static_mut_ref(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
var: String,
|
||||
e2024: bool,
|
||||
mutable: bool,
|
||||
hir_id: hir::HirId,
|
||||
) {
|
||||
if e2024 {
|
||||
let sugg = if mutable {
|
||||
errors::StaticMutRefSugg::Mut { span, var }
|
||||
} else {
|
||||
errors::StaticMutRefSugg::Shared { span, var }
|
||||
};
|
||||
tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg });
|
||||
return;
|
||||
}
|
||||
|
||||
let (label, sugg, shared) = if mutable {
|
||||
(
|
||||
errors::RefOfMutStaticLabel::Mut { span },
|
||||
errors::RefOfMutStaticSugg::Mut { span, var },
|
||||
"mutable ",
|
||||
)
|
||||
} else {
|
||||
(
|
||||
errors::RefOfMutStaticLabel::Shared { span },
|
||||
errors::RefOfMutStaticSugg::Shared { span, var },
|
||||
"shared ",
|
||||
)
|
||||
};
|
||||
tcx.emit_spanned_lint(
|
||||
STATIC_MUT_REF,
|
||||
hir_id,
|
||||
span,
|
||||
errors::RefOfMutStatic { shared, why_note: (), label, sugg },
|
||||
);
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ fn equate_intrinsic_type<'tcx>(
|
|||
}
|
||||
_ => {
|
||||
struct_span_err!(tcx.dcx(), it.span, E0622, "intrinsic must be a function")
|
||||
.span_label(it.span, "expected a function")
|
||||
.span_label_mv(it.span, "expected a function")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,12 +153,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
};
|
||||
let Some(asm_ty) = asm_ty else {
|
||||
let msg = format!("cannot use value of type `{ty}` for inline assembly");
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
err.note(
|
||||
"only integers, floats, SIMD vectors, pointers and function pointers \
|
||||
can be used as arguments for inline assembly",
|
||||
);
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(expr.span, msg)
|
||||
.note_mv(
|
||||
"only integers, floats, SIMD vectors, pointers and function pointers \
|
||||
can be used as arguments for inline assembly",
|
||||
)
|
||||
.emit();
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
@ -166,9 +168,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
// possibly fail is for SIMD types which don't #[derive(Copy)].
|
||||
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
|
||||
let msg = "arguments for inline assembly must be copyable";
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
err.note(format!("`{ty}` does not implement the Copy trait"));
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(expr.span, msg)
|
||||
.note_mv(format!("`{ty}` does not implement the Copy trait"))
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Ideally we wouldn't need to do this, but LLVM's register allocator
|
||||
|
|
@ -183,16 +187,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
if let Some((in_expr, Some(in_asm_ty))) = tied_input {
|
||||
if in_asm_ty != asm_ty {
|
||||
let msg = "incompatible types for asm inout argument";
|
||||
let mut err = self.tcx.dcx().struct_span_err(vec![in_expr.span, expr.span], msg);
|
||||
|
||||
let in_expr_ty = (self.get_operand_ty)(in_expr);
|
||||
err.span_label(in_expr.span, format!("type `{in_expr_ty}`"));
|
||||
err.span_label(expr.span, format!("type `{ty}`"));
|
||||
err.note(
|
||||
"asm inout arguments must have the same type, \
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(vec![in_expr.span, expr.span], msg)
|
||||
.span_label_mv(in_expr.span, format!("type `{in_expr_ty}`"))
|
||||
.span_label_mv(expr.span, format!("type `{ty}`"))
|
||||
.note_mv(
|
||||
"asm inout arguments must have the same type, \
|
||||
unless they are both pointers or integers of the same size",
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
// All of the later checks have already been done on the input, so
|
||||
|
|
@ -234,13 +239,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
if let Some(feature) = feature {
|
||||
if !target_features.contains(feature) {
|
||||
let msg = format!("`{feature}` target feature is not enabled");
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
err.note(format!(
|
||||
"this is required to use type `{}` with register class `{}`",
|
||||
ty,
|
||||
reg_class.name(),
|
||||
));
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(expr.span, msg)
|
||||
.note_mv(format!(
|
||||
"this is required to use type `{}` with register class `{}`",
|
||||
ty,
|
||||
reg_class.name(),
|
||||
))
|
||||
.emit();
|
||||
return Some(asm_ty);
|
||||
}
|
||||
}
|
||||
|
|
@ -449,14 +456,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
ty::Never | ty::Error(_) => {}
|
||||
ty::FnDef(..) => {}
|
||||
_ => {
|
||||
let mut err =
|
||||
self.tcx.dcx().struct_span_err(*op_sp, "invalid `sym` operand");
|
||||
err.span_label(
|
||||
self.tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
);
|
||||
err.help("`sym` operands must refer to either a function or a static");
|
||||
err.emit();
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(*op_sp, "invalid `sym` operand")
|
||||
.span_label_mv(
|
||||
self.tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
)
|
||||
.help_mv(
|
||||
"`sym` operands must refer to either a function or a static",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ mod check;
|
|||
mod compare_impl_item;
|
||||
pub mod dropck;
|
||||
mod entry;
|
||||
mod errs;
|
||||
pub mod intrinsic;
|
||||
pub mod intrinsicck;
|
||||
mod region;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_span::source_map;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut};
|
||||
|
||||
use std::mem;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
|
@ -224,6 +226,8 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
|
|||
let stmt_id = stmt.hir_id.local_id;
|
||||
debug!("resolve_stmt(stmt.id={:?})", stmt_id);
|
||||
|
||||
maybe_stmt_static_mut(visitor.tcx, *stmt);
|
||||
|
||||
// Every statement will clean up the temporaries created during
|
||||
// execution of that statement. Therefore each statement has an
|
||||
// associated destruction scope that represents the scope of the
|
||||
|
|
@ -242,6 +246,8 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
|
|||
fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr);
|
||||
|
||||
maybe_expr_static_mut(visitor.tcx, *expr);
|
||||
|
||||
let prev_cx = visitor.cx;
|
||||
visitor.enter_node_scope_with_dtor(expr.hir_id.local_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -197,11 +197,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
|||
let mut res = Ok(());
|
||||
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
|
||||
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
|
||||
let mut err =
|
||||
tcx.dcx().struct_span_err(sp, "impls of auto traits cannot be default");
|
||||
err.span_labels(impl_.defaultness_span, "default because of this");
|
||||
err.span_label(sp, "auto trait");
|
||||
res = Err(err.emit());
|
||||
res = Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(sp, "impls of auto traits cannot be default")
|
||||
.span_labels_mv(impl_.defaultness_span, "default because of this")
|
||||
.span_label_mv(sp, "auto trait")
|
||||
.emit());
|
||||
}
|
||||
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
|
||||
match tcx.impl_polarity(def_id) {
|
||||
|
|
@ -489,35 +490,33 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
|
||||
if !unsatisfied_bounds.is_empty() {
|
||||
let plural = pluralize!(unsatisfied_bounds.len());
|
||||
let mut err = tcx.dcx().struct_span_err(
|
||||
gat_item_hir.span,
|
||||
format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
|
||||
);
|
||||
|
||||
let suggestion = format!(
|
||||
"{} {}",
|
||||
gat_item_hir.generics.add_where_or_trailing_comma(),
|
||||
unsatisfied_bounds.join(", "),
|
||||
);
|
||||
err.span_suggestion(
|
||||
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
|
||||
format!("add the required where clause{plural}"),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
let bound =
|
||||
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
|
||||
err.note(format!(
|
||||
"{bound} currently required to ensure that impls have maximum flexibility"
|
||||
));
|
||||
err.note(
|
||||
"we are soliciting feedback, see issue #87479 \
|
||||
tcx.dcx()
|
||||
.struct_span_err(
|
||||
gat_item_hir.span,
|
||||
format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
|
||||
)
|
||||
.span_suggestion_mv(
|
||||
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
|
||||
format!("add the required where clause{plural}"),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.note_mv(format!(
|
||||
"{bound} currently required to ensure that impls have maximum flexibility"
|
||||
))
|
||||
.note_mv(
|
||||
"we are soliciting feedback, see issue #87479 \
|
||||
<https://github.com/rust-lang/rust/issues/87479> \
|
||||
for more information",
|
||||
);
|
||||
|
||||
err.emit();
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -838,8 +837,8 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
|
|||
trait_should_be_self,
|
||||
"associated item referring to unboxed trait object for its own trait",
|
||||
)
|
||||
.span_label(trait_name.span, "in this trait")
|
||||
.multipart_suggestion(
|
||||
.span_label_mv(trait_name.span, "in this trait")
|
||||
.multipart_suggestion_mv(
|
||||
"you might have meant to use `Self` to refer to the implementing type",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
|
|
@ -938,8 +937,8 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
};
|
||||
if may_suggest_feature && tcx.sess.is_nightly_build() {
|
||||
diag.help(
|
||||
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
|
||||
);
|
||||
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
|
||||
);
|
||||
}
|
||||
|
||||
Err(diag.emit())
|
||||
|
|
@ -1599,7 +1598,7 @@ fn check_method_receiver<'tcx>(
|
|||
the `arbitrary_self_types` feature",
|
||||
),
|
||||
)
|
||||
.help(HELP_FOR_SELF_TYPE)
|
||||
.help_mv(HELP_FOR_SELF_TYPE)
|
||||
.emit()
|
||||
} else {
|
||||
// Report error; would not have worked with `arbitrary_self_types`.
|
||||
|
|
@ -1612,8 +1611,8 @@ fn check_method_receiver<'tcx>(
|
|||
|
||||
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed {
|
||||
struct_span_err!(tcx.dcx(), span, E0307, "invalid `self` parameter type: {receiver_ty}")
|
||||
.note("type of `self` must be `Self` or a type that dereferences to it")
|
||||
.help(HELP_FOR_SELF_TYPE)
|
||||
.note_mv("type of `self` must be `Self` or a type that dereferences to it")
|
||||
.help_mv(HELP_FOR_SELF_TYPE)
|
||||
.emit()
|
||||
}
|
||||
|
||||
|
|
@ -1921,10 +1920,8 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
|
|||
}
|
||||
|
||||
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> {
|
||||
let mut err =
|
||||
struct_span_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used");
|
||||
err.span_label(span, "unused parameter");
|
||||
err
|
||||
struct_span_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used")
|
||||
.span_label_mv(span, "unused parameter")
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
|
|
|||
|
|
@ -70,17 +70,16 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
match seen_items.entry(norm_ident) {
|
||||
Entry::Occupied(entry) => {
|
||||
let former = entry.get();
|
||||
let mut err = struct_span_err!(
|
||||
struct_span_err!(
|
||||
self.tcx.dcx(),
|
||||
span,
|
||||
E0592,
|
||||
"duplicate definitions with name `{}`",
|
||||
ident,
|
||||
);
|
||||
err.span_label(span, format!("duplicate definitions for `{ident}`"));
|
||||
err.span_label(*former, format!("other definition for `{ident}`"));
|
||||
|
||||
err.emit();
|
||||
)
|
||||
.span_label_mv(span, format!("duplicate definitions for `{ident}`"))
|
||||
.span_label_mv(*former, format!("other definition for `{ident}`"))
|
||||
.emit();
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(span);
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ fn check_object_overlap<'tcx>(
|
|||
trait_ref.self_ty(),
|
||||
tcx.def_path_str(trait_def_id)
|
||||
)
|
||||
.span_label(
|
||||
.span_label_mv(
|
||||
span,
|
||||
format!(
|
||||
"`{}` automatically implements trait `{}`",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
"implementing the trait `{}` is not unsafe",
|
||||
trait_ref.print_trait_sugared()
|
||||
)
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
|
||||
"remove `unsafe` from this trait implementation",
|
||||
"",
|
||||
|
|
@ -42,13 +42,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
"the trait `{}` requires an `unsafe impl` declaration",
|
||||
trait_ref.print_trait_sugared()
|
||||
)
|
||||
.note(format!(
|
||||
.note_mv(format!(
|
||||
"the trait `{}` enforces invariants that the compiler can't check. \
|
||||
Review the trait documentation and make sure this implementation \
|
||||
upholds those invariants before adding the `unsafe` keyword",
|
||||
trait_ref.print_trait_sugared()
|
||||
))
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
item.span.shrink_to_lo(),
|
||||
"add `unsafe` to this trait implementation",
|
||||
"unsafe ",
|
||||
|
|
@ -65,13 +65,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
||||
attr_name
|
||||
)
|
||||
.note(format!(
|
||||
.note_mv(format!(
|
||||
"the trait `{}` enforces invariants that the compiler can't check. \
|
||||
Review the trait documentation and make sure this implementation \
|
||||
upholds those invariants before adding the `unsafe` keyword",
|
||||
trait_ref.print_trait_sugared()
|
||||
))
|
||||
.span_suggestion_verbose(
|
||||
.span_suggestion_verbose_mv(
|
||||
item.span.shrink_to_lo(),
|
||||
"add `unsafe` to this trait implementation",
|
||||
"unsafe ",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor};
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{sym, Span, DUMMY_SP};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
||||
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
|
||||
|
|
@ -38,38 +38,12 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
|||
// an obligation and instead be skipped. Otherwise we'd use
|
||||
// `tcx.def_span(def_id);`
|
||||
let span = rustc_span::DUMMY_SP;
|
||||
let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) {
|
||||
// when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound,
|
||||
// because only implementing `Self: Trait<.., false>` is currently not possible.
|
||||
Some((
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
def_id,
|
||||
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
||||
if param.is_host_effect() {
|
||||
tcx.consts.true_.into()
|
||||
} else {
|
||||
tcx.mk_param_from_def(param)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.to_predicate(tcx),
|
||||
|
||||
result.predicates =
|
||||
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
|
||||
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
|
||||
span,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
result.predicates = tcx.arena.alloc_from_iter(
|
||||
result
|
||||
.predicates
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(std::iter::once((
|
||||
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
|
||||
span,
|
||||
)))
|
||||
.chain(non_const_bound),
|
||||
);
|
||||
))));
|
||||
}
|
||||
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
|
||||
result
|
||||
|
|
|
|||
|
|
@ -750,12 +750,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
kind: hir::ItemKind::OpaqueTy { .. }, ..
|
||||
}) = self.tcx.hir_node(parent_id)
|
||||
{
|
||||
let mut err = self.tcx.dcx().struct_span_err(
|
||||
self.tcx.dcx().struct_span_err(
|
||||
lifetime.ident.span,
|
||||
"higher kinded lifetime bounds on nested opaque types are not supported yet",
|
||||
);
|
||||
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
|
||||
err.emit();
|
||||
)
|
||||
.span_note_mv(self.tcx.def_span(def_id), "lifetime declared here")
|
||||
.emit();
|
||||
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
@ -2114,7 +2114,7 @@ pub fn deny_non_region_late_bound(
|
|||
hir::GenericParamKind::Lifetime { .. } => continue,
|
||||
};
|
||||
|
||||
let mut diag = tcx.dcx().struct_span_err(
|
||||
let diag = tcx.dcx().struct_span_err(
|
||||
param.span,
|
||||
format!("late-bound {what} parameter not allowed on {where_}"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
|
|||
Node::Item(it) => locator.visit_item(it),
|
||||
Node::ImplItem(it) => locator.visit_impl_item(it),
|
||||
Node::TraitItem(it) => locator.visit_trait_item(it),
|
||||
Node::ForeignItem(it) => locator.visit_foreign_item(it),
|
||||
other => bug!("{:?} is not a valid scope for an opaque type item", other),
|
||||
}
|
||||
}
|
||||
|
|
@ -240,6 +241,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
|
|||
self.check(it.owner_id.def_id);
|
||||
intravisit::walk_trait_item(self, it);
|
||||
}
|
||||
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
|
||||
trace!(?it.owner_id);
|
||||
assert_ne!(it.owner_id.def_id, self.def_id);
|
||||
// No need to call `check`, as we do not run borrowck on foreign items.
|
||||
intravisit::walk_foreign_item(self, it);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
|
||||
|
|
|
|||
|
|
@ -1410,3 +1410,94 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> {
|
|||
pub mut_key: &'a str,
|
||||
pub ptr_ty: Ty<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_static_mut_ref, code = "E0796")]
|
||||
#[note]
|
||||
pub struct StaticMutRef {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sugg: StaticMutRefSugg,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum StaticMutRefSugg {
|
||||
#[suggestion(
|
||||
hir_analysis_suggestion,
|
||||
style = "verbose",
|
||||
code = "addr_of!({var})",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
Shared {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: String,
|
||||
},
|
||||
#[suggestion(
|
||||
hir_analysis_suggestion_mut,
|
||||
style = "verbose",
|
||||
code = "addr_of_mut!({var})",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
Mut {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: String,
|
||||
},
|
||||
}
|
||||
|
||||
// STATIC_MUT_REF lint
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_analysis_static_mut_ref_lint)]
|
||||
#[note]
|
||||
pub struct RefOfMutStatic<'a> {
|
||||
pub shared: &'a str,
|
||||
#[note(hir_analysis_why_note)]
|
||||
pub why_note: (),
|
||||
#[subdiagnostic]
|
||||
pub label: RefOfMutStaticLabel,
|
||||
#[subdiagnostic]
|
||||
pub sugg: RefOfMutStaticSugg,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum RefOfMutStaticLabel {
|
||||
#[label(hir_analysis_label)]
|
||||
Shared {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(hir_analysis_label_mut)]
|
||||
Mut {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum RefOfMutStaticSugg {
|
||||
#[suggestion(
|
||||
hir_analysis_suggestion,
|
||||
style = "verbose",
|
||||
code = "addr_of!({var})",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
Shared {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: String,
|
||||
},
|
||||
#[suggestion(
|
||||
hir_analysis_suggestion_mut,
|
||||
style = "verbose",
|
||||
code = "addr_of_mut!({var})",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
Mut {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: String,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,13 +166,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
|
|||
|
||||
// this ensures that later parts of type checking can assume that items
|
||||
// have valid types and not error
|
||||
// FIXME(matthewjasper) We shouldn't need to use `track_errors`.
|
||||
tcx.sess.track_errors(|| {
|
||||
tcx.sess.time("type_collecting", || {
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
|
||||
});
|
||||
})?;
|
||||
tcx.sess.time("type_collecting", || {
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
|
||||
});
|
||||
|
||||
// FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function
|
||||
// or the compiler in general.
|
||||
if tcx.features().rustc_attrs {
|
||||
tcx.sess.track_errors(|| {
|
||||
tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
|
||||
|
|
|
|||
|
|
@ -523,8 +523,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let span = self.path_segment.ident.span;
|
||||
let msg = self.create_error_message();
|
||||
|
||||
self.tcx.dcx().struct_span_err_with_code(span, msg, self.code())
|
||||
self.tcx.dcx().struct_span_err(span, msg).code_mv(self.code())
|
||||
}
|
||||
|
||||
/// Builds the `expected 1 type argument / supplied 2 type arguments` message.
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
callee_expr.span,
|
||||
format!("evaluate({predicate:?}) = {result:?}"),
|
||||
)
|
||||
.span_label(predicate_span, "predicate")
|
||||
.span_label_mv(predicate_span, "predicate")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -490,11 +490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx.require_lang_item(hir::LangItem::FnOnce, Some(span));
|
||||
let fn_once_output_def_id =
|
||||
self.tcx.require_lang_item(hir::LangItem::FnOnceOutput, Some(span));
|
||||
if self.tcx.generics_of(fn_once_def_id).host_effect_index.is_none() {
|
||||
if idx == 0 && !self.tcx.is_const_fn_raw(def_id) {
|
||||
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
|
||||
}
|
||||
} else {
|
||||
if self.tcx.has_host_param(fn_once_def_id) {
|
||||
let const_param: ty::GenericArg<'tcx> =
|
||||
([self.tcx.consts.false_, self.tcx.consts.true_])[idx].into();
|
||||
self.register_predicate(traits::Obligation::new(
|
||||
|
|
@ -523,6 +519,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
));
|
||||
|
||||
self.select_obligations_where_possible(|_| {});
|
||||
} else if idx == 0 && !self.tcx.is_const_fn_raw(def_id) {
|
||||
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
|
||||
}
|
||||
} else {
|
||||
self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
}
|
||||
CastError::NeedViaInt => {
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx)
|
||||
.help("cast through an integer first")
|
||||
.help_mv("cast through an integer first")
|
||||
.emit();
|
||||
}
|
||||
CastError::IllegalCast => {
|
||||
|
|
@ -277,7 +277,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
}
|
||||
CastError::DifferingKinds => {
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx)
|
||||
.note("vtable kinds may not match")
|
||||
.note_mv("vtable kinds may not match")
|
||||
.emit();
|
||||
}
|
||||
CastError::CastToBool => {
|
||||
|
|
@ -512,7 +512,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
self.cast_ty,
|
||||
fcx,
|
||||
)
|
||||
.note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate")
|
||||
.note_mv("cannot cast an enum with a non-exhaustive variant when it's defined in another crate")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Requires that the two types unify, and prints an error message if
|
||||
/// they don't.
|
||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(mut e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
e.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -228,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) -> Ty<'tcx> {
|
||||
let (ty, err) =
|
||||
self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
|
||||
if let Some(mut err) = err {
|
||||
if let Some(err) = err {
|
||||
err.emit();
|
||||
}
|
||||
ty
|
||||
|
|
|
|||
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