mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-12 06:53:05 +00:00
Auto merge of #3238 - rust-lang:rustup-2023-12-24, r=saethlin
Automatic Rustup
This commit is contained in:
commit
1754946b3e
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@ -289,8 +289,9 @@ jobs:
|
||||
os: ubuntu-20.04-4core-16gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-integration
|
||||
env:
|
||||
CI_ONLY_WHEN_CHANNEL: nightly
|
||||
os: ubuntu-20.04-16core-64gb
|
||||
env: {}
|
||||
- name: x86_64-gnu-debug
|
||||
os: ubuntu-20.04-8core-32gb
|
||||
env: {}
|
||||
|
@ -4340,6 +4340,7 @@ dependencies = [
|
||||
name = "rustc_pattern_analysis"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"derivative",
|
||||
"rustc_apfloat",
|
||||
"rustc_arena",
|
||||
"rustc_data_structures",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -286,41 +286,16 @@ impl ParenthesizedArgs {
|
||||
|
||||
pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
|
||||
|
||||
/// A modifier on a bound, e.g., `?Trait` or `~const Trait`.
|
||||
///
|
||||
/// Negative bounds should also be handled here.
|
||||
/// Modifiers on a trait bound like `~const`, `?` and `!`.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||
pub enum TraitBoundModifier {
|
||||
/// No modifiers
|
||||
None,
|
||||
|
||||
/// `!Trait`
|
||||
Negative,
|
||||
|
||||
/// `?Trait`
|
||||
Maybe,
|
||||
|
||||
/// `~const Trait`
|
||||
MaybeConst(Span),
|
||||
|
||||
/// `~const !Trait`
|
||||
//
|
||||
// This parses but will be rejected during AST validation.
|
||||
MaybeConstNegative,
|
||||
|
||||
/// `~const ?Trait`
|
||||
//
|
||||
// This parses but will be rejected during AST validation.
|
||||
MaybeConstMaybe,
|
||||
pub struct TraitBoundModifiers {
|
||||
pub constness: BoundConstness,
|
||||
pub polarity: BoundPolarity,
|
||||
}
|
||||
|
||||
impl TraitBoundModifier {
|
||||
pub fn to_constness(self) -> Const {
|
||||
match self {
|
||||
Self::MaybeConst(span) => Const::Yes(span),
|
||||
_ => Const::No,
|
||||
}
|
||||
}
|
||||
impl TraitBoundModifiers {
|
||||
pub const NONE: Self =
|
||||
Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
@ -329,7 +304,7 @@ impl TraitBoundModifier {
|
||||
/// detects `Copy`, `Send` and `Sync`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifier),
|
||||
Trait(PolyTraitRef, TraitBoundModifiers),
|
||||
Outlives(Lifetime),
|
||||
}
|
||||
|
||||
@ -779,8 +754,7 @@ pub enum PatKind {
|
||||
Ident(BindingAnnotation, Ident, Option<P<Pat>>),
|
||||
|
||||
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
|
||||
/// The `bool` is `true` in the presence of a `..`.
|
||||
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, /* recovered */ bool),
|
||||
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
|
||||
|
||||
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
|
||||
TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
|
||||
@ -837,6 +811,15 @@ pub enum PatKind {
|
||||
MacCall(P<MacCall>),
|
||||
}
|
||||
|
||||
/// Whether the `..` is present in a struct fields pattern.
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
|
||||
pub enum PatFieldsRest {
|
||||
/// `module::StructName { field, ..}`
|
||||
Rest,
|
||||
/// `module::StructName { field }`
|
||||
None,
|
||||
}
|
||||
|
||||
/// The kind of borrow in an `AddrOf` expression,
|
||||
/// e.g., `&place` or `&raw const place`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
@ -1193,7 +1176,7 @@ impl Expr {
|
||||
match &self.kind {
|
||||
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
||||
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
|
||||
TraitBoundModifier::None,
|
||||
TraitBoundModifiers::NONE,
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
@ -1274,7 +1257,7 @@ impl Expr {
|
||||
ExprKind::Let(..) => ExprPrecedence::Let,
|
||||
ExprKind::If(..) => ExprPrecedence::If,
|
||||
ExprKind::While(..) => ExprPrecedence::While,
|
||||
ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
|
||||
ExprKind::ForLoop { .. } => ExprPrecedence::ForLoop,
|
||||
ExprKind::Loop(..) => ExprPrecedence::Loop,
|
||||
ExprKind::Match(..) => ExprPrecedence::Match,
|
||||
ExprKind::Closure(..) => ExprPrecedence::Closure,
|
||||
@ -1436,10 +1419,10 @@ pub enum ExprKind {
|
||||
While(P<Expr>, P<Block>, Option<Label>),
|
||||
/// A `for` loop, with an optional label.
|
||||
///
|
||||
/// `'label: for pat in expr { block }`
|
||||
/// `'label: for await? pat in iter { block }`
|
||||
///
|
||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>),
|
||||
ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind },
|
||||
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
|
||||
///
|
||||
/// `'label: loop { block }`
|
||||
@ -1542,6 +1525,13 @@ pub enum ExprKind {
|
||||
Err,
|
||||
}
|
||||
|
||||
/// Used to differentiate between `for` loops and `for await` loops.
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
pub enum ForLoopKind {
|
||||
For,
|
||||
ForAwait,
|
||||
}
|
||||
|
||||
/// Used to differentiate between `async {}` blocks and `gen {}` blocks.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
pub enum GenBlockKind {
|
||||
@ -2491,6 +2481,15 @@ pub enum Const {
|
||||
No,
|
||||
}
|
||||
|
||||
impl From<BoundConstness> for Const {
|
||||
fn from(constness: BoundConstness) -> Self {
|
||||
match constness {
|
||||
BoundConstness::Maybe(span) => Self::Yes(span),
|
||||
BoundConstness::Never => Self::No,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Item defaultness.
|
||||
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
@ -2516,7 +2515,9 @@ impl fmt::Debug for ImplPolarity {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
/// The polarity of a trait bound.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum BoundPolarity {
|
||||
/// `Type: Trait`
|
||||
Positive,
|
||||
@ -2526,6 +2527,35 @@ pub enum BoundPolarity {
|
||||
Maybe(Span),
|
||||
}
|
||||
|
||||
impl BoundPolarity {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Positive => "",
|
||||
Self::Negative(_) => "!",
|
||||
Self::Maybe(_) => "?",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The constness of a trait bound.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum BoundConstness {
|
||||
/// `Type: Trait`
|
||||
Never,
|
||||
/// `Type: ~const Trait`
|
||||
Maybe(Span),
|
||||
}
|
||||
|
||||
impl BoundConstness {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Never => "",
|
||||
Self::Maybe(_) => "~const",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum FnRetTy {
|
||||
/// Returns type is not specified.
|
||||
@ -3259,7 +3289,7 @@ mod size_asserts {
|
||||
static_assert_size!(ForeignItem, 96);
|
||||
static_assert_size!(ForeignItemKind, 24);
|
||||
static_assert_size!(GenericArg, 24);
|
||||
static_assert_size!(GenericBound, 64);
|
||||
static_assert_size!(GenericBound, 72);
|
||||
static_assert_size!(Generics, 40);
|
||||
static_assert_size!(Impl, 136);
|
||||
static_assert_size!(Item, 136);
|
||||
|
@ -1389,7 +1389,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
vis.visit_block(body);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
}
|
||||
ExprKind::ForLoop(pat, iter, body, label) => {
|
||||
ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_expr(iter);
|
||||
vis.visit_block(body);
|
||||
|
@ -19,7 +19,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
||||
| ast::ExprKind::Block(..)
|
||||
| ast::ExprKind::While(..)
|
||||
| ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::ForLoop(..)
|
||||
| ast::ExprKind::ForLoop { .. }
|
||||
| ast::ExprKind::TryBlock(..)
|
||||
| ast::ExprKind::ConstBlock(..)
|
||||
)
|
||||
@ -48,8 +48,16 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||
Closure(closure) => {
|
||||
expr = &closure.body;
|
||||
}
|
||||
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),
|
||||
Gen(..)
|
||||
| Block(..)
|
||||
| ForLoop { .. }
|
||||
| If(..)
|
||||
| Loop(..)
|
||||
| Match(..)
|
||||
| Struct(..)
|
||||
| TryBlock(..)
|
||||
| While(..)
|
||||
| ConstBlock(_) => break Some(expr),
|
||||
|
||||
// FIXME: These can end in `}`, but changing these would break stable code.
|
||||
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
|
||||
|
@ -844,11 +844,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_block(block);
|
||||
}
|
||||
ExprKind::ForLoop(pattern, subexpression, block, opt_label) => {
|
||||
walk_list!(visitor, visit_label, opt_label);
|
||||
visitor.visit_pat(pattern);
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_block(block);
|
||||
ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
|
||||
walk_list!(visitor, visit_label, label);
|
||||
visitor.visit_pat(pat);
|
||||
visitor.visit_expr(iter);
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
ExprKind::Loop(block, opt_label, _) => {
|
||||
walk_list!(visitor, visit_label, opt_label);
|
||||
|
@ -56,12 +56,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
return ex;
|
||||
}
|
||||
// Desugar `ExprForLoop`
|
||||
// from: `[opt_ident]: for <pat> in <head> <body>`
|
||||
// from: `[opt_ident]: for await? <pat> in <iter> <body>`
|
||||
//
|
||||
// This also needs special handling because the HirId of the returned `hir::Expr` will not
|
||||
// correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
|
||||
ExprKind::ForLoop(pat, head, body, opt_label) => {
|
||||
return self.lower_expr_for(e, pat, head, body, *opt_label);
|
||||
ExprKind::ForLoop { pat, iter, body, label, kind } => {
|
||||
return self.lower_expr_for(e, pat, iter, body, *label, *kind);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@ -337,7 +337,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
),
|
||||
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
||||
|
||||
ExprKind::Paren(_) | ExprKind::ForLoop(..) => {
|
||||
ExprKind::Paren(_) | ExprKind::ForLoop { .. } => {
|
||||
unreachable!("already handled")
|
||||
}
|
||||
|
||||
@ -670,7 +670,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let params = arena_vec![self; param];
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Async(async_coroutine_source));
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
async_coroutine_source,
|
||||
));
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
this.task_context = Some(task_context_hid);
|
||||
@ -724,7 +727,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
});
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Gen(coroutine_source));
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
coroutine_source,
|
||||
));
|
||||
|
||||
let res = body(this);
|
||||
(&[], res)
|
||||
@ -802,7 +808,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let params = arena_vec![self; param];
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::AsyncGen(async_coroutine_source));
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
async_coroutine_source,
|
||||
));
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
this.task_context = Some(task_context_hid);
|
||||
@ -874,12 +883,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
/// }
|
||||
/// ```
|
||||
fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
|
||||
let expr = self.arena.alloc(self.lower_expr_mut(expr));
|
||||
self.make_lowered_await(await_kw_span, expr, FutureKind::Future)
|
||||
}
|
||||
|
||||
/// Takes an expr that has already been lowered and generates a desugared await loop around it
|
||||
fn make_lowered_await(
|
||||
&mut self,
|
||||
await_kw_span: Span,
|
||||
expr: &'hir hir::Expr<'hir>,
|
||||
await_kind: FutureKind,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let full_span = expr.span.to(await_kw_span);
|
||||
|
||||
let is_async_gen = match self.coroutine_kind {
|
||||
Some(hir::CoroutineKind::Async(_)) => false,
|
||||
Some(hir::CoroutineKind::AsyncGen(_)) => true,
|
||||
Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => {
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => false,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
|
||||
Some(hir::CoroutineKind::Coroutine)
|
||||
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
|
||||
| None => {
|
||||
return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
||||
await_kw_span,
|
||||
item_span: self.current_item,
|
||||
@ -887,13 +909,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
};
|
||||
|
||||
let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None);
|
||||
let features = match await_kind {
|
||||
FutureKind::Future => None,
|
||||
FutureKind::AsyncIterator => Some(self.allow_for_await.clone()),
|
||||
};
|
||||
let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features);
|
||||
let gen_future_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Await,
|
||||
full_span,
|
||||
Some(self.allow_gen_future.clone()),
|
||||
);
|
||||
let expr = self.lower_expr_mut(expr);
|
||||
let expr_hir_id = expr.hir_id;
|
||||
|
||||
// Note that the name of this binding must not be changed to something else because
|
||||
@ -934,11 +959,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::LangItem::GetContext,
|
||||
arena_vec![self; task_context],
|
||||
);
|
||||
let call = self.expr_call_lang_item_fn(
|
||||
span,
|
||||
hir::LangItem::FuturePoll,
|
||||
arena_vec![self; new_unchecked, get_context],
|
||||
);
|
||||
let call = match await_kind {
|
||||
FutureKind::Future => self.expr_call_lang_item_fn(
|
||||
span,
|
||||
hir::LangItem::FuturePoll,
|
||||
arena_vec![self; new_unchecked, get_context],
|
||||
),
|
||||
FutureKind::AsyncIterator => self.expr_call_lang_item_fn(
|
||||
span,
|
||||
hir::LangItem::AsyncIteratorPollNext,
|
||||
arena_vec![self; new_unchecked, get_context],
|
||||
),
|
||||
};
|
||||
self.arena.alloc(self.expr_unsafe(call))
|
||||
};
|
||||
|
||||
@ -1020,11 +1052,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let awaitee_arm = self.arm(awaitee_pat, loop_expr);
|
||||
|
||||
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
|
||||
let into_future_expr = self.expr_call_lang_item_fn(
|
||||
span,
|
||||
hir::LangItem::IntoFutureIntoFuture,
|
||||
arena_vec![self; expr],
|
||||
);
|
||||
let into_future_expr = match await_kind {
|
||||
FutureKind::Future => self.expr_call_lang_item_fn(
|
||||
span,
|
||||
hir::LangItem::IntoFutureIntoFuture,
|
||||
arena_vec![self; *expr],
|
||||
),
|
||||
// Not needed for `for await` because we expect to have already called
|
||||
// `IntoAsyncIterator::into_async_iter` on it.
|
||||
FutureKind::AsyncIterator => expr,
|
||||
};
|
||||
|
||||
// match <into_future_expr> {
|
||||
// mut __awaitee => loop { .. }
|
||||
@ -1097,9 +1134,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
Some(movability)
|
||||
}
|
||||
Some(
|
||||
hir::CoroutineKind::Gen(_)
|
||||
| hir::CoroutineKind::Async(_)
|
||||
| hir::CoroutineKind::AsyncGen(_),
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
|
||||
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
|
||||
) => {
|
||||
panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
|
||||
}
|
||||
@ -1612,9 +1649,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
|
||||
let is_async_gen = match self.coroutine_kind {
|
||||
Some(hir::CoroutineKind::Gen(_)) => false,
|
||||
Some(hir::CoroutineKind::AsyncGen(_)) => true,
|
||||
Some(hir::CoroutineKind::Async(_)) => {
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
|
||||
return hir::ExprKind::Err(
|
||||
self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }),
|
||||
);
|
||||
@ -1685,6 +1722,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
head: &Expr,
|
||||
body: &Block,
|
||||
opt_label: Option<Label>,
|
||||
loop_kind: ForLoopKind,
|
||||
) -> hir::Expr<'hir> {
|
||||
let head = self.lower_expr_mut(head);
|
||||
let pat = self.lower_pat(pat);
|
||||
@ -1713,17 +1751,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (iter_pat, iter_pat_nid) =
|
||||
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
|
||||
|
||||
// `match Iterator::next(&mut iter) { ... }`
|
||||
let match_expr = {
|
||||
let iter = self.expr_ident(head_span, iter, iter_pat_nid);
|
||||
let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
|
||||
let next_expr = self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IteratorNext,
|
||||
arena_vec![self; ref_mut_iter],
|
||||
);
|
||||
let next_expr = match loop_kind {
|
||||
ForLoopKind::For => {
|
||||
// `Iterator::next(&mut iter)`
|
||||
let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
|
||||
self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IteratorNext,
|
||||
arena_vec![self; ref_mut_iter],
|
||||
)
|
||||
}
|
||||
ForLoopKind::ForAwait => {
|
||||
// we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this
|
||||
// to make_lowered_await with `FutureKind::AsyncIterator` which will generator
|
||||
// calls to `poll_next`. In user code, this would probably be a call to
|
||||
// `Pin::as_mut` but here it's easy enough to do `new_unchecked`.
|
||||
|
||||
// `&mut iter`
|
||||
let iter = self.expr_mut_addr_of(head_span, iter);
|
||||
// `Pin::new_unchecked(...)`
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||
head_span,
|
||||
hir::LangItem::PinNewUnchecked,
|
||||
arena_vec![self; iter],
|
||||
));
|
||||
// `unsafe { ... }`
|
||||
let iter = self.arena.alloc(self.expr_unsafe(iter));
|
||||
let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator);
|
||||
self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span })
|
||||
}
|
||||
};
|
||||
let arms = arena_vec![self; none_arm, some_arm];
|
||||
|
||||
// `match $next_expr { ... }`
|
||||
self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
|
||||
};
|
||||
let match_stmt = self.stmt_expr(for_span, match_expr);
|
||||
@ -1743,13 +1805,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// `mut iter => { ... }`
|
||||
let iter_arm = self.arm(iter_pat, loop_expr);
|
||||
|
||||
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
||||
let into_iter_expr = {
|
||||
self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IntoIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
)
|
||||
let into_iter_expr = match loop_kind {
|
||||
ForLoopKind::For => {
|
||||
// `::std::iter::IntoIterator::into_iter(<head>)`
|
||||
self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IntoIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
)
|
||||
}
|
||||
// ` unsafe { Pin::new_unchecked(&mut into_async_iter(<head>)) }`
|
||||
ForLoopKind::ForAwait => {
|
||||
// `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
|
||||
let iter = self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IntoAsyncIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
);
|
||||
let iter = self.expr_mut_addr_of(head_span, iter);
|
||||
// `Pin::new_unchecked(...)`
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||
head_span,
|
||||
hir::LangItem::PinNewUnchecked,
|
||||
arena_vec![self; iter],
|
||||
));
|
||||
// `unsafe { ... }`
|
||||
let iter = self.arena.alloc(self.expr_unsafe(iter));
|
||||
iter
|
||||
}
|
||||
};
|
||||
|
||||
let match_expr = self.arena.alloc(self.expr_match(
|
||||
@ -2152,3 +2235,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by [`LoweringContext::make_lowered_await`] to customize the desugaring based on what kind
|
||||
/// of future we are awaiting.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum FutureKind {
|
||||
/// We are awaiting a normal future
|
||||
Future,
|
||||
/// We are awaiting something that's known to be an AsyncIterator (i.e. we are in the header of
|
||||
/// a `for await` loop)
|
||||
AsyncIterator,
|
||||
}
|
||||
|
@ -1372,7 +1372,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// need to compute this at all unless there is a Maybe bound.
|
||||
let mut is_param: Option<bool> = None;
|
||||
for bound in &bound_pred.bounds {
|
||||
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
|
||||
if !matches!(
|
||||
*bound,
|
||||
GenericBound::Trait(
|
||||
_,
|
||||
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||
|
@ -130,6 +130,7 @@ struct LoweringContext<'a, 'hir> {
|
||||
allow_try_trait: Lrc<[Symbol]>,
|
||||
allow_gen_future: Lrc<[Symbol]>,
|
||||
allow_async_iterator: Lrc<[Symbol]>,
|
||||
allow_for_await: Lrc<[Symbol]>,
|
||||
|
||||
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
||||
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
|
||||
@ -174,6 +175,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
} else {
|
||||
[sym::gen_future].into()
|
||||
},
|
||||
allow_for_await: [sym::async_iterator].into(),
|
||||
// FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
|
||||
// interact with `gen`/`async gen` blocks
|
||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||
@ -1425,19 +1427,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
|
||||
GenericBound::Trait(
|
||||
ty,
|
||||
modifier @ (TraitBoundModifier::None
|
||||
| TraitBoundModifier::MaybeConst(_)
|
||||
| TraitBoundModifier::Negative),
|
||||
) => {
|
||||
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
|
||||
}
|
||||
// `~const ?Bound` will cause an error during AST validation
|
||||
// anyways, so treat it like `?Bound` as compilation proceeds.
|
||||
TraitBoundModifiers {
|
||||
polarity: BoundPolarity::Positive | BoundPolarity::Negative(_),
|
||||
constness,
|
||||
},
|
||||
) => Some(this.lower_poly_trait_ref(ty, itctx, (*constness).into())),
|
||||
// We can safely ignore constness here, since AST validation
|
||||
// will take care of invalid modifier combinations.
|
||||
GenericBound::Trait(
|
||||
_,
|
||||
TraitBoundModifier::Maybe
|
||||
| TraitBoundModifier::MaybeConstMaybe
|
||||
| TraitBoundModifier::MaybeConstNegative,
|
||||
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
|
||||
) => None,
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
if lifetime_bound.is_none() {
|
||||
@ -2028,9 +2027,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::GenericBound<'hir> {
|
||||
match tpb {
|
||||
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
|
||||
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
|
||||
self.lower_trait_bound_modifier(*modifier),
|
||||
GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
|
||||
self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()),
|
||||
self.lower_trait_bound_modifiers(*modifiers),
|
||||
),
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
||||
@ -2316,25 +2315,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
|
||||
match f {
|
||||
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
||||
TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst,
|
||||
|
||||
TraitBoundModifier::Negative => {
|
||||
fn lower_trait_bound_modifiers(
|
||||
&mut self,
|
||||
modifiers: TraitBoundModifiers,
|
||||
) -> hir::TraitBoundModifier {
|
||||
match (modifiers.constness, modifiers.polarity) {
|
||||
(BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None,
|
||||
(BoundConstness::Never, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||
(BoundConstness::Never, BoundPolarity::Negative(_)) => {
|
||||
if self.tcx.features().negative_bounds {
|
||||
hir::TraitBoundModifier::Negative
|
||||
} else {
|
||||
hir::TraitBoundModifier::None
|
||||
}
|
||||
}
|
||||
|
||||
// `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a
|
||||
// placeholder for compilation to proceed.
|
||||
TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
|
||||
hir::TraitBoundModifier::Maybe
|
||||
(BoundConstness::Maybe(_), BoundPolarity::Positive) => {
|
||||
hir::TraitBoundModifier::MaybeConst
|
||||
}
|
||||
// Invalid modifier combinations will cause an error during AST validation.
|
||||
// Arbitrarily pick a placeholder for compilation to proceed.
|
||||
(BoundConstness::Maybe(_), BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||
(BoundConstness::Maybe(_), BoundPolarity::Negative(_)) => {
|
||||
hir::TraitBoundModifier::MaybeConst
|
||||
}
|
||||
TraitBoundModifier::MaybeConstNegative => hir::TraitBoundModifier::MaybeConst,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
span: self.lower_span(f.span),
|
||||
}
|
||||
}));
|
||||
break hir::PatKind::Struct(qpath, fs, *etc);
|
||||
break hir::PatKind::Struct(qpath, fs, *etc == ast::PatFieldsRest::Rest);
|
||||
}
|
||||
PatKind::Tuple(pats) => {
|
||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
|
||||
|
@ -152,6 +152,8 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
|
||||
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||
.help = remove one of these features
|
||||
|
||||
ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive
|
||||
|
||||
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
|
||||
.because = {$annotation} because of this
|
||||
.type = inherent impl for this type
|
||||
@ -195,8 +197,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
|
||||
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
|
||||
.help = use `auto trait Trait {"{}"}` instead
|
||||
|
||||
ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
|
||||
|
||||
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
|
||||
|
||||
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
|
||||
|
@ -1196,18 +1196,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
|
||||
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
||||
if let GenericBound::Trait(poly, modify) = bound {
|
||||
match (ctxt, modify) {
|
||||
(BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
|
||||
if let GenericBound::Trait(poly, modifiers) = bound {
|
||||
match (ctxt, modifiers.constness, modifiers.polarity) {
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
||||
span: poly.span,
|
||||
path_str: pprust::path_to_string(&poly.trait_ref.path),
|
||||
});
|
||||
}
|
||||
(BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span });
|
||||
}
|
||||
(_, &TraitBoundModifier::MaybeConst(span))
|
||||
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
||||
if let Some(reason) = &self.disallow_tilde_const =>
|
||||
{
|
||||
let reason = match reason {
|
||||
@ -1235,16 +1235,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
};
|
||||
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
||||
}
|
||||
(_, TraitBoundModifier::MaybeConstMaybe) => {
|
||||
self.dcx().emit_err(errors::OptionalConstExclusive {
|
||||
(
|
||||
_,
|
||||
BoundConstness::Maybe(_),
|
||||
BoundPolarity::Maybe(_) | BoundPolarity::Negative(_),
|
||||
) => {
|
||||
self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
|
||||
span: bound.span(),
|
||||
modifier: "?",
|
||||
});
|
||||
}
|
||||
(_, TraitBoundModifier::MaybeConstNegative) => {
|
||||
self.dcx().emit_err(errors::OptionalConstExclusive {
|
||||
span: bound.span(),
|
||||
modifier: "!",
|
||||
left: modifiers.constness.as_str(),
|
||||
right: modifiers.polarity.as_str(),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
@ -1252,7 +1251,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
|
||||
// Negative trait bounds are not allowed to have associated constraints
|
||||
if let GenericBound::Trait(trait_ref, TraitBoundModifier::Negative) = bound
|
||||
if let GenericBound::Trait(trait_ref, modifiers) = bound
|
||||
&& let BoundPolarity::Negative(_) = modifiers.polarity
|
||||
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
|
||||
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
|
||||
{
|
||||
@ -1494,7 +1494,8 @@ fn deny_equality_constraints(
|
||||
for param in &generics.params {
|
||||
if param.ident == potential_param.ident {
|
||||
for bound in ¶m.bounds {
|
||||
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
|
||||
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) =
|
||||
bound
|
||||
{
|
||||
if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
|
||||
let assoc = pprust::path_to_string(&ast::Path::from_ident(
|
||||
|
@ -580,11 +580,12 @@ pub enum TildeConstReason {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_optional_const_exclusive)]
|
||||
pub struct OptionalConstExclusive {
|
||||
#[diag(ast_passes_incompatible_trait_bound_modifiers)]
|
||||
pub struct IncompatibleTraitBoundModifiers {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub modifier: &'static str,
|
||||
pub left: &'static str,
|
||||
pub right: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -527,6 +527,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
"async closures are unstable",
|
||||
"to use an async block, remove the `||`: `async {`"
|
||||
);
|
||||
gate_all!(async_for_loop, "`for await` loops are experimental");
|
||||
gate_all!(
|
||||
closure_lifetime_binder,
|
||||
"`for<...>` binders for closures are experimental",
|
||||
|
@ -4,6 +4,7 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(let_chains)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
mod helpers;
|
||||
|
@ -17,7 +17,7 @@ use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
||||
use rustc_ast::util::parser;
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
||||
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
||||
use rustc_ast::{GenericArg, GenericBound, SelfKind, TraitBoundModifier};
|
||||
use rustc_ast::{GenericArg, GenericBound, SelfKind};
|
||||
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_span::edition::Edition;
|
||||
@ -1427,7 +1427,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
self.nbsp();
|
||||
self.word("{");
|
||||
let empty = fields.is_empty() && !etc;
|
||||
let empty = fields.is_empty() && *etc == ast::PatFieldsRest::None;
|
||||
if !empty {
|
||||
self.space();
|
||||
}
|
||||
@ -1445,7 +1445,7 @@ impl<'a> State<'a> {
|
||||
},
|
||||
|f| f.pat.span,
|
||||
);
|
||||
if *etc {
|
||||
if *etc == ast::PatFieldsRest::Rest {
|
||||
if !fields.is_empty() {
|
||||
self.word_space(",");
|
||||
}
|
||||
@ -1559,26 +1559,20 @@ impl<'a> State<'a> {
|
||||
|
||||
match bound {
|
||||
GenericBound::Trait(tref, modifier) => {
|
||||
match modifier {
|
||||
TraitBoundModifier::None => {}
|
||||
TraitBoundModifier::Negative => {
|
||||
self.word("!");
|
||||
}
|
||||
TraitBoundModifier::Maybe => {
|
||||
self.word("?");
|
||||
}
|
||||
TraitBoundModifier::MaybeConst(_) => {
|
||||
self.word_space("~const");
|
||||
}
|
||||
TraitBoundModifier::MaybeConstNegative => {
|
||||
self.word_space("~const");
|
||||
self.word("!");
|
||||
}
|
||||
TraitBoundModifier::MaybeConstMaybe => {
|
||||
self.word_space("~const");
|
||||
self.word("?");
|
||||
match modifier.constness {
|
||||
ast::BoundConstness::Never => {}
|
||||
ast::BoundConstness::Maybe(_) => {
|
||||
self.word_space(modifier.constness.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
match modifier.polarity {
|
||||
ast::BoundPolarity::Positive => {}
|
||||
ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
|
||||
self.word(modifier.polarity.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
self.print_poly_trait_ref(tref);
|
||||
}
|
||||
GenericBound::Outlives(lt) => self.print_lifetime(*lt),
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||
use ast::ForLoopKind;
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
@ -418,20 +419,23 @@ impl<'a> State<'a> {
|
||||
self.space();
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
}
|
||||
ast::ExprKind::ForLoop(pat, iter, blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
ast::ExprKind::ForLoop { pat, iter, body, label, kind } => {
|
||||
if let Some(label) = label {
|
||||
self.print_ident(label.ident);
|
||||
self.word_space(":");
|
||||
}
|
||||
self.cbox(0);
|
||||
self.ibox(0);
|
||||
self.word_nbsp("for");
|
||||
if kind == &ForLoopKind::ForAwait {
|
||||
self.word_nbsp("await");
|
||||
}
|
||||
self.print_pat(pat);
|
||||
self.space();
|
||||
self.word_space("in");
|
||||
self.print_expr_as_cond(iter);
|
||||
self.space();
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
self.print_block_with_attrs(body, attrs);
|
||||
}
|
||||
ast::ExprKind::Loop(blk, opt_label, _) => {
|
||||
if let Some(label) = opt_label {
|
||||
|
@ -5,7 +5,6 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||
use ast::StaticItem;
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::GenericBound;
|
||||
use rustc_ast::ModKind;
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
@ -338,19 +337,9 @@ impl<'a> State<'a> {
|
||||
self.word_nbsp("trait");
|
||||
self.print_ident(item.ident);
|
||||
self.print_generic_params(&generics.params);
|
||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
for b in bounds.iter() {
|
||||
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
|
||||
self.space();
|
||||
self.word_space("for ?");
|
||||
self.print_trait_ref(&ptr.trait_ref);
|
||||
} else {
|
||||
real_bounds.push(b.clone());
|
||||
}
|
||||
}
|
||||
if !real_bounds.is_empty() {
|
||||
if !bounds.is_empty() {
|
||||
self.word_nbsp(":");
|
||||
self.print_type_bounds(&real_bounds);
|
||||
self.print_type_bounds(bounds);
|
||||
}
|
||||
self.print_where_clause(&generics.where_clause);
|
||||
self.word(" ");
|
||||
|
@ -2,7 +2,8 @@ use std::num::IntErrorKind;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::{
|
||||
error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
||||
error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
Level,
|
||||
};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -50,14 +51,12 @@ pub(crate) struct UnknownMetaItem<'a> {
|
||||
}
|
||||
|
||||
// Manual implementation to be able to format `expected` items correctly.
|
||||
impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
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 = dcx.struct_span_err_with_code(
|
||||
self.span,
|
||||
fluent::attr_unknown_meta_item,
|
||||
error_code!(E0541),
|
||||
);
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item);
|
||||
diag.set_span(self.span);
|
||||
diag.code(error_code!(E0541));
|
||||
diag.set_arg("item", self.item);
|
||||
diag.set_arg("expected", expected.join(", "));
|
||||
diag.span_label(self.span, fluent::attr_label);
|
||||
@ -200,10 +199,11 @@ pub(crate) struct UnsupportedLiteral {
|
||||
pub start_point_span: Span,
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut diag = dcx.struct_span_err_with_code(
|
||||
self.span,
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
match self.reason {
|
||||
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
||||
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
||||
@ -214,8 +214,9 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
||||
fluent::attr_unsupported_literal_deprecated_kv_pair
|
||||
}
|
||||
},
|
||||
error_code!(E0565),
|
||||
);
|
||||
diag.set_span(self.span);
|
||||
diag.code(error_code!(E0565));
|
||||
if self.is_bytestr {
|
||||
diag.span_suggestion(
|
||||
self.start_point_span,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc_errors::{
|
||||
struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
@ -12,7 +12,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
place: &str,
|
||||
borrow_place: &str,
|
||||
value_place: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow {
|
||||
place,
|
||||
span,
|
||||
@ -28,7 +28,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
desc: &str,
|
||||
borrow_span: Span,
|
||||
borrow_desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
span,
|
||||
@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
old_loan_span: Span,
|
||||
old_opt_via: &str,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
@ -97,7 +97,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
desc: &str,
|
||||
old_loan_span: Span,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
new_loan_span,
|
||||
@ -130,7 +130,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
noun_old: &str,
|
||||
old_opt_via: &str,
|
||||
previous_end_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
new_loan_span,
|
||||
@ -162,7 +162,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
old_opt_via: &str,
|
||||
previous_end_span: Option<Span>,
|
||||
second_borrow_desc: &str,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
new_loan_span,
|
||||
@ -194,7 +194,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
kind_old: &str,
|
||||
msg_old: &str,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
@ -235,7 +235,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span: Span,
|
||||
borrow_span: Span,
|
||||
desc: &str,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
span,
|
||||
@ -254,16 +254,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span: Span,
|
||||
desc: &str,
|
||||
is_arg: bool,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
|
||||
struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc)
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_assign(
|
||||
&self,
|
||||
span: Span,
|
||||
desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
|
||||
}
|
||||
|
||||
@ -271,7 +267,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
move_from_span: Span,
|
||||
move_from_desc: &str,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc)
|
||||
}
|
||||
|
||||
@ -283,7 +279,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_from_span: Span,
|
||||
ty: Ty<'_>,
|
||||
is_index: Option<bool>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let type_name = match (&ty.kind(), is_index) {
|
||||
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
|
||||
(&ty::Slice(_), _) => "slice",
|
||||
@ -305,7 +301,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
move_from_span: Span,
|
||||
container_ty: Ty<'_>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
move_from_span,
|
||||
@ -323,7 +319,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
verb: &str,
|
||||
optional_adverb_for_moved: &str,
|
||||
moved_path: Option<String>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
|
||||
|
||||
struct_span_err!(
|
||||
@ -342,7 +338,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span: Span,
|
||||
path: &str,
|
||||
reason: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,)
|
||||
}
|
||||
|
||||
@ -353,7 +349,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
immutable_place: &str,
|
||||
immutable_section: &str,
|
||||
action: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
mutate_span,
|
||||
@ -372,7 +368,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
span: Span,
|
||||
yield_span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
@ -387,7 +383,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
pub(crate) fn cannot_borrow_across_destructor(
|
||||
&self,
|
||||
borrow_span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(
|
||||
self,
|
||||
borrow_span,
|
||||
@ -400,7 +396,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
span: Span,
|
||||
path: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(self, span, E0597, "{} does not live long enough", path,)
|
||||
}
|
||||
|
||||
@ -410,7 +406,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return_kind: &str,
|
||||
reference_desc: &str,
|
||||
path_desc: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
span,
|
||||
@ -436,7 +432,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrowed_path: &str,
|
||||
capture_span: Span,
|
||||
scope: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
closure_span,
|
||||
@ -452,14 +448,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(
|
||||
&self,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",)
|
||||
}
|
||||
|
||||
pub(crate) fn temporary_value_borrowed_for_too_long(
|
||||
&self,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
|
||||
}
|
||||
|
||||
@ -470,7 +466,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
sp: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
|
||||
}
|
||||
}
|
||||
@ -479,7 +475,7 @@ pub(crate) fn borrowed_data_escapes_closure<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
escape_span: Span,
|
||||
escapes_from: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
escape_span,
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_infer::infer::canonical::Canonical;
|
||||
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use rustc_infer::infer::region_constraints::Constraint;
|
||||
@ -147,11 +147,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for ! {
|
||||
trait TypeOpInfo<'tcx> {
|
||||
/// Returns an error to be reported if rerunning the type op fails to
|
||||
/// recover the error's cause.
|
||||
fn fallback_error(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
|
||||
|
||||
fn base_universe(&self) -> ty::UniverseIndex;
|
||||
|
||||
@ -161,7 +157,7 @@ trait TypeOpInfo<'tcx> {
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
|
||||
) -> Option<DiagnosticBuilder<'tcx>>;
|
||||
|
||||
#[instrument(level = "debug", skip(self, mbcx))]
|
||||
fn report_error(
|
||||
@ -224,11 +220,7 @@ struct PredicateQuery<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
||||
fn fallback_error(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
tcx.sess.create_err(HigherRankedLifetimeError {
|
||||
cause: Some(HigherRankedErrorCause::CouldNotProve {
|
||||
predicate: self.canonical_query.value.value.predicate.to_string(),
|
||||
@ -247,7 +239,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
@ -265,11 +257,7 @@ impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
|
||||
where
|
||||
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
|
||||
{
|
||||
fn fallback_error(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
tcx.sess.create_err(HigherRankedLifetimeError {
|
||||
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
|
||||
value: self.canonical_query.value.value.value.to_string(),
|
||||
@ -288,7 +276,7 @@ where
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
@ -312,11 +300,7 @@ struct AscribeUserTypeQuery<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
||||
fn fallback_error(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
||||
// and is only the fallback when the nice error fails. Consider improving this some more.
|
||||
tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
|
||||
@ -332,7 +316,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
@ -342,11 +326,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
||||
fn fallback_error(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
||||
// and is only the fallback when the nice error fails. Consider improving this some more.
|
||||
tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
|
||||
@ -362,7 +342,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
||||
_cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
try_extract_error_from_region_constraints(
|
||||
mbcx.infcx,
|
||||
placeholder_region,
|
||||
@ -383,7 +363,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
// We generally shouldn't have errors here because the query was
|
||||
// already run, but there's no point using `span_delayed_bug`
|
||||
// when we're going to emit an error here anyway.
|
||||
@ -407,14 +387,19 @@ fn try_extract_error_from_region_constraints<'tcx>(
|
||||
region_constraints: &RegionConstraintData<'tcx>,
|
||||
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
|
||||
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
let placeholder_universe = match placeholder_region.kind() {
|
||||
ty::RePlaceholder(p) => p.universe,
|
||||
ty::ReVar(vid) => universe_of_region(vid),
|
||||
_ => ty::UniverseIndex::ROOT,
|
||||
};
|
||||
let matches =
|
||||
|a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
|
||||
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
|
||||
_ => a_region == b_region,
|
||||
};
|
||||
let check = |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| {
|
||||
match *constraint {
|
||||
let mut check =
|
||||
|constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint {
|
||||
Constraint::RegSubReg(sub, sup)
|
||||
if ((exact && sup == placeholder_region)
|
||||
|| (!exact && matches(sup, placeholder_region)))
|
||||
@ -422,16 +407,16 @@ fn try_extract_error_from_region_constraints<'tcx>(
|
||||
{
|
||||
Some((sub, cause.clone()))
|
||||
}
|
||||
// FIXME: Should this check the universe of the var?
|
||||
Constraint::VarSubReg(vid, sup)
|
||||
if ((exact && sup == placeholder_region)
|
||||
|| (!exact && matches(sup, placeholder_region))) =>
|
||||
if (exact
|
||||
&& sup == placeholder_region
|
||||
&& !universe_of_region(vid).can_name(placeholder_universe))
|
||||
|| (!exact && matches(sup, placeholder_region)) =>
|
||||
{
|
||||
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
};
|
||||
let mut info = region_constraints
|
||||
.constraints
|
||||
.iter()
|
||||
|
@ -1,13 +1,11 @@
|
||||
use either::Either;
|
||||
use hir::PatField;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{
|
||||
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
||||
use rustc_hir::{CoroutineDesugaring, PatField};
|
||||
use rustc_hir::{CoroutineKind, CoroutineSource, LangItem};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||
@ -324,7 +322,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
mpi: MovePathIndex,
|
||||
move_span: Span,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
in_pattern: &mut bool,
|
||||
move_spans: UseSpans<'_>,
|
||||
) {
|
||||
@ -483,7 +481,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
desired_action: InitializationRequiringAction,
|
||||
span: Span,
|
||||
use_spans: UseSpans<'tcx>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
// We need all statements in the body where the binding was assigned to to later find all
|
||||
// the branching code paths where the binding *wasn't* assigned to.
|
||||
let inits = &self.move_data.init_path_map[mpi];
|
||||
@ -873,7 +871,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
location: Location,
|
||||
(place, _span): (Place<'tcx>, Span),
|
||||
borrow: &BorrowData<'tcx>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
||||
let borrow_span = borrow_spans.args_or_use();
|
||||
|
||||
@ -921,7 +919,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
issued_borrow: &BorrowData<'tcx>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
|
||||
let issued_span = issued_spans.args_or_use();
|
||||
|
||||
@ -2025,7 +2023,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
drop_span: Span,
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
explanation: BorrowExplanation<'tcx>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
debug!(
|
||||
"report_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}, {:?}, {:?}, {:?}\
|
||||
@ -2200,7 +2198,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
drop_span: Span,
|
||||
borrow_span: Span,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
debug!(
|
||||
"report_thread_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}\
|
||||
@ -2228,7 +2226,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
proper_span: Span,
|
||||
explanation: BorrowExplanation<'tcx>,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
||||
explanation
|
||||
{
|
||||
@ -2395,7 +2393,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return_span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
opt_place_desc: Option<&String>,
|
||||
) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'cx>> {
|
||||
let return_kind = match category {
|
||||
ConstraintCategory::Return(_) => "return",
|
||||
ConstraintCategory::Yield => "yield",
|
||||
@ -2490,7 +2488,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
constraint_span: Span,
|
||||
captured_var: &str,
|
||||
scope: &str,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let args_span = use_span.args_or_use();
|
||||
|
||||
@ -2516,27 +2514,29 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
};
|
||||
let kind = match use_span.coroutine_kind() {
|
||||
Some(coroutine_kind) => match coroutine_kind {
|
||||
CoroutineKind::Gen(kind) => match kind {
|
||||
CoroutineKind::Desugared(CoroutineDesugaring::Gen, kind) => match kind {
|
||||
CoroutineSource::Block => "gen block",
|
||||
CoroutineSource::Closure => "gen closure",
|
||||
CoroutineSource::Fn => {
|
||||
bug!("gen block/closure expected, but gen function found.")
|
||||
}
|
||||
},
|
||||
CoroutineKind::AsyncGen(kind) => match kind {
|
||||
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, kind) => match kind {
|
||||
CoroutineSource::Block => "async gen block",
|
||||
CoroutineSource::Closure => "async gen closure",
|
||||
CoroutineSource::Fn => {
|
||||
bug!("gen block/closure expected, but gen function found.")
|
||||
}
|
||||
},
|
||||
CoroutineKind::Async(async_kind) => match async_kind {
|
||||
CoroutineSource::Block => "async block",
|
||||
CoroutineSource::Closure => "async closure",
|
||||
CoroutineSource::Fn => {
|
||||
bug!("async block/closure expected, but async function found.")
|
||||
CoroutineKind::Desugared(CoroutineDesugaring::Async, async_kind) => {
|
||||
match async_kind {
|
||||
CoroutineSource::Block => "async block",
|
||||
CoroutineSource::Closure => "async closure",
|
||||
CoroutineSource::Fn => {
|
||||
bug!("async block/closure expected, but async function found.")
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
CoroutineKind::Coroutine => "coroutine",
|
||||
},
|
||||
None => "closure",
|
||||
@ -2566,7 +2566,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
ConstraintCategory::CallArgument(_) => {
|
||||
fr_name.highlight_region_name(&mut err);
|
||||
if matches!(use_span.coroutine_kind(), Some(CoroutineKind::Async(_))) {
|
||||
if matches!(
|
||||
use_span.coroutine_kind(),
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _))
|
||||
) {
|
||||
err.note(
|
||||
"async blocks are not executed immediately and must either take a \
|
||||
reference or ownership of outside variables they use",
|
||||
@ -2593,7 +2596,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
upvar_span: Span,
|
||||
upvar_name: Symbol,
|
||||
escape_span: Span,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
@ -288,7 +288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
&mut self,
|
||||
place: Place<'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let description = if place.projection.len() == 1 {
|
||||
format!("static item {}", self.describe_any_place(place.as_ref()))
|
||||
} else {
|
||||
@ -310,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
deref_target_place: Place<'tcx>,
|
||||
span: Span,
|
||||
use_spans: Option<UseSpans<'tcx>>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
// Inspect the type of the content behind the
|
||||
// borrow to provide feedback about why this
|
||||
// was a move rather than a copy.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use hir::ExprKind;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::Node;
|
||||
@ -711,7 +711,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
|
||||
fn construct_mut_suggestion_for_local_binding_patterns(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
local: Local,
|
||||
) {
|
||||
let local_decl = &self.body.local_decls[local];
|
||||
@ -1025,7 +1025,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
||||
fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_>) {
|
||||
let source = self.body.source;
|
||||
let hir = self.infcx.tcx.hir();
|
||||
if let InstanceDef::Item(def_id) = source.instance
|
||||
@ -1067,12 +1067,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_make_local_mut(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
local: Local,
|
||||
name: Symbol,
|
||||
) {
|
||||
fn suggest_make_local_mut(&self, err: &mut DiagnosticBuilder<'_>, local: Local, name: Symbol) {
|
||||
let local_decl = &self.body.local_decls[local];
|
||||
|
||||
let (pointer_sigil, pointer_desc) =
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! Error reporting machinery for lifetime errors.
|
||||
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res::Def;
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -202,7 +202,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
// and the span which bounded to the trait for adding 'static lifetime suggestion
|
||||
fn suggest_static_lifetime_for_gat_from_hrtb(
|
||||
&self,
|
||||
diag: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
diag: &mut DiagnosticBuilder<'_>,
|
||||
lower_bound: RegionVid,
|
||||
) {
|
||||
let mut suggestions = vec![];
|
||||
@ -573,7 +573,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
kind: ReturnConstraint,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||
|
||||
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
@ -645,7 +645,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
fn report_escaping_data_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let ErrorConstraintInfo { span, category, .. } = errci;
|
||||
|
||||
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||
@ -744,10 +744,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
/// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
|
||||
/// | is returning data with lifetime `'b`
|
||||
/// ```
|
||||
fn report_general_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> DiagnosticBuilder<'tcx> {
|
||||
let ErrorConstraintInfo {
|
||||
fr,
|
||||
fr_is_local,
|
||||
@ -1049,7 +1046,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
..
|
||||
}) => {
|
||||
let body = map.body(*body);
|
||||
if !matches!(body.coroutine_kind, Some(hir::CoroutineKind::Async(..))) {
|
||||
if !matches!(
|
||||
body.coroutine_kind,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _))
|
||||
) {
|
||||
closure_span = Some(expr.span.shrink_to_lo());
|
||||
}
|
||||
}
|
||||
|
@ -684,39 +684,46 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
|
||||
};
|
||||
let mir_description = match hir.body(body).coroutine_kind {
|
||||
Some(hir::CoroutineKind::Async(src)) => match src {
|
||||
hir::CoroutineSource::Block => " of async block",
|
||||
hir::CoroutineSource::Closure => " of async closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from async fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
if let hir::FnRetTy::Return(ret) = output {
|
||||
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, src)) => {
|
||||
match src {
|
||||
hir::CoroutineSource::Block => " of async block",
|
||||
hir::CoroutineSource::Closure => " of async closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from async fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
if let hir::FnRetTy::Return(ret) = output {
|
||||
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
||||
}
|
||||
" of async function"
|
||||
}
|
||||
" of async function"
|
||||
}
|
||||
},
|
||||
Some(hir::CoroutineKind::Gen(src)) => match src {
|
||||
hir::CoroutineSource::Block => " of gen block",
|
||||
hir::CoroutineSource::Closure => " of gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from gen fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
" of gen function"
|
||||
}
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, src)) => {
|
||||
match src {
|
||||
hir::CoroutineSource::Block => " of gen block",
|
||||
hir::CoroutineSource::Closure => " of gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from gen fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
" of gen function"
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Some(hir::CoroutineKind::AsyncGen(src)) => match src {
|
||||
Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
src,
|
||||
)) => match src {
|
||||
hir::CoroutineSource::Block => " of async gen block",
|
||||
hir::CoroutineSource::Closure => " of async gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
|
@ -2407,8 +2407,8 @@ mod error {
|
||||
/// when errors in the map are being re-added to the error buffer so that errors with the
|
||||
/// same primary span come out in a consistent order.
|
||||
buffered_move_errors:
|
||||
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>,
|
||||
buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>,
|
||||
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>,
|
||||
buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>,
|
||||
/// Diagnostics to be reported buffer.
|
||||
buffered: Vec<Diagnostic>,
|
||||
/// Set to Some if we emit an error during borrowck
|
||||
@ -2426,7 +2426,7 @@ mod error {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
|
||||
if let None = self.tainted_by_errors {
|
||||
self.tainted_by_errors = Some(self.tcx.sess.span_delayed_bug(
|
||||
t.span.clone_ignoring_labels(),
|
||||
@ -2446,7 +2446,7 @@ mod error {
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
|
||||
self.errors.buffer_error(t);
|
||||
}
|
||||
|
||||
@ -2457,7 +2457,7 @@ mod error {
|
||||
pub fn buffer_move_error(
|
||||
&mut self,
|
||||
move_out_indices: Vec<MoveOutIndex>,
|
||||
place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>),
|
||||
place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>),
|
||||
) -> bool {
|
||||
if let Some((_, diag)) =
|
||||
self.errors.buffered_move_errors.insert(move_out_indices, place_and_err)
|
||||
@ -2473,16 +2473,11 @@ mod error {
|
||||
pub fn get_buffered_mut_error(
|
||||
&mut self,
|
||||
span: Span,
|
||||
) -> Option<(DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)> {
|
||||
) -> Option<(DiagnosticBuilder<'tcx>, usize)> {
|
||||
self.errors.buffered_mut_errors.remove(&span)
|
||||
}
|
||||
|
||||
pub fn buffer_mut_error(
|
||||
&mut self,
|
||||
span: Span,
|
||||
t: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
count: usize,
|
||||
) {
|
||||
pub fn buffer_mut_error(&mut self, span: Span, t: DiagnosticBuilder<'tcx>, count: usize) {
|
||||
self.errors.buffered_mut_errors.insert(span, (t, count));
|
||||
}
|
||||
|
||||
@ -2517,7 +2512,7 @@ mod error {
|
||||
pub fn has_move_error(
|
||||
&self,
|
||||
move_out_indices: &[MoveOutIndex],
|
||||
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx, ErrorGuaranteed>)> {
|
||||
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> {
|
||||
self.errors.buffered_move_errors.get(move_out_indices)
|
||||
}
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
| ExprKind::Continue(_)
|
||||
| ExprKind::Err
|
||||
| ExprKind::Field(_, _)
|
||||
| ExprKind::ForLoop(_, _, _, _)
|
||||
| ExprKind::ForLoop { .. }
|
||||
| ExprKind::FormatArgs(_)
|
||||
| ExprKind::IncludedBytes(..)
|
||||
| ExprKind::InlineAsm(_)
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_errors::{
|
||||
AddToDiagnostic, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
|
||||
SingleLabelManySpans,
|
||||
AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
|
||||
MultiSpan, SingleLabelManySpans,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
@ -446,14 +446,14 @@ pub(crate) struct EnvNotDefinedWithUserMessage {
|
||||
}
|
||||
|
||||
// Hand-written implementation to support custom user messages.
|
||||
impl<'a> IntoDiagnostic<'a> for EnvNotDefinedWithUserMessage {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage {
|
||||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
#[expect(
|
||||
rustc::untranslatable_diagnostic,
|
||||
reason = "cannot translate user-provided messages"
|
||||
)]
|
||||
let mut diag = dcx.struct_err(self.msg_from_user.to_string());
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string());
|
||||
diag.set_span(self.span);
|
||||
diag
|
||||
}
|
||||
@ -801,9 +801,13 @@ pub(crate) struct AsmClobberNoReg {
|
||||
pub(crate) clobbers: Vec<Span>,
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a> for AsmClobberNoReg {
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut diag = dcx.struct_err(crate::fluent_generated::builtin_macros_asm_clobber_no_reg);
|
||||
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.set_span(self.spans.clone());
|
||||
// eager translation as `span_labels` takes `AsRef<str>`
|
||||
let lbl1 = dcx.eagerly_translate_to_string(
|
||||
|
@ -8,9 +8,7 @@ use rustc_ast::{
|
||||
FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{
|
||||
Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult, SingleLabelManySpans,
|
||||
};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan, PResult, SingleLabelManySpans};
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_parse_format as parse;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
@ -726,7 +724,7 @@ fn report_redundant_format_arguments<'a>(
|
||||
args: &FormatArguments,
|
||||
used: &[bool],
|
||||
placeholders: Vec<(Span, &str)>,
|
||||
) -> Option<DiagnosticBuilder<'a, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'a>> {
|
||||
let mut fmt_arg_indices = vec![];
|
||||
let mut args_spans = vec![];
|
||||
let mut fmt_spans = vec![];
|
||||
@ -885,7 +883,6 @@ fn report_invalid_references(
|
||||
highlight: SingleLabelManySpans {
|
||||
spans: args.explicit_args().iter().map(|arg| arg.expr.span).collect(),
|
||||
label: "",
|
||||
kind: rustc_errors::LabelKind::Label,
|
||||
},
|
||||
});
|
||||
// Point out `{:.*}` placeholders: those take an extra argument.
|
||||
|
@ -5,7 +5,7 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, attr, GenericParamKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, Level};
|
||||
use rustc_expand::base::*;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
|
||||
@ -391,15 +391,14 @@ pub fn expand_test_or_bench(
|
||||
fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) {
|
||||
let dcx = cx.sess.dcx();
|
||||
let msg = "the `#[test]` attribute may only be used on a non-associated function";
|
||||
let mut err = match item.map(|i| &i.kind) {
|
||||
let level = match item.map(|i| &i.kind) {
|
||||
// These were a warning before #92959 and need to continue being that to avoid breaking
|
||||
// stable user code (#94508).
|
||||
Some(ast::ItemKind::MacCall(_)) => dcx.struct_span_warn(attr_sp, msg),
|
||||
// `.forget_guarantee()` needed to get these two arms to match types. Because of how
|
||||
// locally close the `.emit()` call is I'm comfortable with it, but if it can be
|
||||
// reworked in the future to not need it, it'd be nice.
|
||||
_ => dcx.struct_span_err(attr_sp, msg).forget_guarantee(),
|
||||
Some(ast::ItemKind::MacCall(_)) => Level::Warning(None),
|
||||
_ => Level::Error { lint: false },
|
||||
};
|
||||
let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg);
|
||||
err.set_span(attr_sp);
|
||||
if let Some(item) = item {
|
||||
err.span_label(
|
||||
item.span,
|
||||
|
@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76eb38f2af690b5a4411d9a8782b6d77dabff3ca939e0518453ab9f9a4392d41"
|
||||
checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39526c036b92912417e8931f52c1e235796688068d3efdbbd8b164f299d19156"
|
||||
checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
@ -75,39 +75,39 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb0deedc9fccf2db53a5a3c9c9d0163e44143b0d004dca9bf6ab6a0024cd79a"
|
||||
checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea2d1b274e45aa8e61e9103efa1ba82d4b5a19d12bd1fd10744c3b7380ba3ff"
|
||||
checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ea5977559a71e63db79a263f0e81a89b996e8a38212c4281e37dd1dbaa8b65c"
|
||||
checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f871ada808b58158d84dfc43a6a2e2d2756baaf4ed1c51fd969ca8330e6ca5c"
|
||||
checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8e6890f587ef59824b3debe577e68fdf9b307b3808c54b8d93a18fd0b70941b"
|
||||
checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@ -117,15 +117,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d5fc6d5d3b52d1917002b17a8ecce448c2621b5bf394bb4e77e2f676893537"
|
||||
checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8a2d7744f743f59d9646d7589ad22ea17ed0d71e04906eb77c31e99bc13bd8b"
|
||||
checksum = "4946271f1055e26544ef8c90fa24776f201566419dfac4b3962c39d5a804ff67"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -143,9 +143,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b96cb196334698e612c197d7d0ae59af5e07667306ec20d7be414717db400873"
|
||||
checksum = "cb7e3bdae2597556e59edeb8ecb62eb32c7e054c4f042d393732902979db69c3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -154,9 +154,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e10c2e7faa65d4ae7de9a83b44f2c31aca7dc638e17d0a79572fdf8103d720b"
|
||||
checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@ -165,9 +165,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.102.0"
|
||||
version = "0.103.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83ce94e18756058af8a66e3c0ba1123ae15517c72162d8060d0cb0974642adf2"
|
||||
checksum = "59e0ee3d013728903e0c513c31afa389b559bfd4fe8a44f80335c799e3132a41"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "15.0.0"
|
||||
version = "16.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b73ad1395eda136baec5ece7e079e0536a82ef73488e345456cc9b89858ad0ec"
|
||||
checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
@ -8,12 +8,12 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.102", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.102" }
|
||||
cranelift-module = { version = "0.102" }
|
||||
cranelift-native = { version = "0.102" }
|
||||
cranelift-jit = { version = "0.102", optional = true }
|
||||
cranelift-object = { version = "0.102" }
|
||||
cranelift-codegen = { version = "0.103", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.103" }
|
||||
cranelift-module = { version = "0.103" }
|
||||
cranelift-native = { version = "0.103" }
|
||||
cranelift-jit = { version = "0.103", optional = true }
|
||||
cranelift-object = { version = "0.103" }
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.28", default-features = false, features = ["write"]}
|
||||
object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
@ -538,261 +538,38 @@ pub enum E1 {
|
||||
pub enum E2<X> {
|
||||
V1 { f: bool },
|
||||
|
||||
/*_00*/ _01(X),
|
||||
_02(X),
|
||||
_03(X),
|
||||
_04(X),
|
||||
_05(X),
|
||||
_06(X),
|
||||
_07(X),
|
||||
_08(X),
|
||||
_09(X),
|
||||
_0A(X),
|
||||
_0B(X),
|
||||
_0C(X),
|
||||
_0D(X),
|
||||
_0E(X),
|
||||
_0F(X),
|
||||
_10(X),
|
||||
_11(X),
|
||||
_12(X),
|
||||
_13(X),
|
||||
_14(X),
|
||||
_15(X),
|
||||
_16(X),
|
||||
_17(X),
|
||||
_18(X),
|
||||
_19(X),
|
||||
_1A(X),
|
||||
_1B(X),
|
||||
_1C(X),
|
||||
_1D(X),
|
||||
_1E(X),
|
||||
_1F(X),
|
||||
_20(X),
|
||||
_21(X),
|
||||
_22(X),
|
||||
_23(X),
|
||||
_24(X),
|
||||
_25(X),
|
||||
_26(X),
|
||||
_27(X),
|
||||
_28(X),
|
||||
_29(X),
|
||||
_2A(X),
|
||||
_2B(X),
|
||||
_2C(X),
|
||||
_2D(X),
|
||||
_2E(X),
|
||||
_2F(X),
|
||||
_30(X),
|
||||
_31(X),
|
||||
_32(X),
|
||||
_33(X),
|
||||
_34(X),
|
||||
_35(X),
|
||||
_36(X),
|
||||
_37(X),
|
||||
_38(X),
|
||||
_39(X),
|
||||
_3A(X),
|
||||
_3B(X),
|
||||
_3C(X),
|
||||
_3D(X),
|
||||
_3E(X),
|
||||
_3F(X),
|
||||
_40(X),
|
||||
_41(X),
|
||||
_42(X),
|
||||
_43(X),
|
||||
_44(X),
|
||||
_45(X),
|
||||
_46(X),
|
||||
_47(X),
|
||||
_48(X),
|
||||
_49(X),
|
||||
_4A(X),
|
||||
_4B(X),
|
||||
_4C(X),
|
||||
_4D(X),
|
||||
_4E(X),
|
||||
_4F(X),
|
||||
_50(X),
|
||||
_51(X),
|
||||
_52(X),
|
||||
_53(X),
|
||||
_54(X),
|
||||
_55(X),
|
||||
_56(X),
|
||||
_57(X),
|
||||
_58(X),
|
||||
_59(X),
|
||||
_5A(X),
|
||||
_5B(X),
|
||||
_5C(X),
|
||||
_5D(X),
|
||||
_5E(X),
|
||||
_5F(X),
|
||||
_60(X),
|
||||
_61(X),
|
||||
_62(X),
|
||||
_63(X),
|
||||
_64(X),
|
||||
_65(X),
|
||||
_66(X),
|
||||
_67(X),
|
||||
_68(X),
|
||||
_69(X),
|
||||
_6A(X),
|
||||
_6B(X),
|
||||
_6C(X),
|
||||
_6D(X),
|
||||
_6E(X),
|
||||
_6F(X),
|
||||
_70(X),
|
||||
_71(X),
|
||||
_72(X),
|
||||
_73(X),
|
||||
_74(X),
|
||||
_75(X),
|
||||
_76(X),
|
||||
_77(X),
|
||||
_78(X),
|
||||
_79(X),
|
||||
_7A(X),
|
||||
_7B(X),
|
||||
_7C(X),
|
||||
_7D(X),
|
||||
_7E(X),
|
||||
_7F(X),
|
||||
_80(X),
|
||||
_81(X),
|
||||
_82(X),
|
||||
_83(X),
|
||||
_84(X),
|
||||
_85(X),
|
||||
_86(X),
|
||||
_87(X),
|
||||
_88(X),
|
||||
_89(X),
|
||||
_8A(X),
|
||||
_8B(X),
|
||||
_8C(X),
|
||||
_8D(X),
|
||||
_8E(X),
|
||||
_8F(X),
|
||||
_90(X),
|
||||
_91(X),
|
||||
_92(X),
|
||||
_93(X),
|
||||
_94(X),
|
||||
_95(X),
|
||||
_96(X),
|
||||
_97(X),
|
||||
_98(X),
|
||||
_99(X),
|
||||
_9A(X),
|
||||
_9B(X),
|
||||
_9C(X),
|
||||
_9D(X),
|
||||
_9E(X),
|
||||
_9F(X),
|
||||
_A0(X),
|
||||
_A1(X),
|
||||
_A2(X),
|
||||
_A3(X),
|
||||
_A4(X),
|
||||
_A5(X),
|
||||
_A6(X),
|
||||
_A7(X),
|
||||
_A8(X),
|
||||
_A9(X),
|
||||
_AA(X),
|
||||
_AB(X),
|
||||
_AC(X),
|
||||
_AD(X),
|
||||
_AE(X),
|
||||
_AF(X),
|
||||
_B0(X),
|
||||
_B1(X),
|
||||
_B2(X),
|
||||
_B3(X),
|
||||
_B4(X),
|
||||
_B5(X),
|
||||
_B6(X),
|
||||
_B7(X),
|
||||
_B8(X),
|
||||
_B9(X),
|
||||
_BA(X),
|
||||
_BB(X),
|
||||
_BC(X),
|
||||
_BD(X),
|
||||
_BE(X),
|
||||
_BF(X),
|
||||
_C0(X),
|
||||
_C1(X),
|
||||
_C2(X),
|
||||
_C3(X),
|
||||
_C4(X),
|
||||
_C5(X),
|
||||
_C6(X),
|
||||
_C7(X),
|
||||
_C8(X),
|
||||
_C9(X),
|
||||
_CA(X),
|
||||
_CB(X),
|
||||
_CC(X),
|
||||
_CD(X),
|
||||
_CE(X),
|
||||
_CF(X),
|
||||
_D0(X),
|
||||
_D1(X),
|
||||
_D2(X),
|
||||
_D3(X),
|
||||
_D4(X),
|
||||
_D5(X),
|
||||
_D6(X),
|
||||
_D7(X),
|
||||
_D8(X),
|
||||
_D9(X),
|
||||
_DA(X),
|
||||
_DB(X),
|
||||
_DC(X),
|
||||
_DD(X),
|
||||
_DE(X),
|
||||
_DF(X),
|
||||
_E0(X),
|
||||
_E1(X),
|
||||
_E2(X),
|
||||
_E3(X),
|
||||
_E4(X),
|
||||
_E5(X),
|
||||
_E6(X),
|
||||
_E7(X),
|
||||
_E8(X),
|
||||
_E9(X),
|
||||
_EA(X),
|
||||
_EB(X),
|
||||
_EC(X),
|
||||
_ED(X),
|
||||
_EE(X),
|
||||
_EF(X),
|
||||
_F0(X),
|
||||
_F1(X),
|
||||
_F2(X),
|
||||
_F3(X),
|
||||
_F4(X),
|
||||
_F5(X),
|
||||
_F6(X),
|
||||
_F7(X),
|
||||
_F8(X),
|
||||
_F9(X),
|
||||
_FA(X),
|
||||
_FB(X),
|
||||
_FC(X),
|
||||
_FD(X),
|
||||
_FE(X),
|
||||
_FF(X),
|
||||
/*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X),
|
||||
_08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X),
|
||||
_10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X),
|
||||
_18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X),
|
||||
_20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X),
|
||||
_28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X),
|
||||
_30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X),
|
||||
_38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X),
|
||||
_40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X),
|
||||
_48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X),
|
||||
_50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X),
|
||||
_58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X),
|
||||
_60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X),
|
||||
_68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X),
|
||||
_70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X),
|
||||
_78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X),
|
||||
_80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X),
|
||||
_88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X),
|
||||
_90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X),
|
||||
_98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X),
|
||||
_A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X),
|
||||
_A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X),
|
||||
_B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X),
|
||||
_B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X),
|
||||
_C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X),
|
||||
_C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X),
|
||||
_D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X),
|
||||
_D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X),
|
||||
_E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X),
|
||||
_E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X),
|
||||
_F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X),
|
||||
_F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X),
|
||||
|
||||
V3,
|
||||
V4,
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-12-19"
|
||||
channel = "nightly-2023-12-24"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||
|
@ -31,6 +31,7 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
|
||||
# FIXME add needs-unwind to these tests
|
||||
rm -r tests/run-make/libtest-junit
|
||||
rm tests/ui/asm/may_unwind.rs
|
||||
rm tests/ui/stable-mir-print/basic_function.rs
|
||||
|
||||
# extra warning about -Cpanic=abort for proc macros
|
||||
rm tests/ui/proc-macro/crt-static.rs
|
||||
@ -44,7 +45,6 @@ rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs
|
||||
# vendor intrinsics
|
||||
rm tests/ui/sse2.rs # CodegenBackend::target_features not yet implemented
|
||||
rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
|
||||
rm tests/ui/simd/masked-load-store.rs
|
||||
|
||||
# exotic linkages
|
||||
rm tests/ui/issues/issue-33992.rs # unsupported linkages
|
||||
@ -80,6 +80,7 @@ rm -r tests/run-make/codegen-options-parsing
|
||||
rm -r tests/run-make/lto-*
|
||||
rm -r tests/run-make/reproducible-build-2
|
||||
rm -r tests/run-make/issue-109934-lto-debuginfo
|
||||
rm -r tests/run-make/no-builtins-lto
|
||||
|
||||
# optimization tests
|
||||
# ==================
|
||||
|
@ -179,7 +179,7 @@ pub(crate) fn compile_fn(
|
||||
let early_dcx = rustc_session::EarlyDiagCtxt::new(
|
||||
rustc_session::config::ErrorOutputType::default(),
|
||||
);
|
||||
early_dcx.early_error(format!(
|
||||
early_dcx.early_fatal(format!(
|
||||
"backend implementation limit exceeded while compiling {name}",
|
||||
name = codegened_func.symbol_name
|
||||
));
|
||||
|
@ -962,6 +962,37 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
sym::simd_masked_store => {
|
||||
intrinsic_args!(fx, args => (mask, ptr, val); intrinsic);
|
||||
|
||||
let (val_lane_count, val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx);
|
||||
assert_eq!(val_lane_count, mask_lane_count);
|
||||
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
|
||||
let ptr_val = ptr.load_scalar(fx);
|
||||
|
||||
for lane_idx in 0..val_lane_count {
|
||||
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
|
||||
let if_enabled = fx.bcx.create_block();
|
||||
let next = fx.bcx.create_block();
|
||||
|
||||
fx.bcx.ins().brif(mask_lane, if_enabled, &[], next, &[]);
|
||||
fx.bcx.seal_block(if_enabled);
|
||||
|
||||
fx.bcx.switch_to_block(if_enabled);
|
||||
let offset = lane_idx as i32 * lane_clif_ty.bytes() as i32;
|
||||
fx.bcx.ins().store(MemFlags::trusted(), val_lane, ptr_val, Offset32::new(offset));
|
||||
fx.bcx.ins().jump(next, &[]);
|
||||
|
||||
fx.bcx.seal_block(next);
|
||||
fx.bcx.switch_to_block(next);
|
||||
|
||||
fx.bcx.ins().nop();
|
||||
}
|
||||
}
|
||||
|
||||
sym::simd_gather => {
|
||||
intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
|
||||
|
||||
@ -1057,7 +1088,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
}
|
||||
|
||||
sym::simd_scatter => {
|
||||
intrinsic_args!(fx, args => (mask, ptr, val); intrinsic);
|
||||
intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
|
||||
|
||||
let (val_lane_count, _val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![cfg_attr(all(doc, not(bootstrap)), allow(internal_features))]
|
||||
#![cfg_attr(all(doc, not(bootstrap)), feature(rustdoc_internals))]
|
||||
#![cfg_attr(all(doc, not(bootstrap)), doc(rust_logo))]
|
||||
#![cfg_attr(doc, allow(internal_features))]
|
||||
#![cfg_attr(doc, feature(rustdoc_internals))]
|
||||
#![cfg_attr(doc, doc(rust_logo))]
|
||||
#![feature(rustc_private)]
|
||||
// Note: please avoid adding other feature gates where possible
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_errors::{
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
||||
IntoDiagnosticArg,
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
IntoDiagnosticArg, Level,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::Span;
|
||||
@ -111,9 +111,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> {
|
||||
#[help(codegen_gcc_missing_features)]
|
||||
pub(crate) struct MissingFeatures;
|
||||
|
||||
impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let mut diag = dcx.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable);
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::codegen_gcc_target_feature_disable_or_enable
|
||||
);
|
||||
if let Some(span) = self.span {
|
||||
diag.set_span(span);
|
||||
};
|
||||
|
@ -4,9 +4,7 @@ use std::path::Path;
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_errors::{
|
||||
DiagCtxt, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, FatalError, IntoDiagnostic,
|
||||
};
|
||||
use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -101,13 +99,14 @@ pub(crate) struct DynamicLinkingWithLTO;
|
||||
|
||||
pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
|
||||
|
||||
impl IntoDiagnostic<'_, FatalError> for ParseTargetMachineConfig<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, FatalError> {
|
||||
let diag: DiagnosticBuilder<'_, FatalError> = self.0.into_diagnostic(dcx);
|
||||
let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message");
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level);
|
||||
let (message, _) = diag.messages().first().expect("`LlvmError` with no message");
|
||||
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
|
||||
|
||||
let mut diag = dcx.struct_almost_fatal(fluent::codegen_llvm_parse_target_machine_config);
|
||||
let mut diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config);
|
||||
diag.set_arg("error", message);
|
||||
diag
|
||||
}
|
||||
@ -123,9 +122,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> {
|
||||
#[help(codegen_llvm_missing_features)]
|
||||
pub(crate) struct MissingFeatures;
|
||||
|
||||
impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let mut diag = dcx.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable);
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::codegen_llvm_target_feature_disable_or_enable,
|
||||
);
|
||||
if let Some(span) = self.span {
|
||||
diag.set_span(span);
|
||||
};
|
||||
@ -184,7 +187,7 @@ pub enum LlvmError<'a> {
|
||||
pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String);
|
||||
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, G> {
|
||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
use LlvmError::*;
|
||||
let msg_with_llvm_err = match &self.0 {
|
||||
WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err,
|
||||
@ -201,7 +204,7 @@ 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);
|
||||
let mut diag = self.0.into_diagnostic(dcx, level);
|
||||
diag.set_primary_message(msg_with_llvm_err);
|
||||
diag.set_arg("llvm_err", self.1);
|
||||
diag
|
||||
|
@ -8,7 +8,6 @@
|
||||
#![feature(rustdoc_internals)]
|
||||
#![doc(rust_logo)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![cfg_attr(bootstrap, feature(c_str_literals))]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(hash_raw_entry)]
|
||||
|
@ -15,7 +15,7 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level};
|
||||
use rustc_errors::{DiagnosticMessage, Style};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style};
|
||||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_incremental::{
|
||||
@ -986,7 +986,7 @@ pub struct CguMessage;
|
||||
type DiagnosticArgName<'source> = Cow<'source, str>;
|
||||
|
||||
struct Diagnostic {
|
||||
msg: Vec<(DiagnosticMessage, Style)>,
|
||||
msgs: Vec<(DiagnosticMessage, Style)>,
|
||||
args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
|
||||
code: Option<DiagnosticId>,
|
||||
lvl: Level,
|
||||
@ -1799,14 +1799,14 @@ impl Emitter for SharedEmitter {
|
||||
let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> =
|
||||
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: diag.message.clone(),
|
||||
msgs: diag.messages.clone(),
|
||||
args: args.clone(),
|
||||
code: diag.code.clone(),
|
||||
lvl: diag.level(),
|
||||
})));
|
||||
for child in &diag.children {
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: child.message.clone(),
|
||||
msgs: child.messages.clone(),
|
||||
args: args.clone(),
|
||||
code: None,
|
||||
lvl: child.level,
|
||||
@ -1838,7 +1838,7 @@ impl SharedEmitterMain {
|
||||
match message {
|
||||
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
|
||||
let dcx = sess.dcx();
|
||||
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg);
|
||||
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs);
|
||||
if let Some(code) = diag.code {
|
||||
d.code(code);
|
||||
}
|
||||
@ -1846,14 +1846,14 @@ impl SharedEmitterMain {
|
||||
dcx.emit_diagnostic(d);
|
||||
}
|
||||
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
||||
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
|
||||
|
||||
let mut err = match level {
|
||||
Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),
|
||||
Level::Warning(_) => sess.struct_warn(msg),
|
||||
Level::Note => sess.struct_note(msg),
|
||||
let err_level = match level {
|
||||
Level::Error { lint: false } => rustc_errors::Level::Error { lint: false },
|
||||
Level::Warning(_) => rustc_errors::Level::Warning(None),
|
||||
Level::Note => rustc_errors::Level::Note,
|
||||
_ => bug!("Invalid inline asm diagnostic level"),
|
||||
};
|
||||
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
|
||||
let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), err_level, msg);
|
||||
|
||||
// If the cookie is 0 then we don't have span information.
|
||||
if cookie != 0 {
|
||||
|
@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
|
||||
use rustc_hir::{CoroutineKind, CoroutineSource, Mutability};
|
||||
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability};
|
||||
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
|
||||
use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
|
||||
@ -560,15 +560,31 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &
|
||||
|
||||
fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str {
|
||||
match coroutine_kind {
|
||||
Some(CoroutineKind::Gen(CoroutineSource::Block)) => "gen_block",
|
||||
Some(CoroutineKind::Gen(CoroutineSource::Closure)) => "gen_closure",
|
||||
Some(CoroutineKind::Gen(CoroutineSource::Fn)) => "gen_fn",
|
||||
Some(CoroutineKind::Async(CoroutineSource::Block)) => "async_block",
|
||||
Some(CoroutineKind::Async(CoroutineSource::Closure)) => "async_closure",
|
||||
Some(CoroutineKind::Async(CoroutineSource::Fn)) => "async_fn",
|
||||
Some(CoroutineKind::AsyncGen(CoroutineSource::Block)) => "async_gen_block",
|
||||
Some(CoroutineKind::AsyncGen(CoroutineSource::Closure)) => "async_gen_closure",
|
||||
Some(CoroutineKind::AsyncGen(CoroutineSource::Fn)) => "async_gen_fn",
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Block)) => {
|
||||
"gen_block"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Closure)) => {
|
||||
"gen_closure"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn)) => "gen_fn",
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) => {
|
||||
"async_block"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) => {
|
||||
"async_closure"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn)) => {
|
||||
"async_fn"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Block)) => {
|
||||
"async_gen_block"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Closure)) => {
|
||||
"async_gen_closure"
|
||||
}
|
||||
Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Fn)) => {
|
||||
"async_gen_fn"
|
||||
}
|
||||
Some(CoroutineKind::Coroutine) => "coroutine",
|
||||
None => "closure",
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ use crate::assert_module_sources::CguReuse;
|
||||
use crate::back::command::Command;
|
||||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
||||
IntoDiagnosticArg,
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
IntoDiagnosticArg, Level,
|
||||
};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
@ -209,192 +209,193 @@ pub enum LinkRlibError {
|
||||
|
||||
pub struct ThorinErrorWrapper(pub thorin::Error);
|
||||
|
||||
impl IntoDiagnostic<'_> for ThorinErrorWrapper {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
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 = dcx.struct_err(fluent::codegen_ssa_thorin_read_input_failure);
|
||||
diag = build(fluent::codegen_ssa_thorin_read_input_failure);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseFileKind(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseObjectFile(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_object_file);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseArchiveFile(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseArchiveMember(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_archive_member);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_archive_member);
|
||||
diag
|
||||
}
|
||||
thorin::Error::InvalidInputKind => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind);
|
||||
diag = build(fluent::codegen_ssa_thorin_invalid_input_kind);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DecompressData(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_decompress_data);
|
||||
diag = build(fluent::codegen_ssa_thorin_decompress_data);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NamelessSection(_, offset) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_without_name);
|
||||
diag = build(fluent::codegen_ssa_thorin_section_without_name);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
|
||||
diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleRelocations(section, offset) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_relocations);
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_relocations);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::UnsupportedRelocation(section, offset) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation);
|
||||
diag = build(fluent::codegen_ssa_thorin_unsupported_relocation);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name);
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_dwo_name);
|
||||
diag.set_arg("id", format!("0x{id:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoCompilationUnits => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_compilation_units);
|
||||
diag = build(fluent::codegen_ssa_thorin_no_compilation_units);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoDie => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_die);
|
||||
diag = build(fluent::codegen_ssa_thorin_no_die);
|
||||
diag
|
||||
}
|
||||
thorin::Error::TopLevelDieNotUnit => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit);
|
||||
diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingRequiredSection(section) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_required_section);
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_required_section);
|
||||
diag.set_arg("section", section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitAbbreviations(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitAttribute(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitHeader(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_header);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit_header);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnit(_) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version);
|
||||
diag = build(fluent::codegen_ssa_thorin_incompatible_index_version);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("actual", actual);
|
||||
diag.set_arg("format", format);
|
||||
diag
|
||||
}
|
||||
thorin::Error::OffsetAtIndex(_, index) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_offset_at_index);
|
||||
diag = build(fluent::codegen_ssa_thorin_offset_at_index);
|
||||
diag.set_arg("index", index);
|
||||
diag
|
||||
}
|
||||
thorin::Error::StrAtOffset(_, offset) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_str_at_offset);
|
||||
diag = build(fluent::codegen_ssa_thorin_str_at_offset);
|
||||
diag.set_arg("offset", format!("0x{offset:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseIndex(_, section) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_index);
|
||||
diag = build(fluent::codegen_ssa_thorin_parse_index);
|
||||
diag.set_arg("section", section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::UnitNotInIndex(unit) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index);
|
||||
diag = build(fluent::codegen_ssa_thorin_unit_not_in_index);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::RowNotInIndex(_, row) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_row_not_in_index);
|
||||
diag = build(fluent::codegen_ssa_thorin_row_not_in_index);
|
||||
diag.set_arg("row", row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::SectionNotInRow => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_not_in_row);
|
||||
diag = build(fluent::codegen_ssa_thorin_section_not_in_row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::EmptyUnit(unit) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_empty_unit);
|
||||
diag = build(fluent::codegen_ssa_thorin_empty_unit);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleDebugInfoSection => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section);
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleDebugTypesSection => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section);
|
||||
diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NotSplitUnit => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_split_unit);
|
||||
diag = build(fluent::codegen_ssa_thorin_not_split_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DuplicateUnit(unit) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_duplicate_unit);
|
||||
diag = build(fluent::codegen_ssa_thorin_duplicate_unit);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingReferencedUnit(unit) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit);
|
||||
diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit);
|
||||
diag.set_arg("unit", format!("0x{unit:08x}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoOutputObjectCreated => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_output_object_created);
|
||||
diag = build(fluent::codegen_ssa_thorin_not_output_object_created);
|
||||
diag
|
||||
}
|
||||
thorin::Error::MixedInputEncodings => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings);
|
||||
diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings);
|
||||
diag
|
||||
}
|
||||
thorin::Error::Io(e) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_io);
|
||||
diag = build(fluent::codegen_ssa_thorin_io);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ObjectRead(e) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_read);
|
||||
diag = build(fluent::codegen_ssa_thorin_object_read);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ObjectWrite(e) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_write);
|
||||
diag = build(fluent::codegen_ssa_thorin_object_write);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::GimliRead(e) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_read);
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_read);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::GimliWrite(e) => {
|
||||
diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_write);
|
||||
diag = build(fluent::codegen_ssa_thorin_gimli_write);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
@ -410,9 +411,9 @@ pub struct LinkingFailed<'a> {
|
||||
pub escaped_output: String,
|
||||
}
|
||||
|
||||
impl IntoDiagnostic<'_> for LinkingFailed<'_> {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let mut diag = dcx.struct_err(fluent::codegen_ssa_linking_failed);
|
||||
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for LinkingFailed<'_> {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_ssa_linking_failed);
|
||||
diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
|
||||
diag.set_arg("exit_status", format!("{}", self.exit_status));
|
||||
|
||||
|
@ -6,7 +6,7 @@ use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{layout::LayoutError, ConstInt};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol, DUMMY_SP};
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
|
||||
use super::{CompileTimeInterpreter, InterpCx};
|
||||
use crate::errors::{self, FrameNote, ReportErrorExt};
|
||||
@ -133,7 +133,7 @@ pub(super) fn report<'tcx, C, F, E>(
|
||||
where
|
||||
C: FnOnce() -> (Span, Vec<FrameNote>),
|
||||
F: FnOnce(Span, Vec<FrameNote>) -> E,
|
||||
E: IntoDiagnostic<'tcx, ErrorGuaranteed>,
|
||||
E: IntoDiagnostic<'tcx>,
|
||||
{
|
||||
// Special handling for certain errors
|
||||
match error {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_errors::{
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee,
|
||||
IntoDiagnostic,
|
||||
IntoDiagnostic, Level,
|
||||
};
|
||||
use rustc_hir::ConstContext;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
@ -875,7 +875,10 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
|
||||
| InvalidProgramInfo::AlreadyReported(_)
|
||||
| InvalidProgramInfo::ConstPropNonsense => {}
|
||||
InvalidProgramInfo::Layout(e) => {
|
||||
let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(dcx);
|
||||
// The level doesn't matter, `diag` is consumed without it being used.
|
||||
let dummy_level = Level::Bug;
|
||||
let diag: DiagnosticBuilder<'_, ()> =
|
||||
e.into_diagnostic().into_diagnostic(dcx, dummy_level);
|
||||
for (name, val) in diag.args() {
|
||||
builder.set_arg(name.clone(), val.clone());
|
||||
}
|
||||
|
@ -165,6 +165,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// We need to handle `extern static`.
|
||||
match self.tcx.try_get_global_alloc(alloc_id) {
|
||||
Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => {
|
||||
// Thread-local statics do not have a constant address. They *must* be accessed via
|
||||
// `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
|
||||
bug!("global memory cannot point to thread-local static")
|
||||
}
|
||||
Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => {
|
||||
@ -539,6 +541,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccessTest)),
|
||||
Some(GlobalAlloc::Static(def_id)) => {
|
||||
assert!(self.tcx.is_static(def_id));
|
||||
// Thread-local statics do not have a constant address. They *must* be accessed via
|
||||
// `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
|
||||
assert!(!self.tcx.is_thread_local_static(def_id));
|
||||
// Notice that every static has two `AllocId` that will resolve to the same
|
||||
// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
|
||||
@ -740,6 +744,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
match self.tcx.try_get_global_alloc(id) {
|
||||
Some(GlobalAlloc::Static(def_id)) => {
|
||||
assert!(self.tcx.is_static(def_id));
|
||||
// Thread-local statics do not have a constant address. They *must* be accessed via
|
||||
// `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
|
||||
assert!(!self.tcx.is_thread_local_static(def_id));
|
||||
// Use size and align of the type.
|
||||
let ty = self
|
||||
|
@ -5,17 +5,15 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::traits::BuiltinImplSource;
|
||||
use rustc_middle::ty::GenericArgs;
|
||||
use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{TraitRef, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt};
|
||||
use rustc_mir_dataflow::Analysis;
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
|
||||
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
|
||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
|
||||
|
||||
use std::mem;
|
||||
@ -464,8 +462,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
|
||||
Rvalue::Aggregate(kind, ..) => {
|
||||
if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()
|
||||
&& let Some(coroutine_kind @ hir::CoroutineKind::Async(..)) =
|
||||
self.tcx.coroutine_kind(def_id)
|
||||
&& let Some(
|
||||
coroutine_kind @ hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
_,
|
||||
),
|
||||
) = self.tcx.coroutine_kind(def_id)
|
||||
{
|
||||
self.check_op(ops::Coroutine(coroutine_kind));
|
||||
}
|
||||
@ -752,143 +754,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
}
|
||||
|
||||
let mut is_trait = false;
|
||||
// Attempting to call a trait method?
|
||||
// FIXME(effects) do we need this?
|
||||
if let Some(trait_id) = tcx.trait_of_item(callee) {
|
||||
if tcx.trait_of_item(callee).is_some() {
|
||||
trace!("attempting to call a trait method");
|
||||
if !self.tcx.features().const_trait_impl {
|
||||
// trait method calls are only permitted when `effects` is enabled.
|
||||
// we don't error, since that is handled by typeck. We try to resolve
|
||||
// the trait into the concrete method, and uses that for const stability
|
||||
// checks.
|
||||
// FIXME(effects) we might consider moving const stability checks to typeck as well.
|
||||
if tcx.features().effects {
|
||||
is_trait = true;
|
||||
|
||||
if let Ok(Some(instance)) =
|
||||
Instance::resolve(tcx, param_env, callee, fn_args)
|
||||
&& let InstanceDef::Item(def) = instance.def
|
||||
{
|
||||
// Resolve a trait method call to its concrete implementation, which may be in a
|
||||
// `const` trait impl. This is only used for the const stability check below, since
|
||||
// we want to look at the concrete impl's stability.
|
||||
fn_args = instance.args;
|
||||
callee = def;
|
||||
}
|
||||
} else {
|
||||
self.check_op(ops::FnCallNonConst {
|
||||
caller,
|
||||
callee,
|
||||
args: fn_args,
|
||||
span: *fn_span,
|
||||
call_source: *call_source,
|
||||
feature: Some(sym::const_trait_impl),
|
||||
feature: Some(if tcx.features().const_trait_impl {
|
||||
sym::effects
|
||||
} else {
|
||||
sym::const_trait_impl
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args);
|
||||
let obligation =
|
||||
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
|
||||
|
||||
let implsrc = {
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
selcx.select(&obligation)
|
||||
};
|
||||
|
||||
match implsrc {
|
||||
Ok(Some(ImplSource::Param(_))) if tcx.features().effects => {
|
||||
debug!(
|
||||
"const_trait_impl: provided {:?} via where-clause in {:?}",
|
||||
trait_ref, param_env
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Closure: Fn{Once|Mut}
|
||||
Ok(Some(ImplSource::Builtin(BuiltinImplSource::Misc, _)))
|
||||
if trait_ref.self_ty().is_closure()
|
||||
&& tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
|
||||
{
|
||||
let ty::Closure(closure_def_id, fn_args) = *trait_ref.self_ty().kind()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
if !tcx.is_const_fn_raw(closure_def_id) {
|
||||
self.check_op(ops::FnCallNonConst {
|
||||
caller,
|
||||
callee,
|
||||
args: fn_args,
|
||||
span: *fn_span,
|
||||
call_source: *call_source,
|
||||
feature: None,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Ok(Some(ImplSource::UserDefined(data))) => {
|
||||
let callee_name = tcx.item_name(callee);
|
||||
|
||||
if let hir::Constness::NotConst = tcx.constness(data.impl_def_id) {
|
||||
self.check_op(ops::FnCallNonConst {
|
||||
caller,
|
||||
callee,
|
||||
args: fn_args,
|
||||
span: *fn_span,
|
||||
call_source: *call_source,
|
||||
feature: None,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(&did) = tcx
|
||||
.associated_item_def_ids(data.impl_def_id)
|
||||
.iter()
|
||||
.find(|did| tcx.item_name(**did) == callee_name)
|
||||
{
|
||||
// using internal args is ok here, since this is only
|
||||
// used for the `resolve` call below
|
||||
fn_args = GenericArgs::identity_for_item(tcx, did);
|
||||
callee = did;
|
||||
}
|
||||
}
|
||||
_ if !tcx.is_const_fn_raw(callee) => {
|
||||
// At this point, it is only legal when the caller is in a trait
|
||||
// marked with #[const_trait], and the callee is in the same trait.
|
||||
let mut nonconst_call_permission = false;
|
||||
if let Some(callee_trait) = tcx.trait_of_item(callee)
|
||||
&& tcx.has_attr(callee_trait, sym::const_trait)
|
||||
&& Some(callee_trait) == tcx.trait_of_item(caller.to_def_id())
|
||||
// Can only call methods when it's `<Self as TheTrait>::f`.
|
||||
&& tcx.types.self_param == fn_args.type_at(0)
|
||||
{
|
||||
nonconst_call_permission = true;
|
||||
}
|
||||
|
||||
if !nonconst_call_permission {
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
ObligationCause::dummy_with_span(*fn_span),
|
||||
param_env,
|
||||
trait_ref,
|
||||
);
|
||||
|
||||
// improve diagnostics by showing what failed. Our requirements are stricter this time
|
||||
// as we are going to error again anyways.
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
if let Err(e) = implsrc {
|
||||
infcx.err_ctxt().report_selection_error(
|
||||
obligation.clone(),
|
||||
&obligation,
|
||||
&e,
|
||||
);
|
||||
}
|
||||
|
||||
self.check_op(ops::FnCallNonConst {
|
||||
caller,
|
||||
callee,
|
||||
args: fn_args,
|
||||
span: *fn_span,
|
||||
call_source: *call_source,
|
||||
feature: None,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Resolve a trait method call to its concrete implementation, which may be in a
|
||||
// `const` trait impl.
|
||||
let instance = Instance::resolve(tcx, param_env, callee, fn_args);
|
||||
debug!("Resolving ({:?}) -> {:?}", callee, instance);
|
||||
if let Ok(Some(func)) = instance {
|
||||
if let InstanceDef::Item(def) = func.def {
|
||||
callee = def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we are calling a function, `callee`, whose `DefId` is known...
|
||||
@ -921,21 +823,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
if !tcx.is_const_fn_raw(callee) {
|
||||
if !tcx.is_const_default_method(callee) {
|
||||
// To get to here we must have already found a const impl for the
|
||||
// trait, but for it to still be non-const can be that the impl is
|
||||
// using default method bodies.
|
||||
self.check_op(ops::FnCallNonConst {
|
||||
caller,
|
||||
callee,
|
||||
args: fn_args,
|
||||
span: *fn_span,
|
||||
call_source: *call_source,
|
||||
feature: None,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if !tcx.is_const_fn_raw(callee) && !is_trait {
|
||||
self.check_op(ops::FnCallNonConst {
|
||||
caller,
|
||||
callee,
|
||||
args: fn_args,
|
||||
span: *fn_span,
|
||||
call_source: *call_source,
|
||||
feature: None,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If the `const fn` we are trying to call is not const-stable, ensure that we have
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use hir::def_id::LocalDefId;
|
||||
use hir::{ConstContext, LangItem};
|
||||
use rustc_errors::{error_code, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{error_code, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
@ -48,11 +48,7 @@ pub trait NonConstOp<'tcx>: std::fmt::Debug {
|
||||
DiagnosticImportance::Primary
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -66,11 +62,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
sym::const_fn_floating_point_arithmetic,
|
||||
@ -84,11 +76,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
|
||||
#[derive(Debug)]
|
||||
pub struct FnCallIndirect;
|
||||
impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
|
||||
}
|
||||
}
|
||||
@ -105,11 +93,7 @@ pub struct FnCallNonConst<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
_: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> DiagnosticBuilder<'tcx> {
|
||||
let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self;
|
||||
let ConstCx { tcx, param_env, .. } = *ccx;
|
||||
|
||||
@ -331,11 +315,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
|
||||
|
||||
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
let FnCallUnstable(def_id, feature) = *self;
|
||||
|
||||
let mut err = ccx
|
||||
@ -359,20 +339,24 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
|
||||
pub struct Coroutine(pub hir::CoroutineKind);
|
||||
impl<'tcx> NonConstOp<'tcx> for Coroutine {
|
||||
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
|
||||
if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 {
|
||||
if let hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Block,
|
||||
) = self.0
|
||||
{
|
||||
Status::Unstable(sym::const_async_blocks)
|
||||
} else {
|
||||
Status::Forbidden
|
||||
}
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
|
||||
if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 {
|
||||
if let hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Block,
|
||||
) = self.0
|
||||
{
|
||||
ccx.tcx.sess.create_feature_err(
|
||||
errors::UnallowedOpInConstContext { span, msg },
|
||||
sym::const_async_blocks,
|
||||
@ -386,11 +370,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
|
||||
#[derive(Debug)]
|
||||
pub struct HeapAllocation;
|
||||
impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations {
|
||||
span,
|
||||
kind: ccx.const_kind(),
|
||||
@ -402,11 +382,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
|
||||
#[derive(Debug)]
|
||||
pub struct InlineAsm;
|
||||
impl<'tcx> NonConstOp<'tcx> for InlineAsm {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() })
|
||||
}
|
||||
}
|
||||
@ -417,11 +393,7 @@ pub struct LiveDrop<'tcx> {
|
||||
pub dropped_ty: Ty<'tcx>,
|
||||
}
|
||||
impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::LiveDrop {
|
||||
span,
|
||||
dropped_ty: self.dropped_ty,
|
||||
@ -444,11 +416,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
|
||||
// not additionally emit a feature gate error if activating the feature gate won't work.
|
||||
DiagnosticImportance::Secondary
|
||||
}
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx
|
||||
.sess
|
||||
.create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
|
||||
@ -461,11 +429,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
|
||||
/// it in the future for static items.
|
||||
pub struct CellBorrow;
|
||||
impl<'tcx> NonConstOp<'tcx> for CellBorrow {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
// FIXME: Maybe a more elegant solution to this if else case
|
||||
if let hir::ConstContext::Static(_) = ccx.const_kind() {
|
||||
ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
|
||||
@ -502,11 +466,7 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
|
||||
DiagnosticImportance::Secondary
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
match self.0 {
|
||||
hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw {
|
||||
span,
|
||||
@ -530,11 +490,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow {
|
||||
Status::Unstable(sym::const_mut_refs)
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
let kind = ccx.const_kind();
|
||||
match self.0 {
|
||||
hir::BorrowKind::Raw => ccx.tcx.sess.create_feature_err(
|
||||
@ -561,11 +517,7 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref {
|
||||
DiagnosticImportance::Secondary
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_feature_err(
|
||||
errors::MutDerefErr { span, kind: ccx.const_kind() },
|
||||
sym::const_mut_refs,
|
||||
@ -577,11 +529,7 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref {
|
||||
#[derive(Debug)]
|
||||
pub struct PanicNonStr;
|
||||
impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::PanicNonStrErr { span })
|
||||
}
|
||||
}
|
||||
@ -592,11 +540,7 @@ impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
|
||||
#[derive(Debug)]
|
||||
pub struct RawPtrComparison;
|
||||
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
// FIXME(const_trait_impl): revert to span_bug?
|
||||
ccx.tcx.sess.create_err(errors::RawPtrComparisonErr { span })
|
||||
}
|
||||
@ -609,11 +553,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
|
||||
Status::Unstable(sym::const_mut_refs)
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
sym::const_mut_refs,
|
||||
@ -629,11 +569,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
|
||||
#[derive(Debug)]
|
||||
pub struct RawPtrToIntCast;
|
||||
impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span })
|
||||
}
|
||||
}
|
||||
@ -650,11 +586,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::StaticAccessErr {
|
||||
span,
|
||||
kind: ccx.const_kind(),
|
||||
@ -667,11 +599,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
|
||||
#[derive(Debug)]
|
||||
pub struct ThreadLocalAccess;
|
||||
impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
ccx.tcx.sess.create_err(errors::NonConstOpErr { span })
|
||||
}
|
||||
}
|
||||
@ -696,11 +624,7 @@ pub mod ty {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_error(
|
||||
&self,
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||
feature_err(
|
||||
&ccx.tcx.sess.parse_sess,
|
||||
sym::const_mut_refs,
|
||||
|
@ -8,9 +8,6 @@ use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance};
|
||||
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
||||
use rustc_mir_dataflow::storage::always_storage_live_locals;
|
||||
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
||||
use rustc_target::abi::{Size, FIRST_VARIANT};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
@ -51,12 +48,6 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
||||
Reveal::All => tcx.param_env_reveal_all_normalized(def_id),
|
||||
};
|
||||
|
||||
let always_live_locals = always_storage_live_locals(body);
|
||||
let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals))
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(body);
|
||||
|
||||
let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
|
||||
// In this case `AbortUnwindingCalls` haven't yet been executed.
|
||||
true
|
||||
@ -83,7 +74,6 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
||||
mir_phase,
|
||||
unwind_edge_count: 0,
|
||||
reachable_blocks: traversal::reachable_as_bitset(body),
|
||||
storage_liveness,
|
||||
place_cache: FxHashSet::default(),
|
||||
value_cache: FxHashSet::default(),
|
||||
can_unwind,
|
||||
@ -116,7 +106,6 @@ struct CfgChecker<'a, 'tcx> {
|
||||
mir_phase: MirPhase,
|
||||
unwind_edge_count: usize,
|
||||
reachable_blocks: BitSet<BasicBlock>,
|
||||
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
|
||||
place_cache: FxHashSet<PlaceRef<'tcx>>,
|
||||
value_cache: FxHashSet<u128>,
|
||||
// If `false`, then the MIR must not contain `UnwindAction::Continue` or
|
||||
@ -294,28 +283,13 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
||||
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
|
||||
fn visit_local(&mut self, local: Local, _context: PlaceContext, location: Location) {
|
||||
if self.body.local_decls.get(local).is_none() {
|
||||
self.fail(
|
||||
location,
|
||||
format!("local {local:?} has no corresponding declaration in `body.local_decls`"),
|
||||
);
|
||||
}
|
||||
|
||||
if self.reachable_blocks.contains(location.block) && context.is_use() {
|
||||
// We check that the local is live whenever it is used. Technically, violating this
|
||||
// restriction is only UB and not actually indicative of not well-formed MIR. This means
|
||||
// that an optimization which turns MIR that already has UB into MIR that fails this
|
||||
// check is not necessarily wrong. However, we have no such optimizations at the moment,
|
||||
// and so we include this check anyway to help us catch bugs. If you happen to write an
|
||||
// optimization that might cause this to incorrectly fire, feel free to remove this
|
||||
// check.
|
||||
self.storage_liveness.seek_after_primary_effect(location);
|
||||
let locals_with_storage = self.storage_liveness.get();
|
||||
if !locals_with_storage.contains(local) {
|
||||
self.fail(location, format!("use of local {local:?}, which has no storage here"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
@ -367,26 +341,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
||||
self.fail(location, format!("explicit `{kind:?}` is forbidden"));
|
||||
}
|
||||
}
|
||||
StatementKind::StorageLive(local) => {
|
||||
// We check that the local is not live when entering a `StorageLive` for it.
|
||||
// Technically, violating this restriction is only UB and not actually indicative
|
||||
// of not well-formed MIR. This means that an optimization which turns MIR that
|
||||
// already has UB into MIR that fails this check is not necessarily wrong. However,
|
||||
// we have no such optimizations at the moment, and so we include this check anyway
|
||||
// to help us catch bugs. If you happen to write an optimization that might cause
|
||||
// this to incorrectly fire, feel free to remove this check.
|
||||
if self.reachable_blocks.contains(location.block) {
|
||||
self.storage_liveness.seek_before_primary_effect(location);
|
||||
let locals_with_storage = self.storage_liveness.get();
|
||||
if locals_with_storage.contains(*local) {
|
||||
self.fail(
|
||||
location,
|
||||
format!("StorageLive({local:?}) which already has storage here"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
StatementKind::StorageDead(_)
|
||||
StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Intrinsic(_)
|
||||
| StatementKind::Coverage(_)
|
||||
| StatementKind::ConstEvalCounter
|
||||
|
@ -81,150 +81,6 @@
|
||||
/// E::A,
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(bootstrap)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_tag {
|
||||
(
|
||||
impl Tag for $Self:ty;
|
||||
$(
|
||||
$($path:ident)::* $( { $( $fields:tt )* })?,
|
||||
)*
|
||||
) => {
|
||||
// Safety:
|
||||
// `bits_for_tags` is called on the same `${index()}`-es as
|
||||
// `into_usize` returns, thus `BITS` constant is correct.
|
||||
unsafe impl $crate::tagged_ptr::Tag for $Self {
|
||||
const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[
|
||||
$(
|
||||
${index()},
|
||||
$( ${ignore(path)} )*
|
||||
)*
|
||||
]);
|
||||
|
||||
#[inline]
|
||||
fn into_usize(self) -> usize {
|
||||
// This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc)
|
||||
// (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>)
|
||||
#[forbid(unreachable_patterns)]
|
||||
match self {
|
||||
// `match` is doing heavy lifting here, by requiring exhaustiveness
|
||||
$(
|
||||
$($path)::* $( { $( $fields )* } )? => ${index()},
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_usize(tag: usize) -> Self {
|
||||
match tag {
|
||||
$(
|
||||
${index()} => $($path)::* $( { $( $fields )* } )?,
|
||||
)*
|
||||
|
||||
// Safety:
|
||||
// `into_usize` only returns `${index()}` of the same
|
||||
// repetition as we are filtering above, thus if this is
|
||||
// reached, the safety contract of this function was
|
||||
// already breached.
|
||||
_ => unsafe {
|
||||
debug_assert!(
|
||||
false,
|
||||
"invalid tag: {tag}\
|
||||
(this is a bug in the caller of `from_usize`)"
|
||||
);
|
||||
std::hint::unreachable_unchecked()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Implements [`Tag`] for a given type.
|
||||
///
|
||||
/// You can use `impl_tag` on structs and enums.
|
||||
/// You need to specify the type and all its possible values,
|
||||
/// which can only be paths with optional fields.
|
||||
///
|
||||
/// [`Tag`]: crate::tagged_ptr::Tag
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(macro_metavar_expr)]
|
||||
/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag};
|
||||
///
|
||||
/// #[derive(Copy, Clone, PartialEq, Debug)]
|
||||
/// enum SomeTag {
|
||||
/// A,
|
||||
/// B,
|
||||
/// X { v: bool },
|
||||
/// Y(bool, bool),
|
||||
/// }
|
||||
///
|
||||
/// impl_tag! {
|
||||
/// // The type for which the `Tag` will be implemented
|
||||
/// impl Tag for SomeTag;
|
||||
/// // You need to specify all possible tag values:
|
||||
/// SomeTag::A, // 0
|
||||
/// SomeTag::B, // 1
|
||||
/// // For variants with fields, you need to specify the fields:
|
||||
/// SomeTag::X { v: true }, // 2
|
||||
/// SomeTag::X { v: false }, // 3
|
||||
/// // For tuple variants use named syntax:
|
||||
/// SomeTag::Y { 0: true, 1: true }, // 4
|
||||
/// SomeTag::Y { 0: false, 1: true }, // 5
|
||||
/// SomeTag::Y { 0: true, 1: false }, // 6
|
||||
/// SomeTag::Y { 0: false, 1: false }, // 7
|
||||
/// }
|
||||
///
|
||||
/// // Tag values are assigned in order:
|
||||
/// assert_eq!(SomeTag::A.into_usize(), 0);
|
||||
/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3);
|
||||
/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5);
|
||||
///
|
||||
/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B);
|
||||
/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true });
|
||||
/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false));
|
||||
/// ```
|
||||
///
|
||||
/// Structs are supported:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(macro_metavar_expr)]
|
||||
/// # use rustc_data_structures::impl_tag;
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct Flags { a: bool, b: bool }
|
||||
///
|
||||
/// impl_tag! {
|
||||
/// impl Tag for Flags;
|
||||
/// Flags { a: true, b: true },
|
||||
/// Flags { a: false, b: true },
|
||||
/// Flags { a: true, b: false },
|
||||
/// Flags { a: false, b: false },
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Not specifying all values results in a compile error:
|
||||
///
|
||||
/// ```compile_fail,E0004
|
||||
/// #![feature(macro_metavar_expr)]
|
||||
/// # use rustc_data_structures::impl_tag;
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// enum E {
|
||||
/// A,
|
||||
/// B,
|
||||
/// }
|
||||
///
|
||||
/// impl_tag! {
|
||||
/// impl Tag for E;
|
||||
/// E::A,
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(not(bootstrap))]
|
||||
#[macro_export]
|
||||
macro_rules! impl_tag {
|
||||
(
|
||||
|
@ -28,7 +28,7 @@ pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<Stri
|
||||
for arg in at_args {
|
||||
match arg_expand(arg.clone()) {
|
||||
Ok(arg) => args.extend(arg),
|
||||
Err(err) => early_dcx.early_error(format!("Failed to load argument file: {err}")),
|
||||
Err(err) => early_dcx.early_fatal(format!("Failed to load argument file: {err}")),
|
||||
}
|
||||
}
|
||||
args
|
||||
|
@ -345,7 +345,7 @@ fn run_compiler(
|
||||
Ok(None) => match matches.free.len() {
|
||||
0 => false, // no input: we will exit early
|
||||
1 => panic!("make_input should have provided valid inputs"),
|
||||
_ => default_early_dcx.early_error(format!(
|
||||
_ => default_early_dcx.early_fatal(format!(
|
||||
"multiple input filenames provided (first two filenames are `{}` and `{}`)",
|
||||
matches.free[0], matches.free[1],
|
||||
)),
|
||||
@ -376,7 +376,7 @@ fn run_compiler(
|
||||
}
|
||||
|
||||
if !has_input {
|
||||
early_dcx.early_error("no input filename given"); // this is fatal
|
||||
early_dcx.early_fatal("no input filename given"); // this is fatal
|
||||
}
|
||||
|
||||
if !sess.opts.unstable_opts.ls.is_empty() {
|
||||
@ -505,9 +505,8 @@ fn make_input(
|
||||
if io::stdin().read_to_string(&mut src).is_err() {
|
||||
// Immediately stop compilation if there was an issue reading
|
||||
// the input (for example if the input stream is not UTF-8).
|
||||
let reported = early_dcx.early_error_no_abort(
|
||||
"couldn't read from stdin, as it did not contain valid UTF-8",
|
||||
);
|
||||
let reported = early_dcx
|
||||
.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
|
||||
return Err(reported);
|
||||
}
|
||||
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
|
||||
@ -567,7 +566,7 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col
|
||||
}
|
||||
}
|
||||
Err(InvalidErrorCode) => {
|
||||
early_dcx.early_error(format!("{code} is not a valid error code"));
|
||||
early_dcx.early_fatal(format!("{code} is not a valid error code"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -685,7 +684,7 @@ fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dy
|
||||
safe_println!("{}", String::from_utf8(v).unwrap());
|
||||
}
|
||||
Input::Str { .. } => {
|
||||
early_dcx.early_error("cannot list metadata for stdin");
|
||||
early_dcx.early_fatal("cannot list metadata for stdin");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -839,7 +838,7 @@ fn print_crate_info(
|
||||
println_info!("deployment_target={}", format!("{major}.{minor}"))
|
||||
} else {
|
||||
early_dcx
|
||||
.early_error("only Apple targets currently support deployment version info")
|
||||
.early_fatal("only Apple targets currently support deployment version info")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1182,7 +1181,7 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
|
||||
.map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
|
||||
_ => None,
|
||||
};
|
||||
early_dcx.early_error(msg.unwrap_or_else(|| e.to_string()));
|
||||
early_dcx.early_fatal(msg.unwrap_or_else(|| e.to_string()));
|
||||
});
|
||||
|
||||
// For all options we just parsed, we check a few aspects:
|
||||
@ -1333,7 +1332,7 @@ pub fn install_ice_hook(
|
||||
{
|
||||
// the error code is already going to be reported when the panic unwinds up the stack
|
||||
let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
|
||||
let _ = early_dcx.early_error_no_abort(msg.clone());
|
||||
let _ = early_dcx.early_err(msg.clone());
|
||||
return;
|
||||
}
|
||||
};
|
||||
@ -1481,7 +1480,7 @@ pub fn init_rustc_env_logger(early_dcx: &EarlyDiagCtxt) {
|
||||
/// the values directly rather than having to set an environment variable.
|
||||
pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
|
||||
if let Err(error) = rustc_log::init_logger(cfg) {
|
||||
early_dcx.early_error(error.to_string());
|
||||
early_dcx.early_fatal(error.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1500,7 +1499,7 @@ pub fn main() -> ! {
|
||||
.enumerate()
|
||||
.map(|(i, arg)| {
|
||||
arg.into_string().unwrap_or_else(|arg| {
|
||||
early_dcx.early_error(format!("argument {i} is not valid Unicode: {arg:?}"))
|
||||
early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}"))
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -1 +1,2 @@
|
||||
#### This error code is internal to the compiler and will not be emitted with normal Rust code.
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
@ -60,7 +60,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
||||
|
||||
self.emit_messages_default(
|
||||
&diag.level,
|
||||
&diag.message,
|
||||
&diag.messages,
|
||||
&fluent_args,
|
||||
&diag.code,
|
||||
&primary_span,
|
||||
|
@ -103,7 +103,7 @@ pub struct Diagnostic {
|
||||
// outside of what methods in this crate themselves allow.
|
||||
pub(crate) level: Level,
|
||||
|
||||
pub message: Vec<(DiagnosticMessage, Style)>,
|
||||
pub messages: Vec<(DiagnosticMessage, Style)>,
|
||||
pub code: Option<DiagnosticId>,
|
||||
pub span: MultiSpan,
|
||||
pub children: Vec<SubDiagnostic>,
|
||||
@ -161,9 +161,8 @@ pub enum DiagnosticId {
|
||||
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
|
||||
pub struct SubDiagnostic {
|
||||
pub level: Level,
|
||||
pub message: Vec<(DiagnosticMessage, Style)>,
|
||||
pub messages: Vec<(DiagnosticMessage, Style)>,
|
||||
pub span: MultiSpan,
|
||||
pub render_span: Option<MultiSpan>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@ -216,14 +215,14 @@ impl StringPart {
|
||||
impl Diagnostic {
|
||||
#[track_caller]
|
||||
pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self {
|
||||
Diagnostic::new_with_code(level, None, message)
|
||||
Diagnostic::new_with_messages(level, vec![(message.into(), Style::NoStyle)])
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self {
|
||||
Diagnostic {
|
||||
level,
|
||||
message: messages,
|
||||
messages,
|
||||
code: None,
|
||||
span: MultiSpan::new(),
|
||||
children: vec![],
|
||||
@ -235,26 +234,6 @@ impl Diagnostic {
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn new_with_code<M: Into<DiagnosticMessage>>(
|
||||
level: Level,
|
||||
code: Option<DiagnosticId>,
|
||||
message: M,
|
||||
) -> Self {
|
||||
Diagnostic {
|
||||
level,
|
||||
message: vec![(message.into(), Style::NoStyle)],
|
||||
code,
|
||||
span: MultiSpan::new(),
|
||||
children: vec![],
|
||||
suggestions: Ok(vec![]),
|
||||
args: Default::default(),
|
||||
sort_span: DUMMY_SP,
|
||||
is_lint: false,
|
||||
emitted_at: DiagnosticLocation::caller(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn level(&self) -> Level {
|
||||
self.level
|
||||
@ -445,7 +424,7 @@ impl Diagnostic {
|
||||
/// Add a note attached to this diagnostic.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
|
||||
self.sub(Level::Note, msg, MultiSpan::new(), None);
|
||||
self.sub(Level::Note, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
@ -453,14 +432,14 @@ impl Diagnostic {
|
||||
&mut self,
|
||||
msg: Vec<(M, Style)>,
|
||||
) -> &mut Self {
|
||||
self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None);
|
||||
self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints the span with a note above it.
|
||||
/// This is like [`Diagnostic::note()`], but it gets its own span.
|
||||
pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
|
||||
self.sub(Level::OnceNote, msg, MultiSpan::new(), None);
|
||||
self.sub(Level::OnceNote, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
@ -472,7 +451,7 @@ impl Diagnostic {
|
||||
sp: S,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self {
|
||||
self.sub(Level::Note, msg, sp.into(), None);
|
||||
self.sub(Level::Note, msg, sp.into());
|
||||
self
|
||||
}
|
||||
|
||||
@ -483,14 +462,14 @@ impl Diagnostic {
|
||||
sp: S,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self {
|
||||
self.sub(Level::OnceNote, msg, sp.into(), None);
|
||||
self.sub(Level::OnceNote, msg, sp.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a warning attached to this diagnostic.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
|
||||
self.sub(Level::Warning(None), msg, MultiSpan::new(), None);
|
||||
self.sub(Level::Warning(None), msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
@ -502,27 +481,27 @@ impl Diagnostic {
|
||||
sp: S,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self {
|
||||
self.sub(Level::Warning(None), msg, sp.into(), None);
|
||||
self.sub(Level::Warning(None), msg, sp.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a help message attached to this diagnostic.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
|
||||
self.sub(Level::Help, msg, MultiSpan::new(), None);
|
||||
self.sub(Level::Help, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints the span with a help above it.
|
||||
/// This is like [`Diagnostic::help()`], but it gets its own span.
|
||||
pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
|
||||
self.sub(Level::OnceHelp, msg, MultiSpan::new(), None);
|
||||
self.sub(Level::OnceHelp, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a help message attached to this diagnostic with a customizable highlighted message.
|
||||
pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self {
|
||||
self.sub_with_highlights(Level::Help, msg, MultiSpan::new(), None);
|
||||
self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
@ -534,7 +513,7 @@ impl Diagnostic {
|
||||
sp: S,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
) -> &mut Self {
|
||||
self.sub(Level::Help, msg, sp.into(), None);
|
||||
self.sub(Level::Help, msg, sp.into());
|
||||
self
|
||||
}
|
||||
|
||||
@ -925,7 +904,7 @@ impl Diagnostic {
|
||||
}
|
||||
|
||||
pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
|
||||
self.message[0] = (msg.into(), Style::NoStyle);
|
||||
self.messages[0] = (msg.into(), Style::NoStyle);
|
||||
self
|
||||
}
|
||||
|
||||
@ -952,8 +931,8 @@ impl Diagnostic {
|
||||
self.args = args;
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] {
|
||||
&self.message
|
||||
pub fn messages(&self) -> &[(DiagnosticMessage, Style)] {
|
||||
&self.messages
|
||||
}
|
||||
|
||||
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
|
||||
@ -964,7 +943,7 @@ impl Diagnostic {
|
||||
attr: impl Into<SubdiagnosticMessage>,
|
||||
) -> DiagnosticMessage {
|
||||
let msg =
|
||||
self.message.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages");
|
||||
self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages");
|
||||
msg.with_subdiagnostic_message(attr.into())
|
||||
}
|
||||
|
||||
@ -972,21 +951,14 @@ impl Diagnostic {
|
||||
/// public methods above.
|
||||
///
|
||||
/// Used by `proc_macro_server` for implementing `server::Diagnostic`.
|
||||
pub fn sub(
|
||||
&mut self,
|
||||
level: Level,
|
||||
message: impl Into<SubdiagnosticMessage>,
|
||||
span: MultiSpan,
|
||||
render_span: Option<MultiSpan>,
|
||||
) {
|
||||
pub fn sub(&mut self, level: Level, message: impl Into<SubdiagnosticMessage>, span: MultiSpan) {
|
||||
let sub = SubDiagnostic {
|
||||
level,
|
||||
message: vec![(
|
||||
messages: vec![(
|
||||
self.subdiagnostic_message_to_diagnostic_message(message),
|
||||
Style::NoStyle,
|
||||
)],
|
||||
span,
|
||||
render_span,
|
||||
};
|
||||
self.children.push(sub);
|
||||
}
|
||||
@ -996,15 +968,14 @@ impl Diagnostic {
|
||||
fn sub_with_highlights<M: Into<SubdiagnosticMessage>>(
|
||||
&mut self,
|
||||
level: Level,
|
||||
message: Vec<(M, Style)>,
|
||||
messages: Vec<(M, Style)>,
|
||||
span: MultiSpan,
|
||||
render_span: Option<MultiSpan>,
|
||||
) {
|
||||
let message = message
|
||||
let messages = messages
|
||||
.into_iter()
|
||||
.map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1))
|
||||
.collect();
|
||||
let sub = SubDiagnostic { level, message, span, render_span };
|
||||
let sub = SubDiagnostic { level, messages, span };
|
||||
self.children.push(sub);
|
||||
}
|
||||
|
||||
@ -1022,7 +993,7 @@ impl Diagnostic {
|
||||
) {
|
||||
(
|
||||
&self.level,
|
||||
&self.message,
|
||||
&self.messages,
|
||||
self.args().collect(),
|
||||
&self.code,
|
||||
&self.span,
|
||||
|
@ -15,13 +15,13 @@ use std::ops::{Deref, DerefMut};
|
||||
use std::panic;
|
||||
use std::thread::panicking;
|
||||
|
||||
/// Trait implemented by error types. This should not be implemented manually. Instead, use
|
||||
/// Trait implemented by error types. This is rarely implemented manually. Instead, use
|
||||
/// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic].
|
||||
#[rustc_diagnostic_item = "IntoDiagnostic"]
|
||||
pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
|
||||
/// Write out as a diagnostic out of `DiagCtxt`.
|
||||
#[must_use]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G>;
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G>;
|
||||
}
|
||||
|
||||
impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned<T>
|
||||
@ -29,8 +29,8 @@ where
|
||||
T: IntoDiagnostic<'a, G>,
|
||||
G: EmissionGuarantee,
|
||||
{
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = self.node.into_diagnostic(dcx);
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut diag = self.node.into_diagnostic(dcx, level);
|
||||
diag.set_span(self.span);
|
||||
diag
|
||||
}
|
||||
@ -43,24 +43,7 @@ where
|
||||
/// extending `DiagCtxtFlags`.
|
||||
#[must_use]
|
||||
#[derive(Clone)]
|
||||
pub struct DiagnosticBuilder<'a, G: EmissionGuarantee> {
|
||||
inner: DiagnosticBuilderInner<'a>,
|
||||
_marker: PhantomData<G>,
|
||||
}
|
||||
|
||||
/// This type exists only for `DiagnosticBuilder::forget_guarantee`, because it:
|
||||
/// 1. lacks the `G` parameter and therefore `DiagnosticBuilder<G1>` can be
|
||||
/// converted into `DiagnosticBuilder<G2>` while reusing the `inner` field
|
||||
/// 2. can implement the `Drop` "bomb" instead of `DiagnosticBuilder`, as it
|
||||
/// contains all of the data (`state` + `diagnostic`) of `DiagnosticBuilder`
|
||||
///
|
||||
/// The `diagnostic` field is not `Copy` and can't be moved out of whichever
|
||||
/// type implements the `Drop` "bomb", but because of the above two facts, that
|
||||
/// never needs to happen - instead, the whole `inner: DiagnosticBuilderInner`
|
||||
/// can be moved out of a `DiagnosticBuilder` and into another.
|
||||
#[must_use]
|
||||
#[derive(Clone)]
|
||||
struct DiagnosticBuilderInner<'a> {
|
||||
pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> {
|
||||
state: DiagnosticBuilderState<'a>,
|
||||
|
||||
/// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a
|
||||
@ -68,6 +51,8 @@ struct DiagnosticBuilderInner<'a> {
|
||||
/// In theory, return value optimization (RVO) should avoid unnecessary
|
||||
/// copying. In practice, it does not (at the time of writing).
|
||||
diagnostic: Box<Diagnostic>,
|
||||
|
||||
_marker: PhantomData<G>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -83,7 +68,7 @@ enum DiagnosticBuilderState<'a> {
|
||||
/// 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 `DiagnosticBuilderInner`, as `.cancel()` takes
|
||||
/// 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`,
|
||||
@ -101,47 +86,50 @@ rustc_data_structures::static_assert_size!(
|
||||
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
|
||||
/// (or "proof") token that the emission happened.
|
||||
pub trait EmissionGuarantee: Sized {
|
||||
/// This exists so that bugs and fatal errors can both result in `!` (an
|
||||
/// abort) when emitted, but have different aborting behaviour.
|
||||
type EmitResult = Self;
|
||||
|
||||
/// Implementation of `DiagnosticBuilder::emit`, fully controlled by each
|
||||
/// `impl` of `EmissionGuarantee`, to make it impossible to create a value
|
||||
/// of `Self` without actually performing the emission.
|
||||
/// of `Self::EmitResult` without actually performing the emission.
|
||||
#[track_caller]
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self;
|
||||
|
||||
/// Creates a new `DiagnosticBuilder` that will return this type of guarantee.
|
||||
#[track_caller]
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self>;
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult;
|
||||
}
|
||||
|
||||
impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
/// Discard the guarantee `.emit()` would return, in favor of having the
|
||||
/// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there
|
||||
/// is a common codepath handling both errors and warnings.
|
||||
pub fn forget_guarantee(self) -> DiagnosticBuilder<'a, ()> {
|
||||
DiagnosticBuilder { inner: self.inner, _marker: PhantomData }
|
||||
impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// 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 => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`.
|
||||
impl EmissionGuarantee for ErrorGuaranteed {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
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.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
|
||||
let guar = dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
|
||||
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.inner.diagnostic.is_error(),
|
||||
db.diagnostic.is_error(),
|
||||
"emitted non-error ({:?}) diagnostic \
|
||||
from `DiagnosticBuilder<ErrorGuaranteed>`",
|
||||
db.inner.diagnostic.level,
|
||||
db.diagnostic.level,
|
||||
);
|
||||
guar.unwrap()
|
||||
}
|
||||
@ -153,152 +141,58 @@ impl EmissionGuarantee for ErrorGuaranteed {
|
||||
// non-error - the field isn't `pub`, but the whole `Diagnostic`
|
||||
// can be overwritten with a new one, thanks to `DerefMut`.
|
||||
assert!(
|
||||
db.inner.diagnostic.is_error(),
|
||||
db.diagnostic.is_error(),
|
||||
"`DiagnosticBuilder<ErrorGuaranteed>`'s diagnostic \
|
||||
became non-error ({:?}), after original `.emit()`",
|
||||
db.inner.diagnostic.level,
|
||||
db.diagnostic.level,
|
||||
);
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new(dcx, Level::Error { lint: false }, msg)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well?
|
||||
impl EmissionGuarantee for () {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
|
||||
dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new(dcx, Level::Warning(None), msg)
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type which enables implementation of `create_note` and `emit_note` functions for
|
||||
/// note-without-error struct diagnostics.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Noted;
|
||||
|
||||
impl EmissionGuarantee for Noted {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
|
||||
Noted
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new(dcx, Level::Note, msg)
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for
|
||||
/// bug struct diagnostics.
|
||||
/// bug diagnostics.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Bug;
|
||||
pub struct BugAbort;
|
||||
|
||||
impl EmissionGuarantee for Bug {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
impl EmissionGuarantee for BugAbort {
|
||||
type EmitResult = !;
|
||||
|
||||
dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
// Then panic. No need to return the marker type.
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new(dcx, Level::Bug, msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl EmissionGuarantee for ! {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for
|
||||
/// fatal diagnostics.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FatalAbort;
|
||||
|
||||
dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
// Then fatally error, returning `!`
|
||||
impl EmissionGuarantee for FatalAbort {
|
||||
type EmitResult = !;
|
||||
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
crate::FatalError.raise()
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new(dcx, Level::Fatal, msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&DiagCtxt` is still available.
|
||||
DiagnosticBuilderState::Emittable(dcx) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
|
||||
dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
// Then fatally error..
|
||||
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
|
||||
db.emit_producing_nothing();
|
||||
rustc_span::fatal_error::FatalError
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
dcx: &DiagCtxt,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new(dcx, Level::Fatal, msg)
|
||||
}
|
||||
}
|
||||
|
||||
/// In general, the `DiagnosticBuilder` uses deref to allow access to
|
||||
@ -318,7 +212,7 @@ macro_rules! forward {
|
||||
$(#[$attrs])*
|
||||
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
|
||||
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
|
||||
self.inner.diagnostic.$n($($name),*);
|
||||
self.diagnostic.$n($($name),*);
|
||||
self
|
||||
}
|
||||
};
|
||||
@ -328,27 +222,21 @@ impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> {
|
||||
type Target = Diagnostic;
|
||||
|
||||
fn deref(&self) -> &Diagnostic {
|
||||
&self.inner.diagnostic
|
||||
&self.diagnostic
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> {
|
||||
fn deref_mut(&mut self) -> &mut Diagnostic {
|
||||
&mut self.inner.diagnostic
|
||||
&mut self.diagnostic
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// Convenience function for internal use, clients should use one of the
|
||||
/// `struct_*` methods on [`DiagCtxt`].
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub(crate) fn new<M: Into<DiagnosticMessage>>(
|
||||
dcx: &'a DiagCtxt,
|
||||
level: Level,
|
||||
message: M,
|
||||
) -> Self {
|
||||
let diagnostic = Diagnostic::new(level, message);
|
||||
Self::new_diagnostic(dcx, diagnostic)
|
||||
pub fn new<M: Into<DiagnosticMessage>>(dcx: &'a DiagCtxt, level: Level, message: M) -> Self {
|
||||
Self::new_diagnostic(dcx, Diagnostic::new(level, message))
|
||||
}
|
||||
|
||||
/// Creates a new `DiagnosticBuilder` with an already constructed
|
||||
@ -357,10 +245,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self {
|
||||
debug!("Created new diagnostic");
|
||||
Self {
|
||||
inner: DiagnosticBuilderInner {
|
||||
state: DiagnosticBuilderState::Emittable(dcx),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
},
|
||||
state: DiagnosticBuilderState::Emittable(dcx),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -369,8 +255,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// but there are various places that rely on continuing to use `self`
|
||||
/// after calling `emit`.
|
||||
#[track_caller]
|
||||
pub fn emit(&mut self) -> G {
|
||||
G::diagnostic_builder_emit_producing_guarantee(self)
|
||||
pub fn emit(&mut self) -> G::EmitResult {
|
||||
G::emit_producing_guarantee(self)
|
||||
}
|
||||
|
||||
/// Emit the diagnostic unless `delay` is true,
|
||||
@ -378,7 +264,7 @@ 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 {
|
||||
pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult {
|
||||
if delay {
|
||||
self.downgrade_to_delayed_bug();
|
||||
}
|
||||
@ -392,7 +278,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// 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.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
drop(self);
|
||||
}
|
||||
|
||||
@ -400,17 +286,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
/// later stage of the compiler. The diagnostic can be accessed with
|
||||
/// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`].
|
||||
///
|
||||
/// As with `buffer`, this is unless the handler has disabled such buffering.
|
||||
/// As with `buffer`, this is unless the dcx has disabled such buffering.
|
||||
pub fn stash(self, span: Span, key: StashKey) {
|
||||
if let Some((diag, handler)) = self.into_diagnostic() {
|
||||
handler.stash_diagnostic(span, key, diag);
|
||||
if let Some((diag, dcx)) = self.into_diagnostic() {
|
||||
dcx.stash_diagnostic(span, key, diag);
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the builder to a `Diagnostic` for later emission,
|
||||
/// unless handler has disabled such buffering, or `.emit()` was called.
|
||||
/// unless dcx has disabled such buffering, or `.emit()` was called.
|
||||
pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> {
|
||||
let dcx = match self.inner.state {
|
||||
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.
|
||||
@ -428,7 +314,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
|
||||
// Take the `Diagnostic` by replacing it with a dummy.
|
||||
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from(""));
|
||||
let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy);
|
||||
let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy);
|
||||
|
||||
// Disable the ICE on `Drop`.
|
||||
self.cancel();
|
||||
@ -442,14 +328,14 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
|
||||
/// Retrieves the [`DiagCtxt`] if available
|
||||
pub fn dcx(&self) -> Option<&DiagCtxt> {
|
||||
match self.inner.state {
|
||||
match self.state {
|
||||
DiagnosticBuilderState::Emittable(dcx) => Some(dcx),
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Buffers the diagnostic for later emission,
|
||||
/// unless handler has disabled such buffering.
|
||||
/// unless dcx has disabled such buffering.
|
||||
pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
|
||||
buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag));
|
||||
}
|
||||
@ -465,7 +351,7 @@ 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 {
|
||||
pub fn delay_as_bug(&mut self) -> G::EmitResult {
|
||||
self.downgrade_to_delayed_bug();
|
||||
self.emit()
|
||||
}
|
||||
@ -630,13 +516,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
|
||||
impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.diagnostic.fmt(f)
|
||||
self.diagnostic.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
|
||||
/// or we emit a bug.
|
||||
impl Drop for DiagnosticBuilderInner<'_> {
|
||||
impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
|
||||
fn drop(&mut self) {
|
||||
match self.state {
|
||||
// No `.emit()` or `.cancel()` calls.
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::diagnostic::DiagnosticLocation;
|
||||
use crate::{fluent_generated as fluent, AddToDiagnostic};
|
||||
use crate::{DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg};
|
||||
use crate::{
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
IntoDiagnosticArg, Level,
|
||||
};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint_defs::Level;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
|
||||
use rustc_span::Span;
|
||||
@ -216,7 +218,7 @@ impl IntoDiagnosticArg for ast::Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for Level {
|
||||
impl IntoDiagnosticArg for rustc_lint_defs::Level {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
|
||||
}
|
||||
@ -245,19 +247,20 @@ impl<Id> IntoDiagnosticArg for hir::def::Res<Id> {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
||||
fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, !> {
|
||||
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 = dcx.struct_fatal(fluent::errors_target_invalid_address_space);
|
||||
diag =
|
||||
DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space);
|
||||
diag.set_arg("addr_space", addr_space);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err", err);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
|
||||
diag = dcx.struct_fatal(fluent::errors_target_invalid_bits);
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits);
|
||||
diag.set_arg("kind", kind);
|
||||
diag.set_arg("bit", bit);
|
||||
diag.set_arg("cause", cause);
|
||||
@ -265,31 +268,39 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::MissingAlignment { cause } => {
|
||||
diag = dcx.struct_fatal(fluent::errors_target_missing_alignment);
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment);
|
||||
diag.set_arg("cause", cause);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
|
||||
diag = dcx.struct_fatal(fluent::errors_target_invalid_alignment);
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err_kind", err.diag_ident());
|
||||
diag.set_arg("align", err.align());
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
|
||||
diag = dcx.struct_fatal(fluent::errors_target_inconsistent_architecture);
|
||||
diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::errors_target_inconsistent_architecture,
|
||||
);
|
||||
diag.set_arg("dl", dl);
|
||||
diag.set_arg("target", target);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
|
||||
diag = dcx.struct_fatal(fluent::errors_target_inconsistent_pointer_width);
|
||||
diag = DiagnosticBuilder::new(
|
||||
dcx,
|
||||
level,
|
||||
fluent::errors_target_inconsistent_pointer_width,
|
||||
);
|
||||
diag.set_arg("pointer_size", pointer_size);
|
||||
diag.set_arg("target", target);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBitsSize { err } => {
|
||||
diag = dcx.struct_fatal(fluent::errors_target_invalid_bits_size);
|
||||
diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size);
|
||||
diag.set_arg("err", err);
|
||||
diag
|
||||
}
|
||||
@ -301,25 +312,13 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
||||
pub struct SingleLabelManySpans {
|
||||
pub spans: Vec<Span>,
|
||||
pub label: &'static str,
|
||||
pub kind: LabelKind,
|
||||
}
|
||||
impl AddToDiagnostic for SingleLabelManySpans {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut crate::Diagnostic, _: F) {
|
||||
match self.kind {
|
||||
LabelKind::Note => diag.span_note(self.spans, self.label),
|
||||
LabelKind::Label => diag.span_labels(self.spans, self.label),
|
||||
LabelKind::Help => diag.span_help(self.spans, self.label),
|
||||
};
|
||||
diag.span_labels(self.spans, self.label);
|
||||
}
|
||||
}
|
||||
|
||||
/// The kind of label to attach when using [`SingleLabelManySpans`]
|
||||
pub enum LabelKind {
|
||||
Note,
|
||||
Label,
|
||||
Help,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[label(errors_expected_lifetime_parameter)]
|
||||
pub struct ExpectedLifetimeParameter {
|
||||
@ -362,9 +361,9 @@ impl IntoDiagnosticArg for Backtrace {
|
||||
pub struct InvalidFlushedDelayedDiagnosticLevel {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub level: rustc_errors::Level,
|
||||
pub level: Level,
|
||||
}
|
||||
impl IntoDiagnosticArg for rustc_errors::Level {
|
||||
impl IntoDiagnosticArg for Level {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
|
@ -350,9 +350,8 @@ pub trait Emitter: Translate {
|
||||
|
||||
children.push(SubDiagnostic {
|
||||
level: Level::Note,
|
||||
message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
|
||||
messages: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
|
||||
span: MultiSpan::new(),
|
||||
render_span: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -533,7 +532,7 @@ impl Emitter for EmitterWriter {
|
||||
|
||||
self.emit_messages_default(
|
||||
&diag.level,
|
||||
&diag.message,
|
||||
&diag.messages,
|
||||
&fluent_args,
|
||||
&diag.code,
|
||||
&primary_span,
|
||||
@ -1228,10 +1227,10 @@ impl EmitterWriter {
|
||||
|
||||
/// Adds a left margin to every line but the first, given a padding length and the label being
|
||||
/// displayed, keeping the provided highlighting.
|
||||
fn msg_to_buffer(
|
||||
fn msgs_to_buffer(
|
||||
&self,
|
||||
buffer: &mut StyledBuffer,
|
||||
msg: &[(DiagnosticMessage, Style)],
|
||||
msgs: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
padding: usize,
|
||||
label: &str,
|
||||
@ -1267,7 +1266,7 @@ impl EmitterWriter {
|
||||
|
||||
// Provided the following diagnostic message:
|
||||
//
|
||||
// let msg = vec![
|
||||
// let msgs = vec![
|
||||
// ("
|
||||
// ("highlighted multiline\nstring to\nsee how it ", Style::NoStyle),
|
||||
// ("looks", Style::Highlight),
|
||||
@ -1284,7 +1283,7 @@ impl EmitterWriter {
|
||||
// see how it *looks* with
|
||||
// very *weird* formats
|
||||
// see?
|
||||
for (text, style) in msg.iter() {
|
||||
for (text, style) in msgs.iter() {
|
||||
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
|
||||
let text = &normalize_whitespace(&text);
|
||||
let lines = text.split('\n').collect::<Vec<_>>();
|
||||
@ -1303,10 +1302,10 @@ impl EmitterWriter {
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, args), ret)]
|
||||
fn emit_message_default(
|
||||
fn emit_messages_default_inner(
|
||||
&mut self,
|
||||
msp: &MultiSpan,
|
||||
msg: &[(DiagnosticMessage, Style)],
|
||||
msgs: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
code: &Option<DiagnosticId>,
|
||||
level: &Level,
|
||||
@ -1327,7 +1326,7 @@ impl EmitterWriter {
|
||||
buffer.append(0, level.to_str(), Style::MainHeaderMsg);
|
||||
buffer.append(0, ": ", Style::NoStyle);
|
||||
}
|
||||
self.msg_to_buffer(&mut buffer, msg, args, max_line_num_len, "note", None);
|
||||
self.msgs_to_buffer(&mut buffer, msgs, args, max_line_num_len, "note", None);
|
||||
} else {
|
||||
let mut label_width = 0;
|
||||
// The failure note level itself does not provide any useful diagnostic information
|
||||
@ -1360,7 +1359,7 @@ impl EmitterWriter {
|
||||
buffer.append(0, ": ", header_style);
|
||||
label_width += 2;
|
||||
}
|
||||
for (text, _) in msg.iter() {
|
||||
for (text, _) in msgs.iter() {
|
||||
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
|
||||
// Account for newlines to align output to its label.
|
||||
for (line, text) in normalize_whitespace(&text).lines().enumerate() {
|
||||
@ -1747,7 +1746,7 @@ impl EmitterWriter {
|
||||
buffer.append(0, level.to_str(), Style::Level(*level));
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
|
||||
self.msg_to_buffer(
|
||||
self.msgs_to_buffer(
|
||||
&mut buffer,
|
||||
&[(suggestion.msg.to_owned(), Style::NoStyle)],
|
||||
args,
|
||||
@ -2074,7 +2073,7 @@ impl EmitterWriter {
|
||||
fn emit_messages_default(
|
||||
&mut self,
|
||||
level: &Level,
|
||||
message: &[(DiagnosticMessage, Style)],
|
||||
messages: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
code: &Option<DiagnosticId>,
|
||||
span: &MultiSpan,
|
||||
@ -2089,9 +2088,9 @@ impl EmitterWriter {
|
||||
num_decimal_digits(n)
|
||||
};
|
||||
|
||||
match self.emit_message_default(
|
||||
match self.emit_messages_default_inner(
|
||||
span,
|
||||
message,
|
||||
messages,
|
||||
args,
|
||||
code,
|
||||
level,
|
||||
@ -2118,10 +2117,10 @@ impl EmitterWriter {
|
||||
}
|
||||
if !self.short_message {
|
||||
for child in children {
|
||||
let span = child.render_span.as_ref().unwrap_or(&child.span);
|
||||
if let Err(err) = self.emit_message_default(
|
||||
let span = &child.span;
|
||||
if let Err(err) = self.emit_messages_default_inner(
|
||||
span,
|
||||
&child.message,
|
||||
&child.messages,
|
||||
args,
|
||||
&None,
|
||||
&child.level,
|
||||
@ -2138,7 +2137,7 @@ impl EmitterWriter {
|
||||
// do not display this suggestion, it is meant only for tools
|
||||
}
|
||||
SuggestionStyle::HideCodeAlways => {
|
||||
if let Err(e) = self.emit_message_default(
|
||||
if let Err(e) = self.emit_messages_default_inner(
|
||||
&MultiSpan::new(),
|
||||
&[(sugg.msg.to_owned(), Style::HeaderMsg)],
|
||||
args,
|
||||
|
@ -398,7 +398,7 @@ impl Diagnostic {
|
||||
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
|
||||
let output = String::from_utf8(output).unwrap();
|
||||
|
||||
let translated_message = je.translate_messages(&diag.message, &args);
|
||||
let translated_message = je.translate_messages(&diag.messages, &args);
|
||||
Diagnostic {
|
||||
message: translated_message.to_string(),
|
||||
code: DiagnosticCode::map_opt_string(diag.code.clone(), je),
|
||||
@ -419,16 +419,12 @@ impl Diagnostic {
|
||||
args: &FluentArgs<'_>,
|
||||
je: &JsonEmitter,
|
||||
) -> Diagnostic {
|
||||
let translated_message = je.translate_messages(&diag.message, args);
|
||||
let translated_message = je.translate_messages(&diag.messages, args);
|
||||
Diagnostic {
|
||||
message: translated_message.to_string(),
|
||||
code: None,
|
||||
level: diag.level.to_str(),
|
||||
spans: diag
|
||||
.render_span
|
||||
.as_ref()
|
||||
.map(|sp| DiagnosticSpan::from_multispan(sp, args, je))
|
||||
.unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)),
|
||||
spans: DiagnosticSpan::from_multispan(&diag.span, args, je),
|
||||
children: vec![],
|
||||
rendered: None,
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(extract_if)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
@ -26,26 +27,42 @@ extern crate tracing;
|
||||
|
||||
extern crate self as rustc_errors;
|
||||
|
||||
pub use diagnostic::{
|
||||
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
|
||||
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
||||
};
|
||||
pub use diagnostic_builder::{
|
||||
BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic,
|
||||
};
|
||||
pub use diagnostic_impls::{
|
||||
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
|
||||
IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, SingleLabelManySpans,
|
||||
};
|
||||
pub use emitter::ColorConfig;
|
||||
pub use rustc_error_messages::{
|
||||
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
|
||||
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
|
||||
};
|
||||
pub use rustc_lint_defs::{pluralize, Applicability};
|
||||
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
|
||||
pub use rustc_span::ErrorGuaranteed;
|
||||
pub use snippet::Style;
|
||||
|
||||
use rustc_lint_defs::LintExpectationId;
|
||||
use Level::*;
|
||||
// Used by external projects such as `rust-gpu`.
|
||||
// See https://github.com/rust-lang/rust/pull/115393.
|
||||
pub use termcolor::{Color, ColorSpec, WriteColor};
|
||||
|
||||
use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline};
|
||||
use emitter::{is_case_difference, DynEmitter, Emitter, EmitterWriter};
|
||||
use registry::Registry;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_data_structures::AtomicRef;
|
||||
pub use rustc_error_messages::{
|
||||
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
|
||||
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
|
||||
};
|
||||
pub use rustc_lint_defs::{pluralize, Applicability};
|
||||
use rustc_lint_defs::LintExpectationId;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
pub use rustc_span::ErrorGuaranteed;
|
||||
use rustc_span::{Loc, Span, DUMMY_SP};
|
||||
|
||||
use std::backtrace::{Backtrace, BacktraceStatus};
|
||||
use std::borrow::Cow;
|
||||
use std::error::Report;
|
||||
use std::fmt;
|
||||
@ -55,9 +72,7 @@ use std::num::NonZeroUsize;
|
||||
use std::panic;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// Used by external projects such as `rust-gpu`.
|
||||
// See https://github.com/rust-lang/rust/pull/115393.
|
||||
pub use termcolor::{Color, ColorSpec, WriteColor};
|
||||
use Level::*;
|
||||
|
||||
pub mod annotate_snippet_emitter_writer;
|
||||
mod diagnostic;
|
||||
@ -75,10 +90,7 @@ mod styled_buffer;
|
||||
mod tests;
|
||||
pub mod translation;
|
||||
|
||||
pub use diagnostic_builder::IntoDiagnostic;
|
||||
pub use snippet::Style;
|
||||
|
||||
pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
|
||||
pub type PErr<'a> = DiagnosticBuilder<'a>;
|
||||
pub type PResult<'a, T> = Result<T, PErr<'a>>;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
@ -162,7 +174,7 @@ pub struct SubstitutionPart {
|
||||
/// Used to translate between `Span`s and byte positions within a single output line in highlighted
|
||||
/// code of structured suggestions.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct SubstitutionHighlight {
|
||||
pub(crate) struct SubstitutionHighlight {
|
||||
start: usize,
|
||||
end: usize,
|
||||
}
|
||||
@ -189,7 +201,7 @@ impl SubstitutionPart {
|
||||
impl CodeSuggestion {
|
||||
/// Returns the assembled code suggestions, whether they should be shown with an underline
|
||||
/// and whether the substitution only differs in capitalization.
|
||||
pub fn splice_lines(
|
||||
pub(crate) fn splice_lines(
|
||||
&self,
|
||||
sm: &SourceMap,
|
||||
) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, bool)> {
|
||||
@ -386,8 +398,6 @@ impl CodeSuggestion {
|
||||
}
|
||||
}
|
||||
|
||||
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
|
||||
|
||||
/// Signifies that the compiler died with an explicit call to `.bug`
|
||||
/// or `.span_bug` rather than a failed assertion, etc.
|
||||
pub struct ExplicitBug;
|
||||
@ -396,20 +406,7 @@ pub struct ExplicitBug;
|
||||
/// rather than a failed assertion, etc.
|
||||
pub struct DelayedBugPanic;
|
||||
|
||||
use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline};
|
||||
pub use diagnostic::{
|
||||
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
|
||||
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
||||
};
|
||||
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
|
||||
pub use diagnostic_impls::{
|
||||
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
|
||||
IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind,
|
||||
SingleLabelManySpans,
|
||||
};
|
||||
use std::backtrace::{Backtrace, BacktraceStatus};
|
||||
|
||||
/// A handler deals with errors and other compiler output.
|
||||
/// A `DiagCtxt` deals with errors and other compiler output.
|
||||
/// Certain errors (fatal, bug, unimpl) may cause immediate exit,
|
||||
/// others log errors for later reporting.
|
||||
pub struct DiagCtxt {
|
||||
@ -446,7 +443,7 @@ struct DiagCtxtInner {
|
||||
emitted_diagnostic_codes: FxIndexSet<DiagnosticId>,
|
||||
|
||||
/// This set contains a hash of every diagnostic that has been emitted by
|
||||
/// this handler. These hashes is used to avoid emitting the same error
|
||||
/// this `DiagCtxt`. These hashes is used to avoid emitting the same error
|
||||
/// twice.
|
||||
emitted_diagnostics: FxHashSet<Hash128>,
|
||||
|
||||
@ -676,7 +673,7 @@ impl DiagCtxt {
|
||||
let key = (span.with_parent(None), key);
|
||||
|
||||
if diag.is_error() {
|
||||
if matches!(diag.level, Level::Error { lint: true }) {
|
||||
if matches!(diag.level, Error { lint: true }) {
|
||||
inner.lint_err_count += 1;
|
||||
} else {
|
||||
inner.err_count += 1;
|
||||
@ -700,7 +697,7 @@ impl DiagCtxt {
|
||||
let key = (span.with_parent(None), key);
|
||||
let diag = inner.stashed_diagnostics.remove(&key)?;
|
||||
if diag.is_error() {
|
||||
if matches!(diag.level, Level::Error { lint: true }) {
|
||||
if matches!(diag.level, Error { lint: true }) {
|
||||
inner.lint_err_count -= 1;
|
||||
} else {
|
||||
inner.err_count -= 1;
|
||||
@ -722,21 +719,6 @@ impl DiagCtxt {
|
||||
self.inner.borrow_mut().emit_stashed_diagnostics()
|
||||
}
|
||||
|
||||
/// Construct a builder with the `msg` at the level appropriate for the
|
||||
/// specific `EmissionGuarantee`.
|
||||
///
|
||||
/// Note: this is necessary for `derive(Diagnostic)`, but shouldn't be used
|
||||
/// outside of that. Instead use `struct_err`, `struct_warn`, etc., which
|
||||
/// make the diagnostic kind clearer.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_diagnostic<G: EmissionGuarantee>(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, G> {
|
||||
G::make_diagnostic_builder(self, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
|
||||
///
|
||||
/// Attempting to `.emit()` the builder will only emit if either:
|
||||
@ -754,37 +736,6 @@ impl DiagCtxt {
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
|
||||
/// The `id` is used for lint emissions which should also fulfill a lint expectation.
|
||||
///
|
||||
/// Attempting to `.emit()` the builder will only emit if either:
|
||||
/// * `can_emit_warnings` is `true`
|
||||
/// * `is_force_warn` was set in `DiagnosticId::Lint`
|
||||
#[track_caller]
|
||||
pub fn struct_span_warn_with_expectation(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
id: LintExpectationId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_warn_with_expectation(msg, id);
|
||||
result.set_span(span);
|
||||
result
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_allow(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
let mut result = self.struct_allow(msg);
|
||||
result.set_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]
|
||||
@ -808,29 +759,14 @@ impl DiagCtxt {
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Warning(None), msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Warning` level with the `msg`. The `id` is used for
|
||||
/// lint emissions which should also fulfill a lint expectation.
|
||||
///
|
||||
/// Attempting to `.emit()` the builder will only emit if either:
|
||||
/// * `can_emit_warnings` is `true`
|
||||
/// * `is_force_warn` was set in `DiagnosticId::Lint`
|
||||
#[track_caller]
|
||||
pub fn struct_warn_with_expectation(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
id: LintExpectationId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Warning(Some(id)), msg)
|
||||
DiagnosticBuilder::new(self, Warning(None), msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Allow` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Allow, msg)
|
||||
DiagnosticBuilder::new(self, Allow, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Expect` level with the `msg`.
|
||||
@ -841,7 +777,7 @@ impl DiagCtxt {
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
id: LintExpectationId,
|
||||
) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Expect(id), msg)
|
||||
DiagnosticBuilder::new(self, Expect(id), msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level at the given `span` and with the `msg`.
|
||||
@ -851,7 +787,7 @@ impl DiagCtxt {
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.set_span(span);
|
||||
result
|
||||
@ -865,7 +801,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_span_err(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
@ -875,18 +811,8 @@ impl DiagCtxt {
|
||||
// FIXME: This method should be removed (every error should have an associated error code).
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_err(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
DiagnosticBuilder::new(self, Level::Error { lint: false }, msg)
|
||||
}
|
||||
|
||||
/// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors.
|
||||
#[doc(hidden)]
|
||||
#[track_caller]
|
||||
pub fn struct_err_lint(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Error { lint: true }, msg)
|
||||
pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_> {
|
||||
DiagnosticBuilder::new(self, Error { lint: false }, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Error` level with the `msg` and the `code`.
|
||||
@ -896,7 +822,7 @@ impl DiagCtxt {
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut result = self.struct_err(msg);
|
||||
result.code(code);
|
||||
result
|
||||
@ -922,7 +848,7 @@ impl DiagCtxt {
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, !> {
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_fatal(msg);
|
||||
result.set_span(span);
|
||||
result
|
||||
@ -936,7 +862,7 @@ impl DiagCtxt {
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
code: DiagnosticId,
|
||||
) -> DiagnosticBuilder<'_, !> {
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
let mut result = self.struct_span_fatal(span, msg);
|
||||
result.code(code);
|
||||
result
|
||||
@ -945,8 +871,11 @@ impl DiagCtxt {
|
||||
/// Construct a builder at the `Fatal` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
|
||||
DiagnosticBuilder::new(self, Level::Fatal, msg)
|
||||
pub fn struct_fatal(
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, FatalAbort> {
|
||||
DiagnosticBuilder::new(self, Fatal, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Fatal` level with the `msg`, that doesn't abort.
|
||||
@ -956,20 +885,40 @@ impl DiagCtxt {
|
||||
&self,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, FatalError> {
|
||||
DiagnosticBuilder::new(self, Level::Fatal, msg)
|
||||
DiagnosticBuilder::new(self, Fatal, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Help` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Help, msg)
|
||||
DiagnosticBuilder::new(self, Help, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Note` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_note(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
|
||||
DiagnosticBuilder::new(self, Level::Note, msg)
|
||||
DiagnosticBuilder::new(self, Note, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Bug` level with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_bug(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, BugAbort> {
|
||||
DiagnosticBuilder::new(self, Bug, msg)
|
||||
}
|
||||
|
||||
/// Construct a builder at the `Bug` level at the given `span` with the `msg`.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_bug(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, BugAbort> {
|
||||
let mut result = self.struct_bug(msg);
|
||||
result.set_span(span);
|
||||
result
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
@ -1028,7 +977,7 @@ impl DiagCtxt {
|
||||
}
|
||||
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
self.inner.borrow_mut().span_bug(span, msg)
|
||||
self.struct_span_bug(span, msg).emit()
|
||||
}
|
||||
|
||||
/// For documentation on this, see `Session::span_delayed_bug`.
|
||||
@ -1041,20 +990,14 @@ impl DiagCtxt {
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> ErrorGuaranteed {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
// This is technically `self.treat_err_as_bug()` but `span_delayed_bug` is called before
|
||||
// incrementing `err_count` by one, so we need to +1 the comparing.
|
||||
// FIXME: Would be nice to increment err_count in a more coherent way.
|
||||
if inner.flags.treat_err_as_bug.is_some_and(|c| {
|
||||
inner.err_count + inner.lint_err_count + inner.delayed_bug_count() + 1 >= c.get()
|
||||
}) {
|
||||
let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug();
|
||||
if treat_next_err_as_bug {
|
||||
// FIXME: don't abort here if report_delayed_bugs is off
|
||||
inner.span_bug(sp, msg);
|
||||
self.span_bug(sp, msg);
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
||||
let mut diagnostic = Diagnostic::new(DelayedBug, msg);
|
||||
diagnostic.set_span(sp);
|
||||
inner.emit_diagnostic(diagnostic).unwrap()
|
||||
self.emit_diagnostic(diagnostic).unwrap()
|
||||
}
|
||||
|
||||
// FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's
|
||||
@ -1062,7 +1005,7 @@ impl DiagCtxt {
|
||||
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
||||
let mut diagnostic = Diagnostic::new(DelayedBug, msg);
|
||||
if inner.flags.report_delayed_bugs {
|
||||
inner.emit_diagnostic_without_consuming(&mut diagnostic);
|
||||
}
|
||||
@ -1070,13 +1013,6 @@ impl DiagCtxt {
|
||||
inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn span_bug_no_panic(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut diag = Diagnostic::new(Bug, msg);
|
||||
diag.set_span(span);
|
||||
self.emit_diagnostic(diag);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
|
||||
@ -1115,9 +1051,9 @@ impl DiagCtxt {
|
||||
self.struct_note(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn bug(&self, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
DiagnosticBuilder::<diagnostic_builder::Bug>::new(self, Bug, msg).emit();
|
||||
panic::panic_any(ExplicitBug);
|
||||
self.struct_bug(msg).emit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1182,10 +1118,9 @@ impl DiagCtxt {
|
||||
|
||||
match (errors.len(), warnings.len()) {
|
||||
(0, 0) => return,
|
||||
(0, _) => inner.emitter.emit_diagnostic(&Diagnostic::new(
|
||||
Level::Warning(None),
|
||||
DiagnosticMessage::Str(warnings),
|
||||
)),
|
||||
(0, _) => inner
|
||||
.emitter
|
||||
.emit_diagnostic(&Diagnostic::new(Warning(None), DiagnosticMessage::Str(warnings))),
|
||||
(_, 0) => {
|
||||
inner.emit_diagnostic(Diagnostic::new(Fatal, errors));
|
||||
}
|
||||
@ -1217,14 +1152,12 @@ impl DiagCtxt {
|
||||
if error_codes.len() > 9 { "..." } else { "." }
|
||||
));
|
||||
inner.failure_note(format!(
|
||||
"For more information about an error, try \
|
||||
`rustc --explain {}`.",
|
||||
"For more information about an error, try `rustc --explain {}`.",
|
||||
&error_codes[0]
|
||||
));
|
||||
} else {
|
||||
inner.failure_note(format!(
|
||||
"For more information about this error, try \
|
||||
`rustc --explain {}`.",
|
||||
"For more information about this error, try `rustc --explain {}`.",
|
||||
&error_codes[0]
|
||||
));
|
||||
}
|
||||
@ -1274,18 +1207,16 @@ impl DiagCtxt {
|
||||
self.create_err(err).emit()
|
||||
}
|
||||
|
||||
pub fn create_err<'a>(
|
||||
&'a self,
|
||||
err: impl IntoDiagnostic<'a>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
err.into_diagnostic(self)
|
||||
#[track_caller]
|
||||
pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> {
|
||||
err.into_diagnostic(self, Error { lint: false })
|
||||
}
|
||||
|
||||
pub fn create_warning<'a>(
|
||||
&'a self,
|
||||
warning: impl IntoDiagnostic<'a, ()>,
|
||||
) -> DiagnosticBuilder<'a, ()> {
|
||||
warning.into_diagnostic(self)
|
||||
warning.into_diagnostic(self, Warning(None))
|
||||
}
|
||||
|
||||
pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
|
||||
@ -1296,7 +1227,7 @@ impl DiagCtxt {
|
||||
&'a self,
|
||||
fatal: impl IntoDiagnostic<'a, FatalError>,
|
||||
) -> DiagnosticBuilder<'a, FatalError> {
|
||||
fatal.into_diagnostic(self)
|
||||
fatal.into_diagnostic(self, Fatal)
|
||||
}
|
||||
|
||||
pub fn emit_almost_fatal<'a>(
|
||||
@ -1308,38 +1239,35 @@ impl DiagCtxt {
|
||||
|
||||
pub fn create_fatal<'a>(
|
||||
&'a self,
|
||||
fatal: impl IntoDiagnostic<'a, !>,
|
||||
) -> DiagnosticBuilder<'a, !> {
|
||||
fatal.into_diagnostic(self)
|
||||
fatal: impl IntoDiagnostic<'a, FatalAbort>,
|
||||
) -> DiagnosticBuilder<'a, FatalAbort> {
|
||||
fatal.into_diagnostic(self, Fatal)
|
||||
}
|
||||
|
||||
pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
|
||||
pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! {
|
||||
self.create_fatal(fatal).emit()
|
||||
}
|
||||
|
||||
pub fn create_bug<'a>(
|
||||
&'a self,
|
||||
bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>,
|
||||
) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> {
|
||||
bug.into_diagnostic(self)
|
||||
bug: impl IntoDiagnostic<'a, BugAbort>,
|
||||
) -> DiagnosticBuilder<'a, BugAbort> {
|
||||
bug.into_diagnostic(self, Bug)
|
||||
}
|
||||
|
||||
pub fn emit_bug<'a>(
|
||||
&'a self,
|
||||
bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>,
|
||||
) -> diagnostic_builder::Bug {
|
||||
pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! {
|
||||
self.create_bug(bug).emit()
|
||||
}
|
||||
|
||||
pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
|
||||
pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) {
|
||||
self.create_note(note).emit()
|
||||
}
|
||||
|
||||
pub fn create_note<'a>(
|
||||
&'a self,
|
||||
note: impl IntoDiagnostic<'a, Noted>,
|
||||
) -> DiagnosticBuilder<'a, Noted> {
|
||||
note.into_diagnostic(self)
|
||||
note: impl IntoDiagnostic<'a, ()>,
|
||||
) -> DiagnosticBuilder<'a, ()> {
|
||||
note.into_diagnostic(self, Note)
|
||||
}
|
||||
|
||||
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
|
||||
@ -1426,7 +1354,7 @@ impl DiagCtxtInner {
|
||||
for diag in diags {
|
||||
// Decrement the count tracking the stash; emitting will increment it.
|
||||
if diag.is_error() {
|
||||
if matches!(diag.level, Level::Error { lint: true }) {
|
||||
if matches!(diag.level, Error { lint: true }) {
|
||||
self.lint_err_count -= 1;
|
||||
} else {
|
||||
self.err_count -= 1;
|
||||
@ -1457,9 +1385,8 @@ impl DiagCtxtInner {
|
||||
&mut self,
|
||||
diagnostic: &mut Diagnostic,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if matches!(diagnostic.level, Level::Error { .. } | Level::Fatal) && self.treat_err_as_bug()
|
||||
{
|
||||
diagnostic.level = Level::Bug;
|
||||
if matches!(diagnostic.level, Error { .. } | Fatal) && self.treat_err_as_bug() {
|
||||
diagnostic.level = Bug;
|
||||
}
|
||||
|
||||
// The `LintExpectationId` can be stable or unstable depending on when it was created.
|
||||
@ -1471,7 +1398,7 @@ impl DiagCtxtInner {
|
||||
return None;
|
||||
}
|
||||
|
||||
if diagnostic.level == Level::DelayedBug {
|
||||
if diagnostic.level == DelayedBug {
|
||||
// FIXME(eddyb) this should check for `has_errors` and stop pushing
|
||||
// once *any* errors were emitted (and truncate `span_delayed_bugs`
|
||||
// when an error is first emitted, also), but maybe there's a case
|
||||
@ -1487,7 +1414,7 @@ impl DiagCtxtInner {
|
||||
}
|
||||
|
||||
if diagnostic.has_future_breakage() {
|
||||
// Future breakages aren't emitted if they're Level::Allowed,
|
||||
// Future breakages aren't emitted if they're Level::Allow,
|
||||
// but they still need to be constructed and stashed below,
|
||||
// so they'll trigger the good-path bug check.
|
||||
self.suppressed_expected_diag = true;
|
||||
@ -1509,7 +1436,7 @@ impl DiagCtxtInner {
|
||||
return None;
|
||||
}
|
||||
|
||||
if matches!(diagnostic.level, Level::Expect(_) | Level::Allow) {
|
||||
if matches!(diagnostic.level, Expect(_) | Allow) {
|
||||
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {});
|
||||
return None;
|
||||
}
|
||||
@ -1534,7 +1461,7 @@ impl DiagCtxtInner {
|
||||
debug!(?self.emitted_diagnostics);
|
||||
let already_emitted_sub = |sub: &mut SubDiagnostic| {
|
||||
debug!(?sub);
|
||||
if sub.level != Level::OnceNote && sub.level != Level::OnceHelp {
|
||||
if sub.level != OnceNote && sub.level != OnceHelp {
|
||||
return false;
|
||||
}
|
||||
let mut hasher = StableHasher::new();
|
||||
@ -1559,7 +1486,7 @@ impl DiagCtxtInner {
|
||||
}
|
||||
}
|
||||
if diagnostic.is_error() {
|
||||
if matches!(diagnostic.level, Level::Error { lint: true }) {
|
||||
if matches!(diagnostic.level, Error { lint: true }) {
|
||||
self.bump_lint_err_count();
|
||||
} else {
|
||||
self.bump_err_count();
|
||||
@ -1583,6 +1510,13 @@ impl DiagCtxtInner {
|
||||
})
|
||||
}
|
||||
|
||||
// Use this one before incrementing `err_count`.
|
||||
fn treat_next_err_as_bug(&self) -> bool {
|
||||
self.flags.treat_err_as_bug.is_some_and(|c| {
|
||||
self.err_count + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
|
||||
})
|
||||
}
|
||||
|
||||
fn delayed_bug_count(&self) -> usize {
|
||||
self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len()
|
||||
}
|
||||
@ -1591,27 +1525,22 @@ impl DiagCtxtInner {
|
||||
self.err_count > 0
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
let mut diag = Diagnostic::new(Bug, msg);
|
||||
diag.set_span(sp);
|
||||
self.emit_diagnostic(diag);
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
|
||||
fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) {
|
||||
self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
|
||||
}
|
||||
|
||||
fn flush_delayed(
|
||||
&mut self,
|
||||
bugs: impl IntoIterator<Item = DelayedDiagnostic>,
|
||||
bugs: Vec<DelayedDiagnostic>,
|
||||
explanation: impl Into<DiagnosticMessage> + Copy,
|
||||
) {
|
||||
let mut no_bugs = true;
|
||||
if bugs.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If backtraces are enabled, also print the query stack
|
||||
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
|
||||
for bug in bugs {
|
||||
for (i, bug) in bugs.into_iter().enumerate() {
|
||||
if let Some(file) = self.ice_file.as_ref()
|
||||
&& let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file)
|
||||
{
|
||||
@ -1619,25 +1548,25 @@ impl DiagCtxtInner {
|
||||
&mut out,
|
||||
"delayed span bug: {}\n{}\n",
|
||||
bug.inner
|
||||
.styled_message()
|
||||
.messages()
|
||||
.iter()
|
||||
.filter_map(|(msg, _)| msg.as_str())
|
||||
.collect::<String>(),
|
||||
&bug.note
|
||||
);
|
||||
}
|
||||
let mut bug =
|
||||
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
|
||||
|
||||
if no_bugs {
|
||||
if i == 0 {
|
||||
// Put the overall explanation before the `DelayedBug`s, to
|
||||
// frame them better (e.g. separate warnings from them).
|
||||
self.emit_diagnostic(Diagnostic::new(Bug, explanation));
|
||||
no_bugs = false;
|
||||
}
|
||||
|
||||
let mut bug =
|
||||
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
|
||||
|
||||
// "Undelay" the `DelayedBug`s (into plain `Bug`s).
|
||||
if bug.level != Level::DelayedBug {
|
||||
if bug.level != DelayedBug {
|
||||
// NOTE(eddyb) not panicking here because we're already producing
|
||||
// an ICE, and the more information the merrier.
|
||||
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
|
||||
@ -1645,15 +1574,13 @@ impl DiagCtxtInner {
|
||||
level: bug.level,
|
||||
});
|
||||
}
|
||||
bug.level = Level::Bug;
|
||||
bug.level = Bug;
|
||||
|
||||
self.emit_diagnostic(bug);
|
||||
}
|
||||
|
||||
// Panic with `DelayedBugPanic` to avoid "unexpected panic" messages.
|
||||
if !no_bugs {
|
||||
panic::panic_any(DelayedBugPanic);
|
||||
}
|
||||
panic::panic_any(DelayedBugPanic);
|
||||
}
|
||||
|
||||
fn bump_lint_err_count(&mut self) {
|
||||
@ -1731,25 +1658,80 @@ impl DelayedDiagnostic {
|
||||
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
|
||||
pub enum Level {
|
||||
/// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `BugAbort`.
|
||||
Bug,
|
||||
|
||||
/// This is a strange one: lets you register an error without emitting it. If compilation ends
|
||||
/// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be
|
||||
/// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
|
||||
/// that should only be reached when compiling erroneous code.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `ErrorGuaranteed`.
|
||||
DelayedBug,
|
||||
|
||||
/// An error that causes an immediate abort. Used for things like configuration errors,
|
||||
/// internal overflows, some file operation errors.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `FatalAbort`, except in the non-aborting "almost fatal" case
|
||||
/// that is occasionaly used, where it is `FatalError`.
|
||||
Fatal,
|
||||
|
||||
/// An error in the code being compiled, which prevents compilation from finishing. This is the
|
||||
/// most common case.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `ErrorGuaranteed`.
|
||||
Error {
|
||||
/// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
|
||||
/// If this error comes from a lint, don't abort compilation even when abort_if_errors() is
|
||||
/// called.
|
||||
lint: bool,
|
||||
},
|
||||
|
||||
/// A warning about the code being compiled. Does not prevent compilation from finishing.
|
||||
///
|
||||
/// This [`LintExpectationId`] is used for expected lint diagnostics, which should
|
||||
/// also emit a warning due to the `force-warn` flag. In all other cases this should
|
||||
/// be `None`.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
Warning(Option<LintExpectationId>),
|
||||
|
||||
/// A message giving additional context. Rare, because notes are more commonly attached to other
|
||||
/// diagnostics such as errors.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
Note,
|
||||
/// A note that is only emitted once.
|
||||
|
||||
/// A note that is only emitted once. Rare, mostly used in circumstances relating to lints.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
OnceNote,
|
||||
|
||||
/// A message suggesting how to fix something. Rare, because help messages are more commonly
|
||||
/// attached to other diagnostics such as errors.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
Help,
|
||||
/// A help that is only emitted once.
|
||||
|
||||
/// A help that is only emitted once. Rare.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
OnceHelp,
|
||||
|
||||
/// Similar to `Note`, but used in cases where compilation has failed. Rare.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
FailureNote,
|
||||
|
||||
/// Only used for lints.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
Allow,
|
||||
|
||||
/// Only used for lints.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `()`.
|
||||
Expect(LintExpectationId),
|
||||
}
|
||||
|
||||
@ -1789,8 +1771,7 @@ impl Level {
|
||||
Note | OnceNote => "note",
|
||||
Help | OnceHelp => "help",
|
||||
FailureNote => "failure-note",
|
||||
Allow => panic!("Shouldn't call on allowed error"),
|
||||
Expect(_) => panic!("Shouldn't call on expected error"),
|
||||
Allow | Expect(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1800,7 +1781,7 @@ impl Level {
|
||||
|
||||
pub fn get_expectation_id(&self) -> Option<LintExpectationId> {
|
||||
match self {
|
||||
Level::Expect(id) | Level::Warning(Some(id)) => Some(*id),
|
||||
Expect(id) | Warning(Some(id)) => Some(*id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1118,15 +1118,12 @@ impl<'a> ExtCtxt<'a> {
|
||||
&self,
|
||||
sp: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
self.sess.dcx().struct_span_err(sp, msg)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_err(
|
||||
&self,
|
||||
err: impl IntoDiagnostic<'a>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
pub fn create_err(&self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> {
|
||||
self.sess.create_err(err)
|
||||
}
|
||||
|
||||
@ -1159,6 +1156,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
// Fixme: does this result in errors?
|
||||
self.expansions.clear();
|
||||
}
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn bug(&self, msg: &'static str) -> ! {
|
||||
self.sess.dcx().bug(msg);
|
||||
}
|
||||
@ -1204,11 +1202,10 @@ pub fn resolve_path(
|
||||
.expect("attempting to resolve a file path in an external file"),
|
||||
FileName::DocTest(path, _) => path,
|
||||
other => {
|
||||
return Err(errors::ResolveRelativePath {
|
||||
return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath {
|
||||
span,
|
||||
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
|
||||
}
|
||||
.into_diagnostic(&parse_sess.dcx));
|
||||
}));
|
||||
}
|
||||
};
|
||||
result.pop();
|
||||
@ -1230,7 +1227,7 @@ pub fn expr_to_spanned_string<'a>(
|
||||
cx: &'a mut ExtCtxt<'_>,
|
||||
expr: P<ast::Expr>,
|
||||
err_msg: &'static str,
|
||||
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> {
|
||||
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> {
|
||||
// Perform eager expansion on the expression.
|
||||
// We want to be able to handle e.g., `concat!("foo", "bar")`.
|
||||
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
|
||||
|
@ -134,10 +134,13 @@ impl<'a> ExtCtxt<'a> {
|
||||
pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
|
||||
ast::GenericBound::Trait(
|
||||
self.poly_trait_ref(path.span, path),
|
||||
if is_const {
|
||||
ast::TraitBoundModifier::MaybeConst(DUMMY_SP)
|
||||
} else {
|
||||
ast::TraitBoundModifier::None
|
||||
ast::TraitBoundModifiers {
|
||||
polarity: ast::BoundPolarity::Positive,
|
||||
constness: if is_const {
|
||||
ast::BoundConstness::Maybe(DUMMY_SP)
|
||||
} else {
|
||||
ast::BoundConstness::Never
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -488,7 +491,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
path: ast::Path,
|
||||
field_pats: ThinVec<ast::PatField>,
|
||||
) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Struct(None, path, field_pats, false))
|
||||
self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
|
||||
}
|
||||
pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Tuple(pats))
|
||||
|
@ -41,132 +41,6 @@ use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::{iter, mem};
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
macro_rules! ast_fragments {
|
||||
(
|
||||
$($Kind:ident($AstTy:ty) {
|
||||
$kind_name:expr;
|
||||
$(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
|
||||
$(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
|
||||
fn $make_ast:ident;
|
||||
})*
|
||||
) => {
|
||||
/// A fragment of AST that can be produced by a single macro expansion.
|
||||
/// Can also serve as an input and intermediate result for macro expansion operations.
|
||||
pub enum AstFragment {
|
||||
OptExpr(Option<P<ast::Expr>>),
|
||||
MethodReceiverExpr(P<ast::Expr>),
|
||||
$($Kind($AstTy),)*
|
||||
}
|
||||
|
||||
/// "Discriminant" of an AST fragment.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum AstFragmentKind {
|
||||
OptExpr,
|
||||
MethodReceiverExpr,
|
||||
$($Kind,)*
|
||||
}
|
||||
|
||||
impl AstFragmentKind {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
AstFragmentKind::OptExpr => "expression",
|
||||
AstFragmentKind::MethodReceiverExpr => "expression",
|
||||
$(AstFragmentKind::$Kind => $kind_name,)*
|
||||
}
|
||||
}
|
||||
|
||||
fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
|
||||
match self {
|
||||
AstFragmentKind::OptExpr =>
|
||||
result.make_expr().map(Some).map(AstFragment::OptExpr),
|
||||
AstFragmentKind::MethodReceiverExpr =>
|
||||
result.make_expr().map(AstFragment::MethodReceiverExpr),
|
||||
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AstFragment {
|
||||
pub fn add_placeholders(&mut self, placeholders: &[NodeId]) {
|
||||
if placeholders.is_empty() {
|
||||
return;
|
||||
}
|
||||
match self {
|
||||
$($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| {
|
||||
${ignore(flat_map_ast_elt)}
|
||||
placeholder(AstFragmentKind::$Kind, *id, None).$make_ast()
|
||||
})),)?)*
|
||||
_ => panic!("unexpected AST fragment kind")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
|
||||
match self {
|
||||
AstFragment::OptExpr(expr) => expr,
|
||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_method_receiver_expr(self) -> P<ast::Expr> {
|
||||
match self {
|
||||
AstFragment::MethodReceiverExpr(expr) => expr,
|
||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||
}
|
||||
}
|
||||
|
||||
$(pub fn $make_ast(self) -> $AstTy {
|
||||
match self {
|
||||
AstFragment::$Kind(ast) => ast,
|
||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||
}
|
||||
})*
|
||||
|
||||
fn make_ast<T: InvocationCollectorNode>(self) -> T::OutputTy {
|
||||
T::fragment_to_output(self)
|
||||
}
|
||||
|
||||
pub fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
|
||||
match self {
|
||||
AstFragment::OptExpr(opt_expr) => {
|
||||
visit_clobber(opt_expr, |opt_expr| {
|
||||
if let Some(expr) = opt_expr {
|
||||
vis.filter_map_expr(expr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
}
|
||||
AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
|
||||
$($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
|
||||
$($(AstFragment::$Kind(ast) =>
|
||||
ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
|
||||
match self {
|
||||
AstFragment::OptExpr(Some(expr)) => visitor.visit_expr(expr),
|
||||
AstFragment::OptExpr(None) => {}
|
||||
AstFragment::MethodReceiverExpr(expr) => visitor.visit_method_receiver_expr(expr),
|
||||
$($(AstFragment::$Kind(ast) => visitor.$visit_ast(ast),)?)*
|
||||
$($(AstFragment::$Kind(ast) => for ast_elt in &ast[..] {
|
||||
visitor.$visit_ast_elt(ast_elt, $($args)*);
|
||||
})?)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> {
|
||||
$(fn $make_ast(self: Box<crate::mbe::macro_rules::ParserAnyMacro<'a>>)
|
||||
-> Option<$AstTy> {
|
||||
Some(self.make(AstFragmentKind::$Kind).$make_ast())
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
macro_rules! ast_fragments {
|
||||
(
|
||||
$($Kind:ident($AstTy:ty) {
|
||||
|
@ -215,7 +215,7 @@ impl<'matcher> Tracker<'matcher> for FailureForwarder {
|
||||
}
|
||||
|
||||
pub(super) fn emit_frag_parse_err(
|
||||
mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>,
|
||||
mut e: DiagnosticBuilder<'_>,
|
||||
parser: &Parser<'_>,
|
||||
orig_parser: &mut Parser<'_>,
|
||||
site_span: Span,
|
||||
@ -224,11 +224,11 @@ pub(super) fn emit_frag_parse_err(
|
||||
) {
|
||||
// FIXME(davidtwco): avoid depending on the error message text
|
||||
if parser.token == token::Eof
|
||||
&& let DiagnosticMessage::Str(message) = &e.message[0].0
|
||||
&& let DiagnosticMessage::Str(message) = &e.messages[0].0
|
||||
&& message.ends_with(", found `<eof>`")
|
||||
{
|
||||
let msg = &e.message[0];
|
||||
e.message[0] = (
|
||||
let msg = &e.messages[0];
|
||||
e.messages[0] = (
|
||||
DiagnosticMessage::from(format!(
|
||||
"macro expansion ends with an incomplete expression: {}",
|
||||
message.replace(", found `<eof>`", ""),
|
||||
|
@ -9,8 +9,8 @@ use rustc_ast::mut_visit::{self, MutVisitor};
|
||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_errors::{pluralize, PResult};
|
||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||
use rustc_span::Span;
|
||||
@ -528,7 +528,7 @@ fn out_of_bounds_err<'a>(
|
||||
max: usize,
|
||||
span: Span,
|
||||
ty: &str,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let msg = if max == 0 {
|
||||
format!(
|
||||
"meta-variable expression `{ty}` with depth parameter \
|
||||
|
@ -43,7 +43,7 @@ pub enum ModError<'a> {
|
||||
ModInBlock(Option<Ident>),
|
||||
FileNotFound(Ident, PathBuf, PathBuf),
|
||||
MultipleCandidates(Ident, PathBuf, PathBuf),
|
||||
ParserError(DiagnosticBuilder<'a, ErrorGuaranteed>),
|
||||
ParserError(DiagnosticBuilder<'a>),
|
||||
}
|
||||
|
||||
pub(crate) fn parse_external_mod(
|
||||
|
@ -499,12 +499,7 @@ impl server::FreeFunctions for Rustc<'_, '_> {
|
||||
rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message);
|
||||
diag.set_span(MultiSpan::from_spans(diagnostic.spans));
|
||||
for child in diagnostic.children {
|
||||
diag.sub(
|
||||
child.level.to_internal(),
|
||||
child.message,
|
||||
MultiSpan::from_spans(child.spans),
|
||||
None,
|
||||
);
|
||||
diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans));
|
||||
}
|
||||
self.sess().dcx.emit_diagnostic(diag);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ declare_features! (
|
||||
/// Allows empty structs and enum variants with braces.
|
||||
(accepted, braced_empty_structs, "1.8.0", Some(29720)),
|
||||
/// Allows `c"foo"` literals.
|
||||
(accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)),
|
||||
(accepted, c_str_literals, "1.76.0", Some(105723)),
|
||||
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
|
||||
(accepted, cfg_attr_multi, "1.33.0", Some(54881)),
|
||||
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
|
||||
@ -341,7 +341,7 @@ declare_features! (
|
||||
(accepted, track_caller, "1.46.0", Some(47809)),
|
||||
/// Allows dyn upcasting trait objects via supertraits.
|
||||
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
|
||||
(accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991)),
|
||||
(accepted, trait_upcasting, "1.76.0", Some(65991)),
|
||||
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
|
||||
(accepted, transparent_enums, "1.42.0", Some(60405)),
|
||||
/// Allows indexing tuples.
|
||||
|
@ -177,7 +177,7 @@ declare_features! (
|
||||
/// Allows using the `#[register_attr]` attribute.
|
||||
(removed, register_attr, "1.65.0", Some(66080),
|
||||
Some("removed in favor of `#![register_tool]`")),
|
||||
(removed, rust_2018_preview, "CURRENT_RUSTC_VERSION", None,
|
||||
(removed, rust_2018_preview, "1.76.0", None,
|
||||
Some("2018 Edition preview is no longer relevant")),
|
||||
/// Allows using the macros:
|
||||
/// + `__diagnostic_used`
|
||||
|
@ -204,7 +204,7 @@ declare_features! (
|
||||
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
|
||||
(internal, lang_items, "1.0.0", None),
|
||||
/// Changes `impl Trait` to capture all lifetimes in scope.
|
||||
(unstable, lifetime_capture_rules_2024, "CURRENT_RUSTC_VERSION", None),
|
||||
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
|
||||
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
|
||||
(unstable, link_cfg, "1.14.0", None),
|
||||
/// Allows the `multiple_supertrait_upcastable` lint.
|
||||
@ -357,6 +357,8 @@ declare_features! (
|
||||
(unstable, async_closure, "1.37.0", Some(62290)),
|
||||
/// Allows `#[track_caller]` on async functions.
|
||||
(unstable, async_fn_track_caller, "1.73.0", Some(110011)),
|
||||
/// Allows `for await` loops.
|
||||
(unstable, async_for_loop, "CURRENT_RUSTC_VERSION", Some(118898)),
|
||||
/// Allows builtin # foo() syntax
|
||||
(unstable, builtin_syntax, "1.71.0", Some(110680)),
|
||||
/// Treat `extern "C"` function as nounwind.
|
||||
@ -468,7 +470,7 @@ declare_features! (
|
||||
/// Allows using `#[repr(align(...))]` on function items
|
||||
(unstable, fn_align, "1.53.0", Some(82232)),
|
||||
/// Support delegating implementation of functions to other already implemented functions.
|
||||
(incomplete, fn_delegation, "CURRENT_RUSTC_VERSION", Some(118212)),
|
||||
(incomplete, fn_delegation, "1.76.0", Some(118212)),
|
||||
/// Allows defining gen blocks and `gen fn`.
|
||||
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
||||
/// Infer generic args for both consts and types.
|
||||
@ -505,7 +507,7 @@ declare_features! (
|
||||
(unstable, let_chains, "1.37.0", Some(53667)),
|
||||
/// Allows using `#[link(kind = "link-arg", name = "...")]`
|
||||
/// to pass custom arguments to the linker.
|
||||
(unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427)),
|
||||
(unstable, link_arg_attribute, "1.76.0", Some(99427)),
|
||||
/// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
|
||||
(unstable, lint_reasons, "1.31.0", Some(54503)),
|
||||
/// Give access to additional metadata about declarative macro meta-variables.
|
||||
@ -527,7 +529,7 @@ declare_features! (
|
||||
/// Allow negative trait implementations.
|
||||
(unstable, negative_impls, "1.44.0", Some(68318)),
|
||||
/// Allows the `!` pattern.
|
||||
(incomplete, never_patterns, "CURRENT_RUSTC_VERSION", Some(118155)),
|
||||
(incomplete, never_patterns, "1.76.0", Some(118155)),
|
||||
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
|
||||
(unstable, never_type, "1.13.0", Some(35121)),
|
||||
/// Allows diverging expressions to fall back to `!` rather than `()`.
|
||||
|
@ -417,8 +417,7 @@ pub enum GenericArgsParentheses {
|
||||
ParenSugar,
|
||||
}
|
||||
|
||||
/// A modifier on a bound, currently this is only used for `?Sized`, where the
|
||||
/// modifier is `Maybe`. Negative bounds should also be handled here.
|
||||
/// A modifier on a trait bound.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub enum TraitBoundModifier {
|
||||
None,
|
||||
@ -1352,15 +1351,8 @@ impl<'hir> Body<'hir> {
|
||||
/// The type of source expression that caused this coroutine to be created.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
|
||||
pub enum CoroutineKind {
|
||||
/// An explicit `async` block or the body of an `async` function.
|
||||
Async(CoroutineSource),
|
||||
|
||||
/// An explicit `gen` block or the body of a `gen` function.
|
||||
Gen(CoroutineSource),
|
||||
|
||||
/// An explicit `async gen` block or the body of an `async gen` function,
|
||||
/// which is able to both `yield` and `.await`.
|
||||
AsyncGen(CoroutineSource),
|
||||
/// A coroutine that comes from a desugaring.
|
||||
Desugared(CoroutineDesugaring, CoroutineSource),
|
||||
|
||||
/// A coroutine literal created via a `yield` inside a closure.
|
||||
Coroutine,
|
||||
@ -1369,31 +1361,11 @@ pub enum CoroutineKind {
|
||||
impl fmt::Display for CoroutineKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
CoroutineKind::Async(k) => {
|
||||
if f.alternate() {
|
||||
f.write_str("`async` ")?;
|
||||
} else {
|
||||
f.write_str("async ")?
|
||||
}
|
||||
CoroutineKind::Desugared(d, k) => {
|
||||
d.fmt(f)?;
|
||||
k.fmt(f)
|
||||
}
|
||||
CoroutineKind::Coroutine => f.write_str("coroutine"),
|
||||
CoroutineKind::Gen(k) => {
|
||||
if f.alternate() {
|
||||
f.write_str("`gen` ")?;
|
||||
} else {
|
||||
f.write_str("gen ")?
|
||||
}
|
||||
k.fmt(f)
|
||||
}
|
||||
CoroutineKind::AsyncGen(k) => {
|
||||
if f.alternate() {
|
||||
f.write_str("`async gen` ")?;
|
||||
} else {
|
||||
f.write_str("async gen ")?
|
||||
}
|
||||
k.fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1426,6 +1398,49 @@ impl fmt::Display for CoroutineSource {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
|
||||
pub enum CoroutineDesugaring {
|
||||
/// An explicit `async` block or the body of an `async` function.
|
||||
Async,
|
||||
|
||||
/// An explicit `gen` block or the body of a `gen` function.
|
||||
Gen,
|
||||
|
||||
/// An explicit `async gen` block or the body of an `async gen` function,
|
||||
/// which is able to both `yield` and `.await`.
|
||||
AsyncGen,
|
||||
}
|
||||
|
||||
impl fmt::Display for CoroutineDesugaring {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
CoroutineDesugaring::Async => {
|
||||
if f.alternate() {
|
||||
f.write_str("`async` ")?;
|
||||
} else {
|
||||
f.write_str("async ")?
|
||||
}
|
||||
}
|
||||
CoroutineDesugaring::Gen => {
|
||||
if f.alternate() {
|
||||
f.write_str("`gen` ")?;
|
||||
} else {
|
||||
f.write_str("gen ")?
|
||||
}
|
||||
}
|
||||
CoroutineDesugaring::AsyncGen => {
|
||||
if f.alternate() {
|
||||
f.write_str("`async gen` ")?;
|
||||
} else {
|
||||
f.write_str("async gen ")?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum BodyOwnerKind {
|
||||
/// Functions and methods.
|
||||
|
@ -307,6 +307,9 @@ language_item_table! {
|
||||
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
|
||||
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
AsyncIteratorPollNext, sym::async_iterator_poll_next, async_iterator_poll_next, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
|
||||
IntoAsyncIterIntoIter, sym::into_async_iter_into_iter, into_async_iter_into_iter, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
|
||||
|
||||
Option, sym::Option, option_type, Target::Enum, GenericRequirement::None;
|
||||
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
|
||||
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
|
||||
|
@ -378,7 +378,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
assert!(self_ty.is_none());
|
||||
}
|
||||
|
||||
let arg_count = check_generic_arg_count(
|
||||
let mut arg_count = check_generic_arg_count(
|
||||
tcx,
|
||||
span,
|
||||
def_id,
|
||||
@ -560,6 +560,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
inferred_params: vec![],
|
||||
infer_args,
|
||||
};
|
||||
if let ty::BoundConstness::ConstIfConst = constness
|
||||
&& generics.has_self
|
||||
&& !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
let e = tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span });
|
||||
arg_count.correct =
|
||||
Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
|
||||
}
|
||||
let args = create_args_for_parent_generic_args(
|
||||
tcx,
|
||||
def_id,
|
||||
@ -570,13 +578,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
&mut args_ctx,
|
||||
);
|
||||
|
||||
if let ty::BoundConstness::ConstIfConst = constness
|
||||
&& generics.has_self
|
||||
&& !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span });
|
||||
}
|
||||
|
||||
(args, arg_count)
|
||||
}
|
||||
|
||||
@ -2686,7 +2687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
&self,
|
||||
constrained_regions: FxHashSet<ty::BoundRegionKind>,
|
||||
referenced_regions: FxHashSet<ty::BoundRegionKind>,
|
||||
generate_err: impl Fn(&str) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
generate_err: impl Fn(&str) -> DiagnosticBuilder<'tcx>,
|
||||
) {
|
||||
for br in referenced_regions.difference(&constrained_regions) {
|
||||
let br_name = match *br {
|
||||
|
@ -124,7 +124,10 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
if let Some(term_did) = tcx.lang_items().termination() {
|
||||
let return_ty = main_fnsig.output();
|
||||
let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
|
||||
let return_ty = return_ty.skip_binder();
|
||||
let Some(return_ty) = return_ty.no_bound_vars() else {
|
||||
tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
|
||||
return;
|
||||
};
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let cause = traits::ObligationCause::new(
|
||||
return_ty_span,
|
||||
|
@ -1912,11 +1912,7 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
|
||||
res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)))
|
||||
}
|
||||
|
||||
fn error_392(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
param_name: Symbol,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> {
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{param_name}` is never used");
|
||||
err.span_label(span, "unused parameter");
|
||||
err
|
||||
|
@ -181,7 +181,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>(
|
||||
suggest: bool,
|
||||
hir_ty: Option<&hir::Ty<'_>>,
|
||||
kind: &'static str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
if placeholder_types.is_empty() {
|
||||
return bad_placeholder(tcx, additional_spans, kind);
|
||||
}
|
||||
@ -333,7 +333,7 @@ fn bad_placeholder<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut spans: Vec<Span>,
|
||||
kind: &'static str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") };
|
||||
|
||||
spans.sort();
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
||||
MultiSpan,
|
||||
error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
Level, MultiSpan,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
@ -315,14 +315,12 @@ pub struct MissingTypeParams {
|
||||
}
|
||||
|
||||
// Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`.
|
||||
impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
|
||||
#[track_caller]
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut err = dcx.struct_span_err_with_code(
|
||||
self.span,
|
||||
fluent::hir_analysis_missing_type_params,
|
||||
error_code!(E0393),
|
||||
);
|
||||
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||
let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params);
|
||||
err.set_span(self.span);
|
||||
err.code(error_code!(E0393));
|
||||
err.set_arg("parameterCount", self.missing_type_params.len());
|
||||
err.set_arg(
|
||||
"parameters",
|
||||
|
@ -4,7 +4,6 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
mod explicit;
|
||||
@ -49,25 +48,6 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
|
||||
let predicates =
|
||||
crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
|
||||
|
||||
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
|
||||
let mut pred: Vec<String> = predicates
|
||||
.iter()
|
||||
.map(|(out_pred, _)| match out_pred.kind().skip_binder() {
|
||||
ty::ClauseKind::RegionOutlives(p) => p.to_string(),
|
||||
ty::ClauseKind::TypeOutlives(p) => p.to_string(),
|
||||
err => bug!("unexpected clause {:?}", err),
|
||||
})
|
||||
.collect();
|
||||
pred.sort();
|
||||
|
||||
let span = tcx.def_span(item_def_id);
|
||||
let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
|
||||
for p in pred {
|
||||
err.note(p);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
|
||||
|
||||
predicates
|
||||
|
@ -1,5 +1,4 @@
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
|
||||
@ -7,15 +6,23 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
|
||||
// For unit testing: check for a special "rustc_outlives"
|
||||
// attribute and report an error with various results if found.
|
||||
if tcx.has_attr(id.owner_id, sym::rustc_outlives) {
|
||||
let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id);
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
tcx.def_span(id.owner_id),
|
||||
E0640,
|
||||
"{:?}",
|
||||
inferred_outlives_of
|
||||
)
|
||||
.emit();
|
||||
let predicates = tcx.inferred_outlives_of(id.owner_id);
|
||||
let mut pred: Vec<String> = predicates
|
||||
.iter()
|
||||
.map(|(out_pred, _)| match out_pred.kind().skip_binder() {
|
||||
ty::ClauseKind::RegionOutlives(p) => p.to_string(),
|
||||
ty::ClauseKind::TypeOutlives(p) => p.to_string(),
|
||||
err => bug!("unexpected clause {:?}", err),
|
||||
})
|
||||
.collect();
|
||||
pred.sort();
|
||||
|
||||
let span = tcx.def_span(id.owner_id);
|
||||
let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
|
||||
for p in pred {
|
||||
err.note(p);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ pub use self::{
|
||||
missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
|
||||
};
|
||||
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc_session::Session;
|
||||
|
||||
pub trait StructuredDiagnostic<'tcx> {
|
||||
@ -14,7 +14,7 @@ pub trait StructuredDiagnostic<'tcx> {
|
||||
|
||||
fn code(&self) -> DiagnosticId;
|
||||
|
||||
fn diagnostic(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let err = self.diagnostic_common();
|
||||
|
||||
if self.session().teach(&self.code()) {
|
||||
@ -24,19 +24,13 @@ pub trait StructuredDiagnostic<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx>;
|
||||
|
||||
fn diagnostic_regular(
|
||||
&self,
|
||||
err: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
||||
err
|
||||
}
|
||||
|
||||
fn diagnostic_extended(
|
||||
&self,
|
||||
err: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
||||
err
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{errors, structured_errors::StructuredDiagnostic};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc_middle::ty::{Ty, TypeVisitableExt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
@ -20,7 +20,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
|
||||
rustc_errors::error_code!(E0617)
|
||||
}
|
||||
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let (sugg_span, replace, help) =
|
||||
if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
|
||||
(Some(self.span), format!("{} as {}", snippet, self.cast_ty), None)
|
||||
@ -44,10 +44,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
|
||||
err
|
||||
}
|
||||
|
||||
fn diagnostic_extended(
|
||||
&self,
|
||||
mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
||||
err.note(format!(
|
||||
"certain types, like `{}`, must be casted before passing them to a \
|
||||
variadic function, because of arcane ABI rules dictated by the C \
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{errors, structured_errors::StructuredDiagnostic};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc_middle::ty::{Ty, TypeVisitableExt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
@ -20,7 +20,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
|
||||
rustc_errors::error_code!(E0607)
|
||||
}
|
||||
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = self.sess.create_err(errors::CastThinPointerToFatPointer {
|
||||
span: self.span,
|
||||
expr_ty: self.expr_ty,
|
||||
@ -34,10 +34,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
|
||||
err
|
||||
}
|
||||
|
||||
fn diagnostic_extended(
|
||||
&self,
|
||||
mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> {
|
||||
err.help(
|
||||
"Thin pointers are \"simple\" pointers: they are purely a reference to a
|
||||
memory address.
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::structured_errors::StructuredDiagnostic;
|
||||
use rustc_errors::{
|
||||
pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed,
|
||||
MultiSpan,
|
||||
pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
|
||||
@ -521,7 +520,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let span = self.path_segment.ident.span;
|
||||
let msg = self.create_error_message();
|
||||
|
||||
@ -1113,7 +1112,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
|
||||
rustc_errors::error_code!(E0107)
|
||||
}
|
||||
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = self.start_diagnostics();
|
||||
|
||||
self.notify(&mut err);
|
||||
|
@ -553,17 +553,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
hir::ItemKind::OpaqueTy(opaque_ty) => {
|
||||
self.print_item_type(item, opaque_ty.generics, |state| {
|
||||
let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len());
|
||||
for b in opaque_ty.bounds {
|
||||
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
|
||||
state.space();
|
||||
state.word_space("for ?");
|
||||
state.print_trait_ref(&ptr.trait_ref);
|
||||
} else {
|
||||
real_bounds.push(b);
|
||||
}
|
||||
}
|
||||
state.print_bounds("= impl", real_bounds);
|
||||
state.print_bounds("= impl", opaque_ty.bounds)
|
||||
});
|
||||
}
|
||||
hir::ItemKind::Enum(ref enum_definition, params) => {
|
||||
@ -625,17 +615,7 @@ impl<'a> State<'a> {
|
||||
self.word_nbsp("trait");
|
||||
self.print_ident(item.ident);
|
||||
self.print_generic_params(generics.params);
|
||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
for b in bounds {
|
||||
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
|
||||
self.space();
|
||||
self.word_space("for ?");
|
||||
self.print_trait_ref(&ptr.trait_ref);
|
||||
} else {
|
||||
real_bounds.push(b);
|
||||
}
|
||||
}
|
||||
self.print_bounds(":", real_bounds);
|
||||
self.print_bounds(":", bounds);
|
||||
self.print_where_clause(generics);
|
||||
self.word(" ");
|
||||
self.bopen();
|
||||
|
@ -305,8 +305,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
) = (parent_node, callee_node)
|
||||
{
|
||||
let fn_decl_span = if hir.body(body).coroutine_kind
|
||||
== Some(hir::CoroutineKind::Async(hir::CoroutineSource::Closure))
|
||||
{
|
||||
== Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Closure,
|
||||
)) {
|
||||
// Actually need to unwrap one more layer of HIR to get to
|
||||
// the _real_ closure...
|
||||
let async_closure = hir.parent_id(parent_hir_id);
|
||||
|
@ -187,7 +187,7 @@ fn make_invalid_casting_error<'a, 'tcx>(
|
||||
expr_ty: Ty<'tcx>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
type_error_struct!(
|
||||
sess,
|
||||
span,
|
||||
|
@ -59,7 +59,8 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
&& can_be_coroutine.is_some()
|
||||
{
|
||||
let yield_ty = match kind {
|
||||
hir::CoroutineKind::Gen(..) | hir::CoroutineKind::Coroutine => {
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
| hir::CoroutineKind::Coroutine => {
|
||||
let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span,
|
||||
@ -71,7 +72,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
// guide inference on the yield type so that we can handle `AsyncIterator`
|
||||
// in this block in projection correctly. In the new trait solver, it is
|
||||
// not a problem.
|
||||
hir::CoroutineKind::AsyncGen(..) => {
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
|
||||
let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span,
|
||||
@ -89,7 +90,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
.into()]),
|
||||
)
|
||||
}
|
||||
hir::CoroutineKind::Async(..) => Ty::new_unit(tcx),
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => Ty::new_unit(tcx),
|
||||
};
|
||||
|
||||
// Resume type defaults to `()` if the coroutine has no argument.
|
||||
|
@ -634,7 +634,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// In the case of the async block that we create for a function body,
|
||||
// we expect the return type of the block to match that of the enclosing
|
||||
// function.
|
||||
Some(hir::CoroutineKind::Async(hir::CoroutineSource::Fn)) => {
|
||||
Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Fn,
|
||||
)) => {
|
||||
debug!("closure is async fn body");
|
||||
let def_id = self.tcx.hir().body_owner_def_id(body.id());
|
||||
self.deduce_future_output_from_obligations(expr_def_id, def_id).unwrap_or_else(
|
||||
@ -651,9 +654,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
)
|
||||
}
|
||||
// All `gen {}` and `async gen {}` must return unit.
|
||||
Some(hir::CoroutineKind::Gen(_) | hir::CoroutineKind::AsyncGen(_)) => {
|
||||
self.tcx.types.unit
|
||||
}
|
||||
Some(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
|
||||
) => self.tcx.types.unit,
|
||||
|
||||
_ => astconv.ty_infer(None, decl.output.span()),
|
||||
},
|
||||
|
@ -36,9 +36,7 @@
|
||||
//! ```
|
||||
|
||||
use crate::FnCtxt;
|
||||
use rustc_errors::{
|
||||
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
@ -1772,7 +1770,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
id: hir::HirId,
|
||||
expression: Option<&'tcx hir::Expr<'tcx>>,
|
||||
blk_id: Option<hir::HirId>,
|
||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);
|
||||
|
||||
let parent_id = fcx.tcx.hir().parent_id(id);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::FnCtxt;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
@ -168,7 +168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
@ -199,7 +199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected: Ty<'tcx>,
|
||||
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) {
|
||||
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
|
||||
let expected = self.resolve_vars_with_obligations(expected);
|
||||
|
||||
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
|
||||
|
@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let [segment] = path.segments
|
||||
&& segment.ident.name == sym::rust
|
||||
{
|
||||
fatally_break_rust(self.tcx);
|
||||
fatally_break_rust(self.tcx, expr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -966,7 +966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn check_for_missing_semi(
|
||||
&self,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
) -> bool {
|
||||
if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind
|
||||
&& let hir::BinOpKind::Mul = binop.node
|
||||
@ -2738,7 +2738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
field: Ident,
|
||||
expr_t: Ty<'tcx>,
|
||||
id: HirId,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let span = field.span;
|
||||
debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t);
|
||||
|
||||
@ -2821,11 +2821,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
err
|
||||
}
|
||||
|
||||
fn private_field_err(
|
||||
&self,
|
||||
field: Ident,
|
||||
base_did: DefId,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
fn private_field_err(&self, field: Ident, base_did: DefId) -> DiagnosticBuilder<'_> {
|
||||
let struct_path = self.tcx().def_path_str(base_did);
|
||||
let kind_name = self.tcx().def_descr(base_did);
|
||||
let mut err = struct_span_err!(
|
||||
|
@ -1258,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected_ty: Ty<'tcx>,
|
||||
provided_ty: Ty<'tcx>,
|
||||
arg: &hir::Expr<'tcx>,
|
||||
err: &mut rustc_errors::DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
err: &mut rustc_errors::DiagnosticBuilder<'tcx>,
|
||||
) {
|
||||
if let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Mut, .. }) = expected_ty.kind()
|
||||
&& let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, .. }) =
|
||||
|
@ -17,8 +17,8 @@ use rustc_hir::def::Res;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath, Stmt,
|
||||
StmtKind, TyKind, WherePredicate,
|
||||
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
|
||||
Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
|
||||
};
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::traits::{self, StatementAsExpression};
|
||||
@ -549,7 +549,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::Coroutine(def_id, ..)
|
||||
if matches!(
|
||||
self.tcx.coroutine_kind(def_id),
|
||||
Some(CoroutineKind::Async(CoroutineSource::Closure))
|
||||
Some(CoroutineKind::Desugared(
|
||||
CoroutineDesugaring::Async,
|
||||
CoroutineSource::Closure
|
||||
))
|
||||
) =>
|
||||
{
|
||||
errors::SuggestBoxing::AsyncBody
|
||||
|
@ -52,7 +52,7 @@ use crate::expectation::Expectation;
|
||||
use crate::fn_ctxt::RawTy;
|
||||
use crate::gather_locals::GatherLocalsVisitor;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
@ -412,24 +412,25 @@ enum TupleArgumentsFlag {
|
||||
TupleArguments,
|
||||
}
|
||||
|
||||
fn fatally_break_rust(tcx: TyCtxt<'_>) {
|
||||
fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
|
||||
let dcx = tcx.sess.dcx();
|
||||
dcx.span_bug_no_panic(
|
||||
MultiSpan::new(),
|
||||
let mut diag = dcx.struct_span_bug(
|
||||
span,
|
||||
"It looks like you're trying to break rust; would you like some ICE?",
|
||||
);
|
||||
dcx.note("the compiler expectedly panicked. this is a feature.");
|
||||
dcx.note(
|
||||
diag.note("the compiler expectedly panicked. this is a feature.");
|
||||
diag.note(
|
||||
"we would appreciate a joke overview: \
|
||||
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
|
||||
);
|
||||
dcx.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),));
|
||||
diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),));
|
||||
if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() {
|
||||
dcx.note(format!("compiler flags: {}", flags.join(" ")));
|
||||
diag.note(format!("compiler flags: {}", flags.join(" ")));
|
||||
if excluded_cargo_defaults {
|
||||
dcx.note("some of the compiler flags provided by cargo are hidden");
|
||||
diag.note("some of the compiler flags provided by cargo are hidden");
|
||||
}
|
||||
}
|
||||
diag.emit()
|
||||
}
|
||||
|
||||
/// `expected` here is the expected number of explicit generic arguments on the trait.
|
||||
|
@ -13,8 +13,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::StashKey;
|
||||
use rustc_errors::{
|
||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||
MultiSpan,
|
||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
@ -120,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
expected: Expectation<'tcx>,
|
||||
trait_missing_method: bool,
|
||||
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'_>> {
|
||||
// Avoid suggestions when we don't know what's going on.
|
||||
if rcvr_ty.references_error() {
|
||||
return None;
|
||||
@ -261,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
rcvr_expr: &hir::Expr<'tcx>,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
let mut file = None;
|
||||
let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file);
|
||||
let mut err = struct_span_err!(
|
||||
@ -299,7 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
no_match_data: &mut NoMatchData<'tcx>,
|
||||
expected: Expectation<'tcx>,
|
||||
trait_missing_method: bool,
|
||||
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'_>> {
|
||||
let mode = no_match_data.mode;
|
||||
let tcx = self.tcx;
|
||||
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
|
||||
|
@ -99,7 +99,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
let mut diag =
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
|
||||
if let Some(expr) = ti.origin_expr {
|
||||
@ -967,7 +967,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
fn emit_bad_pat_path(
|
||||
&self,
|
||||
mut e: DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
mut e: DiagnosticBuilder<'_>,
|
||||
pat: &hir::Pat<'tcx>,
|
||||
res: Res,
|
||||
pat_res: Res,
|
||||
@ -1508,7 +1508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
variant: &VariantDef,
|
||||
pat: &'_ Pat<'_>,
|
||||
fields: &[hir::PatField<'_>],
|
||||
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'_>> {
|
||||
// if this is a tuple struct, then all field names will be numbers
|
||||
// so if any fields in a struct pattern use shorthand syntax, they will
|
||||
// be invalid identifiers (for example, Foo { 0, 1 }).
|
||||
@ -1584,7 +1584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
variant: &ty::VariantDef,
|
||||
args: &'tcx ty::List<ty::GenericArg<'tcx>>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let (field_names, t, plural) = if let [field] = inexistent_fields {
|
||||
(format!("a field named `{}`", field.ident), "this", "")
|
||||
@ -1689,7 +1689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pat: &Pat<'_>,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
variant: &ty::VariantDef,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
|
||||
(variant.ctor_kind(), &pat.kind)
|
||||
{
|
||||
@ -1775,7 +1775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
pat: &Pat<'_>,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let mut err = self
|
||||
.tcx
|
||||
.sess
|
||||
@ -1867,7 +1867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
unmentioned_fields: &[(&ty::FieldDef, Ident)],
|
||||
have_inaccessible_fields: bool,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
|
||||
let field_names = if let [(_, field)] = unmentioned_fields {
|
||||
format!("field `{field}`{inaccessible}")
|
||||
|
@ -502,6 +502,7 @@ impl<T: Idx> ChunkedBitSet<T> {
|
||||
};
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
let mut words = {
|
||||
// FIXME: unconditionally use `Rc::new_zeroed` once it is stable (#63291).
|
||||
let words = mem::MaybeUninit::<[Word; CHUNK_WORDS]>::zeroed();
|
||||
// SAFETY: `words` can safely be all zeroes.
|
||||
let words = unsafe { words.assume_init() };
|
||||
@ -567,6 +568,7 @@ impl<T: Idx> ChunkedBitSet<T> {
|
||||
};
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
let mut words = {
|
||||
// FIXME: unconditionally use `Rc::new_zeroed` once it is stable (#63291).
|
||||
let words = mem::MaybeUninit::<[Word; CHUNK_WORDS]>::zeroed();
|
||||
// SAFETY: `words` can safely be all zeroes.
|
||||
let words = unsafe { words.assume_init() };
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user