Auto merge of #108488 - matthiaskrgr:rollup-i61epcw, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #107941 (Treat `str` as containing `[u8]` for auto trait purposes)
 - #108299 (Require `literal`s for some `(u)int_impl!` parameters)
 - #108337 (hir-analysis: make a helpful note)
 - #108379 (Add `ErrorGuaranteed` to `hir::{Expr,Ty}Kind::Err` variants)
 - #108418 (Replace parse_[sth]_expr with parse_expr_[sth] function names)
 - #108424 (rustc_infer: Consolidate obligation elaboration de-duplication)
 - #108475 (Fix `VecDeque::shrink_to` and add tests.)
 - #108482 (statically guarantee that current error codes are documented)
 - #108484 (Remove `from` lang item)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-02-26 12:40:05 +00:00
commit c4e0cd9660
62 changed files with 492 additions and 427 deletions

View File

@ -1445,6 +1445,7 @@ name = "error_index_generator"
version = "0.0.0"
dependencies = [
"mdbook",
"rustc_error_codes",
]
[[package]]

View File

@ -88,8 +88,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
} else {
self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
hir::ExprKind::Err
let guar = self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
hir::ExprKind::Err(guar)
}
} else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
@ -266,8 +266,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
}
ExprKind::Underscore => {
self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
hir::ExprKind::Err
let guar = self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
hir::ExprKind::Err(guar)
}
ExprKind::Path(qself, path) => {
let qpath = self.lower_qpath(
@ -299,8 +299,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let rest = match &se.rest {
StructRest::Base(e) => Some(self.lower_expr(e)),
StructRest::Rest(sp) => {
self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
Some(&*self.arena.alloc(self.expr_err(*sp)))
let guar =
self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
Some(&*self.arena.alloc(self.expr_err(*sp, guar)))
}
StructRest::None => None,
};
@ -318,7 +319,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
ExprKind::Err => hir::ExprKind::Err,
ExprKind::Err => hir::ExprKind::Err(
self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"),
),
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
@ -761,7 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr_ident_mut(span, task_context_ident, task_context_hid)
} else {
// Use of `await` outside of an async context, we cannot use `task_context` here.
self.expr_err(span)
self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id"))
};
let new_unchecked = self.expr_call_lang_item_fn_mut(
span,

View File

@ -102,7 +102,12 @@ fn make_count<'hir>(
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]);
ctx.expr_call_mut(sp, count_param, value)
} else {
ctx.expr(sp, hir::ExprKind::Err)
ctx.expr(
sp,
hir::ExprKind::Err(
ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"),
),
)
}
}
None => ctx.expr_lang_item_type_relative(sp, hir::LangItem::FormatCount, sym::Implied),
@ -135,7 +140,10 @@ fn make_format_spec<'hir>(
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
ctx.expr_usize(sp, i)
}
Err(_) => ctx.expr(sp, hir::ExprKind::Err),
Err(_) => ctx.expr(
sp,
hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")),
),
};
let &FormatOptions {
ref width,
@ -294,7 +302,12 @@ fn expand_format_args<'hir>(
));
make_argument(ctx, sp, arg, ty)
} else {
ctx.expr(macsp, hir::ExprKind::Err)
ctx.expr(
macsp,
hir::ExprKind::Err(
ctx.tcx.sess.delay_span_bug(macsp, format!("no arg at {arg_index}")),
),
)
}
}));
let elements: Vec<_> = arguments

View File

@ -7,6 +7,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@ -284,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
},
ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: Some(ty), .. }) => {
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
// We lower
//
// type Foo = impl Trait
@ -299,18 +300,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
&generics,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
);
hir::ItemKind::TyAlias(ty, generics)
}
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
let (generics, ty) = self.lower_generics(
&generics,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.arena.alloc(this.ty(span, hir::TyKind::Err)),
|this| match ty {
None => {
let guar = this.tcx.sess.delay_span_bug(
span,
"expected to lower type alias type, but it was missing",
);
this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
}
Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
},
);
hir::ItemKind::TyAlias(ty, generics)
}
@ -798,8 +797,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
/// Construct `ExprKind::Err` for the given `span`.
pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::Err)
pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::Err(guar))
}
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
@ -847,7 +846,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
None => {
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
let guar = this.tcx.sess.delay_span_bug(
i.span,
"expected to lower associated type, but it was missing",
);
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
hir::ImplItemKind::Type(ty)
}
Some(ty) => {
@ -973,7 +976,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
match block {
Some(block) => self.lower_block_expr(block),
None => self.expr_err(span),
None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")),
}
}
@ -983,7 +986,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&[],
match expr {
Some(expr) => this.lower_expr_mut(expr),
None => this.expr_err(span),
None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")),
},
)
})

View File

@ -1082,11 +1082,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TypeBindingKind::Constraint { bounds }
}
DesugarKind::Error(position) => {
self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
let guar = self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
span: constraint.span,
position: DiagnosticArgFromDisplay(position),
});
let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err));
let err_ty =
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
hir::TypeBindingKind::Equality { term: err_ty.into() }
}
}
@ -1255,7 +1256,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
let kind = match &t.kind {
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err => hir::TyKind::Err,
TyKind::Err => {
hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered"))
}
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Ref(region, mt) => {
@ -1381,7 +1384,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path
}
ImplTraitContext::FeatureGated(position, feature) => {
self.tcx
let guar = self
.tcx
.sess
.create_feature_err(
MisplacedImplTrait {
@ -1391,24 +1395,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
*feature,
)
.emit();
hir::TyKind::Err
hir::TyKind::Err(guar)
}
ImplTraitContext::Disallowed(position) => {
self.tcx.sess.emit_err(MisplacedImplTrait {
let guar = self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span,
position: DiagnosticArgFromDisplay(position),
});
hir::TyKind::Err
hir::TyKind::Err(guar)
}
}
}
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
TyKind::CVarArgs => {
self.tcx.sess.delay_span_bug(
let guar = self.tcx.sess.delay_span_bug(
t.span,
"`TyKind::CVarArgs` should have been handled elsewhere",
);
hir::TyKind::Err
hir::TyKind::Err(guar)
}
};

View File

@ -330,8 +330,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Path(..) if allow_paths => {}
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
_ => {
self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
return self.arena.alloc(self.expr_err(expr.span));
let guar = self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
return self.arena.alloc(self.expr_err(expr.span, guar));
}
}
self.lower_expr(expr)

View File

@ -152,7 +152,7 @@ pub fn parse_asm_args<'a>(
ast::InlineAsmOperand::InOut { reg, expr, late: true }
}
} else if p.eat_keyword(kw::Const) {
let anon_const = p.parse_anon_const_expr()?;
let anon_const = p.parse_expr_anon_const()?;
ast::InlineAsmOperand::Const { anon_const }
} else if p.eat_keyword(sym::sym) {
let expr = p.parse_expr()?;

View File

@ -485,7 +485,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
let normalised =
if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
match registry.try_find_description(&normalised) {
Ok(Some(description)) => {
Ok(description) => {
let mut is_in_code_block = false;
let mut text = String::new();
// Slice off the leading newline and print.
@ -509,9 +509,6 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
print!("{text}");
}
}
Ok(None) => {
early_error(output, &format!("no extended information for {code}"));
}
Err(InvalidErrorCode) => {
early_error(output, &format!("{code} is not a valid error code"));
}

View File

@ -513,7 +513,9 @@ E0790: include_str!("./error_codes/E0790.md"),
E0791: include_str!("./error_codes/E0791.md"),
E0792: include_str!("./error_codes/E0792.md"),
E0793: include_str!("./error_codes/E0793.md"),
;
}
// Undocumented removed error codes. Note that many removed error codes are documented.
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
// E0019, // merged into E0015
@ -570,7 +572,7 @@ E0793: include_str!("./error_codes/E0793.md"),
// E0246, // invalid recursive type
// E0247,
// E0248, // value used as a type, now reported earlier during resolution
// as E0412
// // as E0412
// E0249,
// E0257,
// E0258,
@ -631,14 +633,14 @@ E0793: include_str!("./error_codes/E0793.md"),
// E0558, // replaced with a generic attribute input check
// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
// E0564, // only named lifetimes are allowed in `impl Trait`,
// but `{}` was found in the type `{}`
// // but `{}` was found in the type `{}`
// E0598, // lifetime of {} is too short to guarantee its contents can be...
// E0611, // merged into E0616
// E0612, // merged into E0609
// E0613, // Removed (merged with E0609)
// E0629, // missing 'feature' (rustc_const_unstable)
// E0630, // rustc_const_unstable attribute must be paired with stable/unstable
// attribute
// // attribute
// E0645, // trait aliases not finished
// E0694, // an unknown tool name found in scoped attributes
// E0702, // replaced with a generic attribute input check
@ -647,4 +649,3 @@ E0793: include_str!("./error_codes/E0793.md"),
// E0721, // `await` keyword
// E0723, // unstable feature in `const` context
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
}

View File

@ -5,10 +5,9 @@
//! the goal being to make their maintenance easier.
macro_rules! register_diagnostics {
($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[
$( (stringify!($ecode), Some($message)), )*
$( (stringify!($code), None), )*
($($ecode:ident: $message:expr,)*) => (
pub static DIAGNOSTICS: &[(&str, &str)] = &[
$( (stringify!($ecode), $message), )*
];
)
}

View File

@ -580,7 +580,7 @@ impl DiagnosticCode {
let je_result =
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
DiagnosticCode { code: s, explanation: je_result.unwrap_or(None) }
DiagnosticCode { code: s, explanation: je_result.ok() }
})
}
}

View File

@ -42,7 +42,7 @@ pub use rustc_error_messages::{
pub use rustc_lint_defs::{pluralize, Applicability};
use rustc_macros::fluent_messages;
use rustc_span::source_map::SourceMap;
use rustc_span::HashStableContext;
pub use rustc_span::ErrorGuaranteed;
use rustc_span::{Loc, Span};
use std::borrow::Cow;
@ -1477,9 +1477,7 @@ impl HandlerInner {
.emitted_diagnostic_codes
.iter()
.filter_map(|x| match &x {
DiagnosticId::Error(s)
if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
{
DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => {
Some(s.clone())
}
_ => None,
@ -1846,17 +1844,3 @@ pub enum TerminalUrl {
Yes,
Auto,
}
/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(HashStable_Generic)]
pub struct ErrorGuaranteed(());
impl ErrorGuaranteed {
/// To be used only if you really know what you are doing... ideally, we would find a way to
/// eliminate all calls to this method.
pub fn unchecked_claim_error_was_emitted() -> Self {
ErrorGuaranteed(())
}
}

View File

@ -5,21 +5,17 @@ pub struct InvalidErrorCode;
#[derive(Clone)]
pub struct Registry {
long_descriptions: FxHashMap<&'static str, Option<&'static str>>,
long_descriptions: FxHashMap<&'static str, &'static str>,
}
impl Registry {
pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
Registry { long_descriptions: long_descriptions.iter().copied().collect() }
}
/// Returns `InvalidErrorCode` if the code requested does not exist in the
/// registry. Otherwise, returns an `Option` where `None` means the error
/// code is valid but has no extended information.
pub fn try_find_description(
&self,
code: &str,
) -> Result<Option<&'static str>, InvalidErrorCode> {
/// registry.
pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
}
}

View File

@ -369,10 +369,10 @@ impl<'hir> GenericArgs<'hir> {
pub fn has_err(&self) -> bool {
self.args.iter().any(|arg| match arg {
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)),
_ => false,
}) || self.bindings.iter().any(|arg| match arg.kind {
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err),
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err(_)),
_ => false,
})
}
@ -1688,7 +1688,7 @@ impl Expr<'_> {
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Err => ExprPrecedence::Err,
ExprKind::Err(_) => ExprPrecedence::Err,
}
}
@ -1754,7 +1754,7 @@ impl Expr<'_> {
| ExprKind::Yield(..)
| ExprKind::Cast(..)
| ExprKind::DropTemps(..)
| ExprKind::Err => false,
| ExprKind::Err(_) => false,
}
}
@ -1840,7 +1840,7 @@ impl Expr<'_> {
| ExprKind::Binary(..)
| ExprKind::Yield(..)
| ExprKind::DropTemps(..)
| ExprKind::Err => true,
| ExprKind::Err(_) => true,
}
}
@ -2013,7 +2013,7 @@ pub enum ExprKind<'hir> {
Yield(&'hir Expr<'hir>, YieldSource),
/// A placeholder for an expression that wasn't syntactically well formed in some way.
Err,
Err(rustc_span::ErrorGuaranteed),
}
/// Represents an optionally `Self`-qualified value/type path or associated extension.
@ -2676,7 +2676,7 @@ pub enum TyKind<'hir> {
/// specified. This can appear anywhere in a type.
Infer,
/// Placeholder for a type that has failed to be defined.
Err,
Err(rustc_span::ErrorGuaranteed),
}
#[derive(Debug, HashStable_Generic)]

View File

@ -790,7 +790,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
ExprKind::Yield(ref subexpression, _) => {
visitor.visit_expr(subexpression);
}
ExprKind::Lit(_) | ExprKind::Err => {}
ExprKind::Lit(_) | ExprKind::Err(_) => {}
}
}
@ -844,7 +844,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
visitor.visit_lifetime(lifetime);
}
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
TyKind::Infer | TyKind::Err => {}
TyKind::Infer | TyKind::Err(_) => {}
}
}

View File

@ -302,8 +302,6 @@ 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;
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;

View File

@ -131,7 +131,7 @@ hir_analysis_where_clause_on_main = `main` function is not allowed to have a `wh
.label = `main` cannot have a `where` clause
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
.label = `main` function is not allowed to be `#[track_caller]`
.suggestion = remove this annotation
hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
.label = `start` is not allowed to be `#[track_caller]`

View File

@ -3113,7 +3113,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// handled specially and will not descend into this routine.
self.ty_infer(None, ast_ty.span)
}
hir::TyKind::Err => tcx.ty_error_misc(),
hir::TyKind::Err(guar) => tcx.ty_error(*guar),
};
self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);

View File

@ -329,8 +329,9 @@ pub(crate) struct WhereClauseOnMain {
#[diag(hir_analysis_track_caller_on_main)]
pub(crate) struct TrackCallerOnMain {
#[primary_span]
#[suggestion(applicability = "maybe-incorrect", code = "")]
pub span: Span,
#[label]
#[label(hir_analysis_track_caller_on_main)]
pub annotated: Span,
}

View File

@ -358,7 +358,7 @@ impl<'a> State<'a> {
self.print_anon_const(e);
self.word(")");
}
hir::TyKind::Err => {
hir::TyKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
@ -1559,7 +1559,7 @@ impl<'a> State<'a> {
self.word_space("yield");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
hir::ExprKind::Err => {
hir::ExprKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();

View File

@ -354,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected),
ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr),
ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src),
hir::ExprKind::Err => tcx.ty_error_misc(),
hir::ExprKind::Err(guar) => tcx.ty_error(guar),
}
}

View File

@ -301,7 +301,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
hir::ExprKind::Continue(..)
| hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Err => {}
| hir::ExprKind::Err(_) => {}
hir::ExprKind::Loop(blk, ..) => {
self.walk_block(blk);

View File

@ -219,7 +219,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..)
| ExprKind::Err => (),
| ExprKind::Err(_) => (),
}
}
@ -483,7 +483,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
| ExprKind::Closure { .. }
| ExprKind::ConstBlock(..)
| ExprKind::DropTemps(..)
| ExprKind::Err
| ExprKind::Err(_)
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::InlineAsm(..)

View File

@ -383,7 +383,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Err => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
| hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
}
}

View File

@ -116,11 +116,11 @@ pub fn elaborate_predicates_with_span<'tcx>(
pub fn elaborate_obligations<'tcx>(
tcx: TyCtxt<'tcx>,
mut obligations: Vec<PredicateObligation<'tcx>>,
obligations: Vec<PredicateObligation<'tcx>>,
) -> Elaborator<'tcx> {
let mut visited = PredicateSet::new(tcx);
obligations.retain(|obligation| visited.insert(obligation.predicate));
Elaborator { stack: obligations, visited }
let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
elaborator.extend_deduped(obligations);
elaborator
}
fn predicate_obligation<'tcx>(
@ -132,6 +132,15 @@ fn predicate_obligation<'tcx>(
}
impl<'tcx> Elaborator<'tcx> {
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>) {
// Only keep those bounds that we haven't already seen.
// This is necessary to prevent infinite recursion in some
// cases. One common case is when people define
// `trait Sized: Sized { }` rather than `trait Sized { }`.
// let visited = &mut self.visited;
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
}
pub fn filter_to_traits(self) -> FilterToTraits<Self> {
FilterToTraits::new(self)
}
@ -172,15 +181,7 @@ impl<'tcx> Elaborator<'tcx> {
)
});
debug!(?data, ?obligations, "super_predicates");
// Only keep those bounds that we haven't already seen.
// This is necessary to prevent infinite recursion in some
// cases. One common case is when people define
// `trait Sized: Sized { }` rather than `trait Sized { }`.
let visited = &mut self.visited;
let obligations = obligations.filter(|o| visited.insert(o.predicate));
self.stack.extend(obligations);
self.extend_deduped(obligations);
}
ty::PredicateKind::WellFormed(..) => {
// Currently, we do not elaborate WF predicates,
@ -237,10 +238,9 @@ impl<'tcx> Elaborator<'tcx> {
return;
}
let visited = &mut self.visited;
let mut components = smallvec![];
push_outlives_components(tcx, ty_max, &mut components);
self.stack.extend(
self.extend_deduped(
components
.into_iter()
.filter_map(|component| match component {
@ -280,7 +280,6 @@ impl<'tcx> Elaborator<'tcx> {
.map(|predicate_kind| {
bound_predicate.rebind(predicate_kind).to_predicate(tcx)
})
.filter(|&predicate| visited.insert(predicate))
.map(|predicate| {
predicate_obligation(
predicate,

View File

@ -758,7 +758,7 @@ impl<'tcx> Cx<'tcx> {
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
hir::ExprKind::Err => unreachable!(),
hir::ExprKind::Err(_) => unreachable!(),
};
Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }

View File

@ -693,7 +693,7 @@ impl<'a> Parser<'a> {
span: self.prev_token.span.shrink_to_lo(),
tokens: None,
};
let struct_expr = snapshot.parse_struct_expr(None, path, false);
let struct_expr = snapshot.parse_expr_struct(None, path, false);
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
return Some(match (struct_expr, block_tail) {
(Ok(expr), Err(mut err)) => {
@ -1624,7 +1624,7 @@ impl<'a> Parser<'a> {
// Handle `await { <expr> }`.
// This needs to be handled separately from the next arm to avoid
// interpreting `await { <expr> }?` as `<expr>?.await`.
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)
self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)
} else {
self.parse_expr()
}

View File

@ -103,7 +103,7 @@ impl<'a> Parser<'a> {
self.collect_tokens_no_attrs(|this| this.parse_expr())
}
pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> {
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
}
@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
}
/// Parses a sequence of expressions delimited by parentheses.
fn parse_paren_expr_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r)
}
@ -136,7 +136,7 @@ impl<'a> Parser<'a> {
r: Restrictions,
already_parsed_attrs: Option<AttrWrapper>,
) -> PResult<'a, P<Expr>> {
self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
self.with_res(r, |this| this.parse_expr_assoc(already_parsed_attrs))
}
/// Parses an associative expression.
@ -144,15 +144,15 @@ impl<'a> Parser<'a> {
/// This parses an expression accounting for associativity and precedence of the operators in
/// the expression.
#[inline]
fn parse_assoc_expr(
fn parse_expr_assoc(
&mut self,
already_parsed_attrs: Option<AttrWrapper>,
) -> PResult<'a, P<Expr>> {
self.parse_assoc_expr_with(0, already_parsed_attrs.into())
self.parse_expr_assoc_with(0, already_parsed_attrs.into())
}
/// Parses an associative expression with operators of at least `min_prec` precedence.
pub(super) fn parse_assoc_expr_with(
pub(super) fn parse_expr_assoc_with(
&mut self,
min_prec: usize,
lhs: LhsExpr,
@ -167,9 +167,9 @@ impl<'a> Parser<'a> {
_ => None,
};
if self.token.is_range_separator() {
return self.parse_prefix_range_expr(attrs);
return self.parse_expr_prefix_range(attrs);
} else {
self.parse_prefix_expr(attrs)?
self.parse_expr_prefix(attrs)?
}
};
let last_type_ascription_set = self.last_type_ascription.is_some();
@ -293,7 +293,7 @@ impl<'a> Parser<'a> {
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
// generalise it to the Fixity::None code.
lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?;
lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?;
break;
}
@ -306,7 +306,7 @@ impl<'a> Parser<'a> {
Fixity::None => 1,
};
let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
})?;
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
@ -458,7 +458,7 @@ impl<'a> Parser<'a> {
/// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
/// The other two variants are handled in `parse_prefix_range_expr` below.
fn parse_range_expr(
fn parse_expr_range(
&mut self,
prec: usize,
lhs: P<Expr>,
@ -466,7 +466,7 @@ impl<'a> Parser<'a> {
cur_op_span: Span,
) -> PResult<'a, P<Expr>> {
let rhs = if self.is_at_start_of_range_notation_rhs() {
Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
} else {
None
};
@ -491,7 +491,7 @@ impl<'a> Parser<'a> {
}
/// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
fn parse_prefix_range_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
fn parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
// Check for deprecated `...` syntax.
if self.token == token::DotDotDot {
self.err_dotdotdot_syntax(self.token.span);
@ -518,7 +518,7 @@ impl<'a> Parser<'a> {
this.bump();
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
// RHS must be parsed with more associativity than the dots.
this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
.map(|x| (lo.to(x.span), Some(x)))?
} else {
(lo, None)
@ -529,7 +529,7 @@ impl<'a> Parser<'a> {
}
/// Parses a prefix-unary-operator expr.
fn parse_prefix_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
fn parse_expr_prefix(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(attrs)?;
let lo = self.token.span;
@ -547,20 +547,20 @@ impl<'a> Parser<'a> {
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
match this.token.uninterpolate().kind {
// `!expr`
token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
// `~expr`
token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
// `-expr`
token::BinOp(token::Minus) => {
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
}
// `*expr`
token::BinOp(token::Star) => {
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
}
// `&expr` and `&&expr`
token::BinOp(token::And) | token::AndAnd => {
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
}
// `+lit`
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
@ -579,7 +579,7 @@ impl<'a> Parser<'a> {
this.sess.emit_err(err);
this.bump();
this.parse_prefix_expr(None)
this.parse_expr_prefix(None)
}
// Recover from `++x`:
token::BinOp(token::Plus)
@ -592,28 +592,28 @@ impl<'a> Parser<'a> {
this.bump();
this.bump();
let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
let operand_expr = this.parse_expr_dot_or_call(Default::default())?;
this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
}
token::Ident(..) if this.token.is_keyword(kw::Box) => {
make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
}
token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
}
_ => return this.parse_dot_or_call_expr(Some(attrs)),
_ => return this.parse_expr_dot_or_call(Some(attrs)),
}
}
fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
self.bump();
let expr = self.parse_prefix_expr(None);
let expr = self.parse_expr_prefix(None);
let (span, expr) = self.interpolated_or_expr_span(expr)?;
Ok((lo.to(span), expr))
}
fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
let (span, expr) = self.parse_prefix_expr_common(lo)?;
fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
let (span, expr) = self.parse_expr_prefix_common(lo)?;
Ok((span, self.mk_unary(op, expr)))
}
@ -621,12 +621,12 @@ impl<'a> Parser<'a> {
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.sess.emit_err(errors::TildeAsUnaryOperator(lo));
self.parse_unary_expr(lo, UnOp::Not)
self.parse_expr_unary(lo, UnOp::Not)
}
/// Parse `box expr`.
fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
let (span, expr) = self.parse_prefix_expr_common(lo)?;
fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
let (span, expr) = self.parse_expr_prefix_common(lo)?;
self.sess.gated_spans.gate(sym::box_syntax, span);
Ok((span, ExprKind::Box(expr)))
}
@ -664,7 +664,7 @@ impl<'a> Parser<'a> {
),
});
self.parse_unary_expr(lo, UnOp::Not)
self.parse_expr_unary(lo, UnOp::Not)
}
/// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
@ -722,7 +722,7 @@ impl<'a> Parser<'a> {
segments[0].ident.span,
),
};
match self.parse_labeled_expr(label, false) {
match self.parse_expr_labeled(label, false) {
Ok(expr) => {
type_err.cancel();
self.sess.emit_err(errors::MalformedLoopLabel {
@ -816,7 +816,7 @@ impl<'a> Parser<'a> {
("cast", None)
};
let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?;
// Check if an illegal postfix operator has been added after the cast.
// If the resulting expression is not a cast, it is an illegal postfix operator.
@ -887,15 +887,15 @@ impl<'a> Parser<'a> {
}
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.expect_and()?;
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
let expr = if self.token.is_range_separator() {
self.parse_prefix_range_expr(None)
self.parse_expr_prefix_range(None)
} else {
self.parse_prefix_expr(None)
self.parse_expr_prefix(None)
};
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
let span = lo.to(hi);
@ -925,16 +925,16 @@ impl<'a> Parser<'a> {
}
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
fn parse_dot_or_call_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(attrs)?;
self.collect_tokens_for_expr(attrs, |this, attrs| {
let base = this.parse_bottom_expr();
let base = this.parse_expr_bottom();
let (span, base) = this.interpolated_or_expr_span(base)?;
this.parse_dot_or_call_expr_with(base, span, attrs)
this.parse_expr_dot_or_call_with(base, span, attrs)
})
}
pub(super) fn parse_dot_or_call_expr_with(
pub(super) fn parse_expr_dot_or_call_with(
&mut self,
e0: P<Expr>,
lo: Span,
@ -943,7 +943,7 @@ impl<'a> Parser<'a> {
// Stitch the list of outer attributes onto the return value.
// A little bit ugly, but the best way given the current code
// structure
let res = self.parse_dot_or_call_expr_with_(e0, lo);
let res = self.parse_expr_dot_or_call_with_(e0, lo);
if attrs.is_empty() {
res
} else {
@ -957,7 +957,7 @@ impl<'a> Parser<'a> {
}
}
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
loop {
let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
// we are using noexpect here because we don't expect a `?` directly after a `return`
@ -980,15 +980,15 @@ impl<'a> Parser<'a> {
};
if has_dot {
// expr.f
e = self.parse_dot_suffix_expr(lo, e)?;
e = self.parse_expr_dot_suffix(lo, e)?;
continue;
}
if self.expr_is_complete(&e) {
return Ok(e);
}
e = match self.token.kind {
token::OpenDelim(Delimiter::Parenthesis) => self.parse_fn_call_expr(lo, e),
token::OpenDelim(Delimiter::Bracket) => self.parse_index_expr(lo, e)?,
token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
_ => return Ok(e),
}
}
@ -1000,14 +1000,14 @@ impl<'a> Parser<'a> {
&& self.look_ahead(3, |t| t.can_begin_expr())
}
fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
fn parse_expr_dot_suffix(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
match self.token.uninterpolate().kind {
token::Ident(..) => self.parse_dot_suffix(base, lo),
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None))
Ok(self.parse_expr_tuple_field_access(lo, base, symbol, suffix, None))
}
token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix))
Ok(self.parse_expr_tuple_field_access_float(lo, base, symbol, suffix))
}
_ => {
self.error_unexpected_after_dot();
@ -1029,7 +1029,7 @@ impl<'a> Parser<'a> {
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
// we should break everything including floats into more basic proc-macro style
// tokens in the lexer (probably preferable).
fn parse_tuple_field_access_expr_float(
fn parse_expr_tuple_field_access_float(
&mut self,
lo: Span,
base: P<Expr>,
@ -1072,7 +1072,7 @@ impl<'a> Parser<'a> {
match &*components {
// 1e2
[IdentLike(i)] => {
self.parse_tuple_field_access_expr(lo, base, Symbol::intern(&i), suffix, None)
self.parse_expr_tuple_field_access(lo, base, Symbol::intern(&i), suffix, None)
}
// 1.
[IdentLike(i), Punct('.')] => {
@ -1088,7 +1088,7 @@ impl<'a> Parser<'a> {
let symbol = Symbol::intern(&i);
self.token = Token::new(token::Ident(symbol, false), ident_span);
let next_token = (Token::new(token::Dot, dot_span), self.token_spacing);
self.parse_tuple_field_access_expr(lo, base, symbol, None, Some(next_token))
self.parse_expr_tuple_field_access(lo, base, symbol, None, Some(next_token))
}
// 1.2 | 1.2e3
[IdentLike(i1), Punct('.'), IdentLike(i2)] => {
@ -1109,11 +1109,11 @@ impl<'a> Parser<'a> {
// See issue #76399 and PR #76285 for more details
let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone);
let base1 =
self.parse_tuple_field_access_expr(lo, base, symbol1, None, Some(next_token1));
self.parse_expr_tuple_field_access(lo, base, symbol1, None, Some(next_token1));
let symbol2 = Symbol::intern(&i2);
let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span);
self.bump_with((next_token2, self.token_spacing)); // `.`
self.parse_tuple_field_access_expr(lo, base1, symbol2, suffix, None)
self.parse_expr_tuple_field_access(lo, base1, symbol2, suffix, None)
}
// 1e+ | 1e- (recovered)
[IdentLike(_), Punct('+' | '-')] |
@ -1131,7 +1131,7 @@ impl<'a> Parser<'a> {
}
}
fn parse_tuple_field_access_expr(
fn parse_expr_tuple_field_access(
&mut self,
lo: Span,
base: P<Expr>,
@ -1152,7 +1152,7 @@ impl<'a> Parser<'a> {
}
/// Parse a function call expression, `expr(...)`.
fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
&& self.look_ahead_type_ascription_as_field()
{
@ -1163,7 +1163,7 @@ impl<'a> Parser<'a> {
let open_paren = self.token.span;
let mut seq = self
.parse_paren_expr_seq()
.parse_expr_paren_seq()
.map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
if let Some(expr) =
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
@ -1236,7 +1236,7 @@ impl<'a> Parser<'a> {
}
/// Parse an indexing expression `expr[...]`.
fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
let prev_span = self.prev_token.span;
let open_delim_span = self.token.span;
self.bump(); // `[`
@ -1259,7 +1259,7 @@ impl<'a> Parser<'a> {
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
// Method call `expr.f()`
let args = self.parse_paren_expr_seq()?;
let args = self.parse_expr_paren_seq()?;
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(
@ -1287,7 +1287,7 @@ impl<'a> Parser<'a> {
///
/// N.B., this does not parse outer attributes, and is private because it only works
/// correctly if called from `parse_dot_or_call_expr()`.
fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole_expr!(self);
@ -1300,13 +1300,13 @@ impl<'a> Parser<'a> {
// This match arm is a special-case of the `_` match arm below and
// could be removed without changing functionality, but it's faster
// to have it here, especially for programs with large constants.
self.parse_lit_expr()
self.parse_expr_lit()
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
self.parse_tuple_parens_expr()
self.parse_expr_tuple_parens()
} else if self.check(&token::OpenDelim(Delimiter::Brace)) {
self.parse_block_expr(None, lo, BlockCheckMode::Default)
self.parse_expr_block(None, lo, BlockCheckMode::Default)
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
self.parse_closure_expr().map_err(|mut err| {
self.parse_expr_closure().map_err(|mut err| {
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
// then suggest parens around the lhs.
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
@ -1315,42 +1315,42 @@ impl<'a> Parser<'a> {
err
})
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
self.parse_array_or_repeat_expr(Delimiter::Bracket)
self.parse_expr_array_or_repeat(Delimiter::Bracket)
} else if self.check_path() {
self.parse_path_start_expr()
self.parse_expr_path_start()
} else if self.check_keyword(kw::Move)
|| self.check_keyword(kw::Static)
|| self.check_const_closure()
{
self.parse_closure_expr()
self.parse_expr_closure()
} else if self.eat_keyword(kw::If) {
self.parse_if_expr()
self.parse_expr_if()
} else if self.check_keyword(kw::For) {
if self.choose_generics_over_qpath(1) {
self.parse_closure_expr()
self.parse_expr_closure()
} else {
assert!(self.eat_keyword(kw::For));
self.parse_for_expr(None, self.prev_token.span)
self.parse_expr_for(None, self.prev_token.span)
}
} else if self.eat_keyword(kw::While) {
self.parse_while_expr(None, self.prev_token.span)
self.parse_expr_while(None, self.prev_token.span)
} else if let Some(label) = self.eat_label() {
self.parse_labeled_expr(label, true)
self.parse_expr_labeled(label, true)
} else if self.eat_keyword(kw::Loop) {
let sp = self.prev_token.span;
self.parse_loop_expr(None, self.prev_token.span).map_err(|mut err| {
self.parse_expr_loop(None, self.prev_token.span).map_err(|mut err| {
err.span_label(sp, "while parsing this `loop` expression");
err
})
} else if self.eat_keyword(kw::Match) {
let match_sp = self.prev_token.span;
self.parse_match_expr().map_err(|mut err| {
self.parse_expr_match().map_err(|mut err| {
err.span_label(match_sp, "while parsing this `match` expression");
err
})
} else if self.eat_keyword(kw::Unsafe) {
let sp = self.prev_token.span;
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
self.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|mut err| {
err.span_label(sp, "while parsing this `unsafe` expression");
err
@ -1364,17 +1364,17 @@ impl<'a> Parser<'a> {
self.expect_keyword(kw::Try)?;
self.parse_try_block(lo)
} else if self.eat_keyword(kw::Return) {
self.parse_return_expr()
self.parse_expr_return()
} else if self.eat_keyword(kw::Continue) {
self.parse_continue_expr(lo)
self.parse_expr_continue(lo)
} else if self.eat_keyword(kw::Break) {
self.parse_break_expr()
self.parse_expr_break()
} else if self.eat_keyword(kw::Yield) {
self.parse_yield_expr()
self.parse_expr_yield()
} else if self.is_do_yeet() {
self.parse_yeet_expr()
self.parse_expr_yeet()
} else if self.check_keyword(kw::Let) {
self.parse_let_expr()
self.parse_expr_let()
} else if self.eat_keyword(kw::Underscore) {
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
} else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
@ -1397,19 +1397,19 @@ impl<'a> Parser<'a> {
// Check for `async {` and `async move {`.
self.parse_async_block()
} else {
self.parse_closure_expr()
self.parse_expr_closure()
}
} else if self.eat_keyword(kw::Await) {
self.recover_incorrect_await_syntax(lo, self.prev_token.span)
} else {
self.parse_lit_expr()
self.parse_expr_lit()
}
} else {
self.parse_lit_expr()
self.parse_expr_lit()
}
}
fn parse_lit_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
match self.parse_opt_token_lit() {
Some((token_lit, _)) => {
@ -1420,7 +1420,7 @@ impl<'a> Parser<'a> {
}
}
fn parse_tuple_parens_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_tuple_parens(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
let (es, trailing_comma) = match self.parse_seq_to_end(
@ -1444,7 +1444,7 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr)
}
fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
fn parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.bump(); // `[` or other open delim
@ -1457,7 +1457,7 @@ impl<'a> Parser<'a> {
let first_expr = self.parse_expr()?;
if self.eat(&token::Semi) {
// Repeating array syntax: `[ 0; 512 ]`
let count = self.parse_anon_const_expr()?;
let count = self.parse_expr_anon_const()?;
self.expect(close)?;
ExprKind::Repeat(first_expr, count)
} else if self.eat(&token::Comma) {
@ -1476,7 +1476,7 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr)
}
fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
let (qself, path) = if self.eat_lt() {
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
(Some(qself), path)
@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> {
}
/// Parse `'label: $expr`. The label is already parsed.
fn parse_labeled_expr(
fn parse_expr_labeled(
&mut self,
label_: Label,
mut consume_colon: bool,
@ -1522,15 +1522,15 @@ impl<'a> Parser<'a> {
let label = Some(label_);
let ate_colon = self.eat(&token::Colon);
let expr = if self.eat_keyword(kw::While) {
self.parse_while_expr(label, lo)
self.parse_expr_while(label, lo)
} else if self.eat_keyword(kw::For) {
self.parse_for_expr(label, lo)
self.parse_expr_for(label, lo)
} else if self.eat_keyword(kw::Loop) {
self.parse_loop_expr(label, lo)
self.parse_expr_loop(label, lo)
} else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
|| self.token.is_whole_block()
{
self.parse_block_expr(label, lo, BlockCheckMode::Default)
self.parse_expr_block(label, lo, BlockCheckMode::Default)
} else if !ate_colon
&& self.may_recover()
&& (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
@ -1670,7 +1670,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"return" expr?`.
fn parse_return_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let kind = ExprKind::Ret(self.parse_expr_opt()?);
let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
@ -1678,7 +1678,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"do" "yeet" expr?`.
fn parse_yeet_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.bump(); // `do`
@ -1700,13 +1700,13 @@ impl<'a> Parser<'a> {
/// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
/// expression only gets a warning for compatibility reasons; and a labeled break
/// with a labeled loop does not even get a warning because there is no ambiguity.
fn parse_break_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let mut label = self.eat_label();
let kind = if self.token == token::Colon && let Some(label) = label.take() {
// The value expression can be a labeled loop, see issue #86948, e.g.:
// `loop { break 'label: loop { break 'label 42; }; }`
let lexpr = self.parse_labeled_expr(label, true)?;
let lexpr = self.parse_expr_labeled(label, true)?;
self.sess.emit_err(errors::LabeledLoopInBreak {
span: lexpr.span,
sub: errors::WrapExpressionInParentheses {
@ -1759,7 +1759,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"continue" label?`.
fn parse_continue_expr(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
let mut label = self.eat_label();
// Recover `continue label` -> `continue 'label`
@ -1776,7 +1776,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"yield" expr?`.
fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let kind = ExprKind::Yield(self.parse_expr_opt()?);
let span = lo.to(self.prev_token.span);
@ -1993,7 +1993,7 @@ impl<'a> Parser<'a> {
/// expression.
fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
match snapshot.parse_expr_array_or_repeat(Delimiter::Brace) {
Ok(arr) => {
self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces {
span: arr.span,
@ -2056,7 +2056,7 @@ impl<'a> Parser<'a> {
}
/// Parses a block or unsafe block.
pub(super) fn parse_block_expr(
pub(super) fn parse_expr_block(
&mut self,
opt_label: Option<Label>,
lo: Span,
@ -2086,7 +2086,7 @@ impl<'a> Parser<'a> {
}
/// Parses a closure expression (e.g., `move |args| expr`).
fn parse_closure_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
let binder = if self.check_keyword(kw::For) {
@ -2123,7 +2123,7 @@ impl<'a> Parser<'a> {
_ => {
// If an explicit return type is given, require a block to appear (RFC 968).
let body_lo = self.token.span;
self.parse_block_expr(None, body_lo, BlockCheckMode::Default)?
self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
}
};
@ -2236,9 +2236,9 @@ impl<'a> Parser<'a> {
}
/// Parses an `if` expression (`if` token already eaten).
fn parse_if_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let cond = self.parse_cond_expr()?;
let cond = self.parse_expr_cond()?;
self.parse_if_after_cond(lo, cond)
}
@ -2316,12 +2316,12 @@ impl<'a> Parser<'a> {
self.error_on_if_block_attrs(lo, false, block.span, attrs);
block
};
let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
let els = if self.eat_keyword(kw::Else) { Some(self.parse_expr_else()?) } else { None };
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
}
/// Parses the condition of a `if` or `while` expression.
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
let cond =
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
@ -2334,7 +2334,7 @@ impl<'a> Parser<'a> {
}
/// Parses a `let $pat = $expr` pseudo-expression.
fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_let(&mut self) -> PResult<'a, P<Expr>> {
// This is a *approximate* heuristic that detects if `let` chains are
// being parsed in the right position. It's approximate because it
// doesn't deny all invalid `let` expressions, just completely wrong usages.
@ -2364,7 +2364,7 @@ impl<'a> Parser<'a> {
self.expect(&token::Eq)?;
}
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
this.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())
})?;
let span = lo.to(expr.span);
self.sess.gated_spans.gate(sym::let_chains, span);
@ -2372,11 +2372,11 @@ impl<'a> Parser<'a> {
}
/// Parses an `else { ... }` expression (`else` token already eaten).
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
let else_span = self.prev_token.span; // `else`
let attrs = self.parse_outer_attributes()?; // For recovery.
let expr = if self.eat_keyword(kw::If) {
self.parse_if_expr()?
self.parse_expr_if()?
} else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
self.parse_simple_block()?
} else {
@ -2450,7 +2450,7 @@ impl<'a> Parser<'a> {
}
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
// Record whether we are about to parse `for (`.
// This is used below for recovery in case of `for ( $stuff ) $block`
// in which case we will suggest `for $stuff $block`.
@ -2508,8 +2508,8 @@ impl<'a> Parser<'a> {
}
/// Parses a `while` or `while let` expression (`while` token already eaten).
fn parse_while_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let cond = self.parse_cond_expr().map_err(|mut err| {
fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let cond = self.parse_expr_cond().map_err(|mut err| {
err.span_label(lo, "while parsing the condition of this `while` expression");
err
})?;
@ -2526,7 +2526,7 @@ impl<'a> Parser<'a> {
}
/// Parses `loop { ... }` (`loop` token already eaten).
fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let loop_span = self.prev_token.span;
let (attrs, body) = self.parse_inner_attrs_and_block()?;
Ok(self.mk_expr_with_attrs(
@ -2544,7 +2544,7 @@ impl<'a> Parser<'a> {
}
/// Parses a `match ... { ... }` expression (`match` token already eaten).
fn parse_match_expr(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
let match_span = self.prev_token.span;
let lo = self.prev_token.span;
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@ -2914,7 +2914,7 @@ impl<'a> Parser<'a> {
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
return Some(Err(err));
}
let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
let expr = self.parse_expr_struct(qself.clone(), path.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here.
self.sess.emit_err(errors::StructLiteralNotAllowedHere {
@ -3043,7 +3043,7 @@ impl<'a> Parser<'a> {
}
/// Precondition: already parsed the '{'.
pub(super) fn parse_struct_expr(
pub(super) fn parse_expr_struct(
&mut self,
qself: Option<P<ast::QSelf>>,
pth: ast::Path,

View File

@ -1331,7 +1331,7 @@ impl<'a> Parser<'a> {
};
let disr_expr =
if this.eat(&token::Eq) { Some(this.parse_anon_const_expr()?) } else { None };
if this.eat(&token::Eq) { Some(this.parse_expr_anon_const()?) } else { None };
let vr = ast::Variant {
ident,
@ -1722,7 +1722,7 @@ impl<'a> Parser<'a> {
}
if self.token.kind == token::Eq {
self.bump();
let const_expr = self.parse_anon_const_expr()?;
let const_expr = self.parse_expr_anon_const()?;
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
self.struct_span_err(sp, "default values on `struct` fields aren't supported")
.span_suggestion(

View File

@ -653,7 +653,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
// Parse const argument.
let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind {
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)?
self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?
} else {
self.handle_unambiguous_unbraced_const_arg()?
};

View File

@ -146,14 +146,14 @@ impl<'a> Parser<'a> {
}
let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) {
this.parse_struct_expr(None, path, true)?
this.parse_expr_struct(None, path, true)?
} else {
let hi = this.prev_token.span;
this.mk_expr(lo.to(hi), ExprKind::Path(None, path))
};
let expr = this.with_res(Restrictions::STMT_EXPR, |this| {
this.parse_dot_or_call_expr_with(expr, lo, attrs)
this.parse_expr_dot_or_call_with(expr, lo, attrs)
})?;
// `DUMMY_SP` will get overwritten later in this function
Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None))
@ -163,7 +163,7 @@ impl<'a> Parser<'a> {
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
this.parse_assoc_expr_with(
this.parse_expr_assoc_with(
0,
LhsExpr::AlreadyParsed { expr, starts_statement: true },
)
@ -199,8 +199,8 @@ impl<'a> Parser<'a> {
// Since none of the above applied, this is an expression statement macro.
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
let e = self.parse_assoc_expr_with(
let e = self.parse_expr_dot_or_call_with(e, lo, attrs)?;
let e = self.parse_expr_assoc_with(
0,
LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
)?;

View File

@ -433,7 +433,7 @@ impl<'a> Parser<'a> {
};
let ty = if self.eat(&token::Semi) {
let mut length = self.parse_anon_const_expr()?;
let mut length = self.parse_expr_anon_const()?;
if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
@ -494,7 +494,7 @@ impl<'a> Parser<'a> {
// To avoid ambiguity, the type is surrounded by parentheses.
fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
let expr = self.parse_anon_const_expr()?;
let expr = self.parse_expr_anon_const()?;
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
Ok(TyKind::Typeof(expr))
}

View File

@ -475,7 +475,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
| hir::ExprKind::Err
| hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
intravisit::walk_expr(self, expr);
@ -1129,7 +1129,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Err
| hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
@ -1427,7 +1427,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::Yield(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
| hir::ExprKind::Err => {}
| hir::ExprKind::Err(_) => {}
}
}

View File

@ -219,7 +219,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
hir::intravisit::walk_expr(self, expr);
}
ExprKind::Err => {
ExprKind::Err(_) => {
self.items.push((ItemKind::Err, span));
}
}

View File

@ -2149,3 +2149,17 @@ where
Hash::hash(&len, hasher);
}
}
/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(HashStable_Generic)]
pub struct ErrorGuaranteed(());
impl ErrorGuaranteed {
/// To be used only if you really know what you are doing... ideally, we would find a way to
/// eliminate all calls to this method.
pub fn unchecked_claim_error_was_emitted() -> Self {
ErrorGuaranteed(())
}
}

View File

@ -740,6 +740,7 @@ symbols! {
frem_fast,
from,
from_desugaring,
from_fn,
from_iter,
from_method,
from_output,

View File

@ -21,12 +21,14 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::Str
| ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never
| ty::Char => Ok(vec![]),
// Treat this like `struct str([u8]);`
ty::Str => Ok(vec![tcx.mk_slice(tcx.types.u8)]),
ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)

View File

@ -3107,6 +3107,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.tcx.def_span(def_id),
"required because it's used within this closure",
),
ty::Str => err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes"),
_ => err.note(&msg),
};
}

View File

@ -2300,12 +2300,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::Str
| ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never
| ty::Char => ty::Binder::dummy(Vec::new()),
// Treat this like `struct str([u8]);`
ty::Str => ty::Binder::dummy(vec![self.tcx().mk_slice(self.tcx().types.u8)]),
ty::Placeholder(..)
| ty::Dynamic(..)
| ty::Param(..)

View File

@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
return;
}
if target_cap < self.capacity() {
// There are three cases of interest:
// All elements are out of desired bounds
// Elements are contiguous, and head is out of desired bounds
// Elements are discontiguous, and tail is out of desired bounds
//
// At all other times, element positions are unaffected.
//
// Indicates that elements at the head should be moved.
// There are three cases of interest:
// All elements are out of desired bounds
// Elements are contiguous, and tail is out of desired bounds
// Elements are discontiguous
//
// At all other times, element positions are unaffected.
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
// Move elements from out of desired bounds (positions after target_cap)
if self.len == 0 {
self.head = 0;
} else if self.head >= target_cap && tail_outside {
// H := head
// L := last element
// H L
// [. . . . . . . . o o o o o o o . ]
// H L
// [o o o o o o o . ]
unsafe {
// nonoverlapping because self.head >= target_cap >= self.len
self.copy_nonoverlapping(self.head, 0, self.len);
}
self.head = 0;
} else if self.head < target_cap && tail_outside {
// H := head
// L := last element
// H L
// [. . . o o o o o o o . . . . . . ]
// L H
// [o o . o o o o o ]
let len = self.head + self.len - target_cap;
unsafe {
self.copy_nonoverlapping(target_cap, 0, len);
}
} else if self.head >= target_cap {
// H := head
// L := last element
// L H
// [o o o o o . . . . . . . . . o o ]
// L H
// [o o o o o . o o ]
let len = self.capacity() - self.head;
let new_head = target_cap - len;
unsafe {
// can't use copy_nonoverlapping here for the same reason
// as in `handle_capacity_increase()`
self.copy(self.head, new_head, len);
}
self.head = new_head;
// `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
// overflow.
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
if self.len == 0 {
self.head = 0;
} else if self.head >= target_cap && tail_outside {
// Head and tail are both out of bounds, so copy all of them to the front.
//
// H := head
// L := last element
// H L
// [. . . . . . . . o o o o o o o . ]
// H L
// [o o o o o o o . ]
unsafe {
// nonoverlapping because `self.head >= target_cap >= self.len`.
self.copy_nonoverlapping(self.head, 0, self.len);
}
self.buf.shrink_to_fit(target_cap);
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
debug_assert!(self.len <= self.capacity());
self.head = 0;
} else if self.head < target_cap && tail_outside {
// Head is in bounds, tail is out of bounds.
// Copy the overflowing part to the beginning of the
// buffer. This won't overlap because `target_cap >= self.len`.
//
// H := head
// L := last element
// H L
// [. . . o o o o o o o . . . . . . ]
// L H
// [o o . o o o o o ]
let len = self.head + self.len - target_cap;
unsafe {
self.copy_nonoverlapping(target_cap, 0, len);
}
} else if !self.is_contiguous() {
// The head slice is at least partially out of bounds, tail is in bounds.
// Copy the head backwards so it lines up with the target capacity.
// This won't overlap because `target_cap >= self.len`.
//
// H := head
// L := last element
// L H
// [o o o o o . . . . . . . . . o o ]
// L H
// [o o o o o . o o ]
let head_len = self.capacity() - self.head;
let new_head = target_cap - head_len;
unsafe {
// can't use `copy_nonoverlapping()` here because the new and old
// regions for the head might overlap.
self.copy(self.head, new_head, head_len);
}
self.head = new_head;
}
self.buf.shrink_to_fit(target_cap);
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
debug_assert!(self.len <= self.capacity());
}
/// Shortens the deque, keeping the first `len` elements and dropping

View File

@ -748,6 +748,48 @@ fn test_drain() {
}
}
#[test]
fn issue_108453() {
let mut deque = VecDeque::with_capacity(10);
deque.push_back(1u8);
deque.push_back(2);
deque.push_back(3);
deque.push_front(10);
deque.push_front(9);
deque.shrink_to(9);
assert_eq!(deque.into_iter().collect::<Vec<_>>(), vec![9, 10, 1, 2, 3]);
}
#[test]
fn test_shrink_to() {
// test deques with capacity 16 with all possible head positions, lengths and target capacities.
let cap = 16;
for len in 0..cap {
for head in 0..cap {
let expected = (1..=len).collect::<VecDeque<_>>();
for target_cap in len..cap {
let mut deque = VecDeque::with_capacity(cap);
// currently, `with_capacity` always allocates the exact capacity if it's greater than 8.
assert_eq!(deque.capacity(), cap);
// we can let the head point anywhere in the buffer since the deque is empty.
deque.head = head;
deque.extend(1..=len);
deque.shrink_to(target_cap);
assert_eq!(deque, expected);
}
}
}
}
#[test]
fn test_shrink_to_fit() {
// This test checks that every single combination of head and tail position,

View File

@ -542,7 +542,7 @@ pub trait Into<T>: Sized {
#[const_trait]
pub trait From<T>: Sized {
/// Converts to this type from the input type.
#[lang = "from"]
#[rustc_diagnostic_item = "from_fn"]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn from(value: T) -> Self;

View File

@ -3,21 +3,26 @@ macro_rules! int_impl {
Self = $SelfT:ty,
ActualT = $ActualT:ident,
UnsignedT = $UnsignedT:ty,
BITS = $BITS:expr,
BITS_MINUS_ONE = $BITS_MINUS_ONE:expr,
Min = $Min:expr,
Max = $Max:expr,
rot = $rot:expr,
rot_op = $rot_op:expr,
rot_result = $rot_result:expr,
swap_op = $swap_op:expr,
swapped = $swapped:expr,
reversed = $reversed:expr,
le_bytes = $le_bytes:expr,
be_bytes = $be_bytes:expr,
// There are all for use *only* in doc comments.
// As such, they're all passed as literals -- passing them as a string
// literal is fine if they need to be multiple code tokens.
// In non-comments, use the associated constants rather than these.
BITS = $BITS:literal,
BITS_MINUS_ONE = $BITS_MINUS_ONE:literal,
Min = $Min:literal,
Max = $Max:literal,
rot = $rot:literal,
rot_op = $rot_op:literal,
rot_result = $rot_result:literal,
swap_op = $swap_op:literal,
swapped = $swapped:literal,
reversed = $reversed:literal,
le_bytes = $le_bytes:literal,
be_bytes = $be_bytes:literal,
to_xe_bytes_doc = $to_xe_bytes_doc:expr,
from_xe_bytes_doc = $from_xe_bytes_doc:expr,
bound_condition = $bound_condition:expr,
bound_condition = $bound_condition:literal,
) => {
/// The smallest value that can be represented by this integer type
#[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")]
@ -30,7 +35,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")]
/// ```
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
pub const MIN: Self = !Self::MAX;
/// The largest value that can be represented by this integer type
#[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ").")]
@ -43,7 +48,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")]
/// ```
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX: Self = !Self::MIN;
pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self;
/// The size of this integer type in bits.
///
@ -53,7 +58,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
#[stable(feature = "int_bits_const", since = "1.53.0")]
pub const BITS: u32 = $BITS;
pub const BITS: u32 = <$UnsignedT>::BITS;
/// Converts a string slice in a given base to an integer.
///
@ -1380,7 +1385,7 @@ macro_rules! int_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shl(rhs & ($BITS - 1))
self.unchecked_shl(rhs & (Self::BITS - 1))
}
}
@ -1410,7 +1415,7 @@ macro_rules! int_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shr(rhs & ($BITS - 1))
self.unchecked_shr(rhs & (Self::BITS - 1))
}
}
@ -1916,7 +1921,7 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shl(rhs), rhs >= Self::BITS)
}
/// Shifts self right by `rhs` bits.
@ -1939,7 +1944,7 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shr(rhs), rhs >= Self::BITS)
}
/// Computes the absolute value of `self`.

View File

@ -4,19 +4,24 @@ macro_rules! uint_impl {
ActualT = $ActualT:ident,
SignedT = $SignedT:ident,
NonZeroT = $NonZeroT:ident,
BITS = $BITS:expr,
MAX = $MaxV:expr,
rot = $rot:expr,
rot_op = $rot_op:expr,
rot_result = $rot_result:expr,
swap_op = $swap_op:expr,
swapped = $swapped:expr,
reversed = $reversed:expr,
le_bytes = $le_bytes:expr,
be_bytes = $be_bytes:expr,
// There are all for use *only* in doc comments.
// As such, they're all passed as literals -- passing them as a string
// literal is fine if they need to be multiple code tokens.
// In non-comments, use the associated constants rather than these.
BITS = $BITS:literal,
MAX = $MaxV:literal,
rot = $rot:literal,
rot_op = $rot_op:literal,
rot_result = $rot_result:literal,
swap_op = $swap_op:literal,
swapped = $swapped:literal,
reversed = $reversed:literal,
le_bytes = $le_bytes:literal,
be_bytes = $be_bytes:literal,
to_xe_bytes_doc = $to_xe_bytes_doc:expr,
from_xe_bytes_doc = $from_xe_bytes_doc:expr,
bound_condition = $bound_condition:expr,
bound_condition = $bound_condition:literal,
) => {
/// The smallest value that can be represented by this integer type.
///
@ -51,7 +56,7 @@ macro_rules! uint_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
#[stable(feature = "int_bits_const", since = "1.53.0")]
pub const BITS: u32 = $BITS;
pub const BITS: u32 = Self::MAX.count_ones();
/// Converts a string slice in a given base to an integer.
///
@ -1403,7 +1408,7 @@ macro_rules! uint_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shl(rhs & ($BITS - 1))
self.unchecked_shl(rhs & (Self::BITS - 1))
}
}
@ -1436,7 +1441,7 @@ macro_rules! uint_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shr(rhs & ($BITS - 1))
self.unchecked_shr(rhs & (Self::BITS - 1))
}
}
@ -1860,7 +1865,7 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shl(rhs), rhs >= Self::BITS)
}
/// Shifts self right by `rhs` bits.
@ -1885,7 +1890,7 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shr(rhs), rhs >= Self::BITS)
}
/// Raises self to the power of `exp`, using exponentiation by squaring.

View File

@ -1661,7 +1661,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
}
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer | TyKind::Err | TyKind::Typeof(..) => Infer,
TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) => Infer,
}
}

View File

@ -1022,7 +1022,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
))
.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
),
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err(_) => {
Position::ReborrowStable(precedence)
},
};
@ -1038,7 +1038,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
if self.0
|| matches!(
ty.kind,
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
)
{
self.0 = true;

View File

@ -224,7 +224,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
| ExprKind::Path(_)
| ExprKind::ConstBlock(_)
| ExprKind::Lit(_)
| ExprKind::Err => NeverLoopResult::Otherwise,
| ExprKind::Err(_) => NeverLoopResult::Otherwise,
}
}

View File

@ -341,7 +341,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
ExprKind::ConstBlock(_) |
ExprKind::Continue(_) |
ExprKind::DropTemps(_) |
ExprKind::Err |
ExprKind::Err(_) |
ExprKind::InlineAsm(_) |
ExprKind::Let(_) |
ExprKind::Lit(_) |

View File

@ -49,10 +49,10 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
(arg, arg.span)
},
ExprKind::Call(path, [arg])
if path_def_id(cx, path).map_or(false, |id| {
if match_def_path(cx, id, &paths::FROM_STR_METHOD) {
if path_def_id(cx, path).map_or(false, |did| {
if match_def_path(cx, did, &paths::FROM_STR_METHOD) {
true
} else if cx.tcx.lang_items().from_fn() == Some(id) {
} else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
!is_copy(cx, typeck.expr_ty(expr))
} else {
false

View File

@ -7,6 +7,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
declare_clippy_lint! {
/// ### What it does
@ -54,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
);
} else {
if_chain! {
if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id);
if let [.., last_arg] = args;
if let ExprKind::Lit(spanned) = &last_arg.kind;
if let LitKind::Str(symbol, _) = spanned.node;

View File

@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
}
if_chain! {
if Some(def_id) == cx.tcx.lang_items().from_fn();
if cx.tcx.is_diagnostic_item(sym::from_fn, def_id);
if same_type_and_consts(a, b);
then {

View File

@ -588,7 +588,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
},
}
},
ExprKind::Err => kind!("Err"),
ExprKind::Err(_) => kind!("Err"),
ExprKind::DropTemps(expr) => {
bind!(self, expr);
kind!("DropTemps({expr})");

View File

@ -193,7 +193,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
| ExprKind::Ret(_)
| ExprKind::InlineAsm(_)
| ExprKind::Yield(..)
| ExprKind::Err => {
| ExprKind::Err(_) => {
self.eagerness = ForceNoChange;
return;
},

View File

@ -714,7 +714,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
self.hash_pat(pat);
},
ExprKind::Err => {},
ExprKind::Err(_) => {},
ExprKind::Lit(ref l) => {
l.node.hash(&mut self.s);
},
@ -986,7 +986,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
TyKind::Err | TyKind::Infer | TyKind::Never => {},
TyKind::Err(_) | TyKind::Infer | TyKind::Never => {},
}
}

View File

@ -157,7 +157,7 @@ impl<'a> Sugg<'a> {
| hir::ExprKind::Ret(..)
| hir::ExprKind::Struct(..)
| hir::ExprKind::Tup(..)
| hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
| hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
hir::ExprKind::Assign(lhs, rhs, _) => {
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))

View File

@ -665,7 +665,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
| ExprKind::Path(_)
| ExprKind::Continue(_)
| ExprKind::InlineAsm(_)
| ExprKind::Err => (),
| ExprKind::Err(_) => (),
}
ControlFlow::Continue(())
}

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
mdbook = { version = "0.4", default-features = false, features = ["search"] }
rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
[[bin]]
name = "error_index_generator"

View File

@ -2,9 +2,6 @@
extern crate rustc_driver;
// We use the function we generate from `register_diagnostics!`.
use crate::error_codes::error_codes;
use std::env;
use std::error::Error;
use std::fs::{self, File};
@ -17,22 +14,6 @@ use std::str::FromStr;
use mdbook::book::{parse_summary, BookItem, Chapter};
use mdbook::{Config, MDBook};
macro_rules! register_diagnostics {
($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
let mut errors: Vec<(&str, Option<&str>)> = vec![
$((stringify!($error_code), Some($message)),)+
$((stringify!($undocumented), None),)*
];
errors.sort();
errors
}
}
}
#[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
mod error_codes;
enum OutputFormat {
HTML,
Markdown,
@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
write!(output_file, "# Rust Compiler Error Index\n")?;
for (err_code, description) in error_codes().iter() {
match description {
Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
None => {}
}
for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
write!(output_file, "## {}\n{}\n", err_code, description)?
}
Ok(())
@ -105,27 +83,23 @@ This page lists all the error codes emitted by the Rust compiler.
"
);
let err_codes = error_codes();
let err_codes = rustc_error_codes::DIAGNOSTICS;
let mut chapters = Vec::with_capacity(err_codes.len());
for (err_code, explanation) in err_codes.iter() {
if let Some(explanation) = explanation {
introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
let content = add_rust_attribute_on_codeblock(explanation);
chapters.push(BookItem::Chapter(Chapter {
name: err_code.to_string(),
content: format!("# Error code {}\n\n{}\n", err_code, content),
number: None,
sub_items: Vec::new(),
// We generate it into the `error_codes` folder.
path: Some(PathBuf::from(&format!("{}.html", err_code))),
source_path: None,
parent_names: Vec::new(),
}));
} else {
introduction.push_str(&format!(" * {}\n", err_code));
}
let content = add_rust_attribute_on_codeblock(explanation);
chapters.push(BookItem::Chapter(Chapter {
name: err_code.to_string(),
content: format!("# Error code {}\n\n{}\n", err_code, content),
number: None,
sub_items: Vec::new(),
// We generate it into the `error_codes` folder.
path: Some(PathBuf::from(&format!("{}.html", err_code))),
source_path: None,
parent_names: Vec::new(),
}));
}
let mut config = Config::from_str(include_str!("book_config.toml"))?;

View File

@ -45,7 +45,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
let mut errors = Vec::new();
// Stage 1: create list
let error_codes = extract_error_codes(root_path, &mut errors, verbose);
let error_codes = extract_error_codes(root_path, &mut errors);
println!("Found {} error codes", error_codes.len());
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
@ -65,18 +65,17 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
}
/// Stage 1: Parses a list of error codes from `error_codes.rs`.
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
let path = root_path.join(Path::new(ERROR_CODES_PATH));
let file =
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
let mut error_codes = Vec::new();
let mut reached_undocumented_codes = false;
for line in file.lines() {
let line = line.trim();
if !reached_undocumented_codes && line.starts_with('E') {
if line.starts_with('E') {
let split_line = line.split_once(':');
// Extract the error code from the line, emitting a fatal error if it is not in a correct format.
@ -111,23 +110,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool
}
error_codes.push(err_code);
} else if reached_undocumented_codes && line.starts_with('E') {
let err_code = match line.split_once(',') {
None => line,
Some((err_code, _)) => err_code,
}
.to_string();
verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
if error_codes.contains(&err_code) {
errors.push(format!("Found duplicate error code: `{}`", err_code));
}
error_codes.push(err_code);
} else if line == ";" {
// Once we reach the undocumented error codes, adapt to different syntax.
reached_undocumented_codes = true;
}
}

View File

@ -0,0 +1,13 @@
#![feature(negative_impls)]
#![feature(auto_traits)]
auto trait AutoTrait {}
impl<T> !AutoTrait for [T] {}
fn needs_auto_trait<T: AutoTrait + ?Sized>() {}
fn main() {
needs_auto_trait::<str>();
//~^ ERROR the trait bound `[u8]: AutoTrait` is not satisfied in `str`
}

View File

@ -0,0 +1,16 @@
error[E0277]: the trait bound `[u8]: AutoTrait` is not satisfied in `str`
--> $DIR/str-contains-slice-conceptually.rs:11:22
|
LL | needs_auto_trait::<str>();
| ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]`
|
= note: `str` is considered to contain a `[u8]` slice for auto trait purposes
note: required by a bound in `needs_auto_trait`
--> $DIR/str-contains-slice-conceptually.rs:8:24
|
LL | fn needs_auto_trait<T: AutoTrait + ?Sized>() {}
| ^^^^^^^^^ required by this bound in `needs_auto_trait`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -2,7 +2,7 @@ error: `main` function is not allowed to be `#[track_caller]`
--> $DIR/error-with-main.rs:1:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ help: remove this annotation
LL | fn main() {
| --------- `main` function is not allowed to be `#[track_caller]`