1
Fork 0

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" version = "0.0.0"
dependencies = [ dependencies = [
"mdbook", "mdbook",
"rustc_error_codes",
] ]
[[package]] [[package]]

View file

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

View file

@ -102,7 +102,12 @@ fn make_count<'hir>(
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]); let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]);
ctx.expr_call_mut(sp, count_param, value) ctx.expr_call_mut(sp, count_param, value)
} else { } 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), 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))); argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
ctx.expr_usize(sp, i) 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 { let &FormatOptions {
ref width, ref width,
@ -294,7 +302,12 @@ fn expand_format_args<'hir>(
)); ));
make_argument(ctx, sp, arg, ty) make_argument(ctx, sp, arg, ty)
} else { } 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 let elements: Vec<_> = arguments

View file

@ -7,6 +7,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt; use rustc_ast::visit::AssocCtxt;
use rustc_ast::*; use rustc_ast::*;
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; 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))), .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::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 // We lower
// //
// type Foo = impl Trait // type Foo = impl Trait
@ -299,18 +300,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
&generics, &generics,
id, id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic), &ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy), |this| match ty {
); None => {
hir::ItemKind::TyAlias(ty, generics) let guar = this.tcx.sess.delay_span_bug(
} span,
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => { "expected to lower type alias type, but it was missing",
let mut generics = generics.clone(); );
add_ty_alias_where_clause(&mut generics, *where_clauses, true); this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
let (generics, ty) = self.lower_generics( }
&generics, Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
id, },
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.arena.alloc(this.ty(span, hir::TyKind::Err)),
); );
hir::ItemKind::TyAlias(ty, generics) hir::ItemKind::TyAlias(ty, generics)
} }
@ -798,8 +797,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
/// Construct `ExprKind::Err` for the given `span`. /// Construct `ExprKind::Err` for the given `span`.
pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> { pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::Err) self.expr(span, hir::ExprKind::Err(guar))
} }
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
@ -847,7 +846,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic), &ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty { |this| match ty {
None => { 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) hir::ImplItemKind::Type(ty)
} }
Some(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> { fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
match block { match block {
Some(block) => self.lower_block_expr(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 { match expr {
Some(expr) => this.lower_expr_mut(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 } hir::TypeBindingKind::Constraint { bounds }
} }
DesugarKind::Error(position) => { DesugarKind::Error(position) => {
self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding { let guar = self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
span: constraint.span, span: constraint.span,
position: DiagnosticArgFromDisplay(position), 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() } 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> { fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
let kind = match &t.kind { let kind = match &t.kind {
TyKind::Infer => hir::TyKind::Infer, 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::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Ref(region, mt) => { TyKind::Ref(region, mt) => {
@ -1381,7 +1384,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path path
} }
ImplTraitContext::FeatureGated(position, feature) => { ImplTraitContext::FeatureGated(position, feature) => {
self.tcx let guar = self
.tcx
.sess .sess
.create_feature_err( .create_feature_err(
MisplacedImplTrait { MisplacedImplTrait {
@ -1391,24 +1395,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
*feature, *feature,
) )
.emit(); .emit();
hir::TyKind::Err hir::TyKind::Err(guar)
} }
ImplTraitContext::Disallowed(position) => { ImplTraitContext::Disallowed(position) => {
self.tcx.sess.emit_err(MisplacedImplTrait { let guar = self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span, span: t.span,
position: DiagnosticArgFromDisplay(position), position: DiagnosticArgFromDisplay(position),
}); });
hir::TyKind::Err hir::TyKind::Err(guar)
} }
} }
} }
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
TyKind::CVarArgs => { TyKind::CVarArgs => {
self.tcx.sess.delay_span_bug( let guar = self.tcx.sess.delay_span_bug(
t.span, t.span,
"`TyKind::CVarArgs` should have been handled elsewhere", "`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::Path(..) if allow_paths => {}
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
_ => { _ => {
self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span }); let guar = self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
return self.arena.alloc(self.expr_err(expr.span)); return self.arena.alloc(self.expr_err(expr.span, guar));
} }
} }
self.lower_expr(expr) self.lower_expr(expr)

View file

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

View file

@ -485,7 +485,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
let normalised = let normalised =
if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") }; if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
match registry.try_find_description(&normalised) { match registry.try_find_description(&normalised) {
Ok(Some(description)) => { Ok(description) => {
let mut is_in_code_block = false; let mut is_in_code_block = false;
let mut text = String::new(); let mut text = String::new();
// Slice off the leading newline and print. // Slice off the leading newline and print.
@ -509,9 +509,6 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
print!("{text}"); print!("{text}");
} }
} }
Ok(None) => {
early_error(output, &format!("no extended information for {code}"));
}
Err(InvalidErrorCode) => { Err(InvalidErrorCode) => {
early_error(output, &format!("{code} is not a valid error code")); 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"), E0791: include_str!("./error_codes/E0791.md"),
E0792: include_str!("./error_codes/E0792.md"), E0792: include_str!("./error_codes/E0792.md"),
E0793: include_str!("./error_codes/E0793.md"), E0793: include_str!("./error_codes/E0793.md"),
; }
// Undocumented removed error codes. Note that many removed error codes are documented.
// E0006, // merged with E0005 // E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard // E0008, // cannot bind by-move into a pattern guard
// E0019, // merged into E0015 // E0019, // merged into E0015
@ -570,7 +572,7 @@ E0793: include_str!("./error_codes/E0793.md"),
// E0246, // invalid recursive type // E0246, // invalid recursive type
// E0247, // E0247,
// E0248, // value used as a type, now reported earlier during resolution // E0248, // value used as a type, now reported earlier during resolution
// as E0412 // // as E0412
// E0249, // E0249,
// E0257, // E0257,
// E0258, // E0258,
@ -631,14 +633,14 @@ E0793: include_str!("./error_codes/E0793.md"),
// E0558, // replaced with a generic attribute input check // E0558, // replaced with a generic attribute input check
// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 // E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
// E0564, // only named lifetimes are allowed in `impl Trait`, // 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... // E0598, // lifetime of {} is too short to guarantee its contents can be...
// E0611, // merged into E0616 // E0611, // merged into E0616
// E0612, // merged into E0609 // E0612, // merged into E0609
// E0613, // Removed (merged with E0609) // E0613, // Removed (merged with E0609)
// E0629, // missing 'feature' (rustc_const_unstable) // E0629, // missing 'feature' (rustc_const_unstable)
// E0630, // rustc_const_unstable attribute must be paired with stable/unstable // E0630, // rustc_const_unstable attribute must be paired with stable/unstable
// attribute // // attribute
// E0645, // trait aliases not finished // E0645, // trait aliases not finished
// E0694, // an unknown tool name found in scoped attributes // E0694, // an unknown tool name found in scoped attributes
// E0702, // replaced with a generic attribute input check // E0702, // replaced with a generic attribute input check
@ -647,4 +649,3 @@ E0793: include_str!("./error_codes/E0793.md"),
// E0721, // `await` keyword // E0721, // `await` keyword
// E0723, // unstable feature in `const` context // E0723, // unstable feature in `const` context
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. // 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. //! the goal being to make their maintenance easier.
macro_rules! register_diagnostics { macro_rules! register_diagnostics {
($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( ($($ecode:ident: $message:expr,)*) => (
pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[ pub static DIAGNOSTICS: &[(&str, &str)] = &[
$( (stringify!($ecode), Some($message)), )* $( (stringify!($ecode), $message), )*
$( (stringify!($code), None), )*
]; ];
) )
} }

View file

@ -580,7 +580,7 @@ impl DiagnosticCode {
let je_result = let je_result =
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap(); 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}; pub use rustc_lint_defs::{pluralize, Applicability};
use rustc_macros::fluent_messages; use rustc_macros::fluent_messages;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::HashStableContext; pub use rustc_span::ErrorGuaranteed;
use rustc_span::{Loc, Span}; use rustc_span::{Loc, Span};
use std::borrow::Cow; use std::borrow::Cow;
@ -1477,9 +1477,7 @@ impl HandlerInner {
.emitted_diagnostic_codes .emitted_diagnostic_codes
.iter() .iter()
.filter_map(|x| match &x { .filter_map(|x| match &x {
DiagnosticId::Error(s) DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => {
if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
{
Some(s.clone()) Some(s.clone())
} }
_ => None, _ => None,
@ -1846,17 +1844,3 @@ pub enum TerminalUrl {
Yes, Yes,
Auto, 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)] #[derive(Clone)]
pub struct Registry { pub struct Registry {
long_descriptions: FxHashMap<&'static str, Option<&'static str>>, long_descriptions: FxHashMap<&'static str, &'static str>,
} }
impl Registry { 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() } Registry { long_descriptions: long_descriptions.iter().copied().collect() }
} }
/// Returns `InvalidErrorCode` if the code requested does not exist in the /// Returns `InvalidErrorCode` if the code requested does not exist in the
/// registry. Otherwise, returns an `Option` where `None` means the error /// registry.
/// code is valid but has no extended information. pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
pub fn try_find_description(
&self,
code: &str,
) -> Result<Option<&'static str>, InvalidErrorCode> {
self.long_descriptions.get(code).copied().ok_or(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 { pub fn has_err(&self) -> bool {
self.args.iter().any(|arg| match arg { self.args.iter().any(|arg| match arg {
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err), GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)),
_ => false, _ => false,
}) || self.bindings.iter().any(|arg| match arg.kind { }) || 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, _ => false,
}) })
} }
@ -1688,7 +1688,7 @@ impl Expr<'_> {
ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Yield(..) => ExprPrecedence::Yield, ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Err => ExprPrecedence::Err, ExprKind::Err(_) => ExprPrecedence::Err,
} }
} }
@ -1754,7 +1754,7 @@ impl Expr<'_> {
| ExprKind::Yield(..) | ExprKind::Yield(..)
| ExprKind::Cast(..) | ExprKind::Cast(..)
| ExprKind::DropTemps(..) | ExprKind::DropTemps(..)
| ExprKind::Err => false, | ExprKind::Err(_) => false,
} }
} }
@ -1840,7 +1840,7 @@ impl Expr<'_> {
| ExprKind::Binary(..) | ExprKind::Binary(..)
| ExprKind::Yield(..) | ExprKind::Yield(..)
| ExprKind::DropTemps(..) | ExprKind::DropTemps(..)
| ExprKind::Err => true, | ExprKind::Err(_) => true,
} }
} }
@ -2013,7 +2013,7 @@ pub enum ExprKind<'hir> {
Yield(&'hir Expr<'hir>, YieldSource), Yield(&'hir Expr<'hir>, YieldSource),
/// A placeholder for an expression that wasn't syntactically well formed in some way. /// 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. /// 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. /// specified. This can appear anywhere in a type.
Infer, Infer,
/// Placeholder for a type that has failed to be defined. /// Placeholder for a type that has failed to be defined.
Err, Err(rustc_span::ErrorGuaranteed),
} }
#[derive(Debug, HashStable_Generic)] #[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, _) => { ExprKind::Yield(ref subexpression, _) => {
visitor.visit_expr(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); visitor.visit_lifetime(lifetime);
} }
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), 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; Context, sym::Context, context, Target::Struct, GenericRequirement::None;
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), 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; OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
OptionNone, sym::None, option_none_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 .label = `main` cannot have a `where` clause
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]` 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]` hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
.label = `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. // handled specially and will not descend into this routine.
self.ty_infer(None, ast_ty.span) 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); 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)] #[diag(hir_analysis_track_caller_on_main)]
pub(crate) struct TrackCallerOnMain { pub(crate) struct TrackCallerOnMain {
#[primary_span] #[primary_span]
#[suggestion(applicability = "maybe-incorrect", code = "")]
pub span: Span, pub span: Span,
#[label] #[label(hir_analysis_track_caller_on_main)]
pub annotated: Span, pub annotated: Span,
} }

View file

@ -358,7 +358,7 @@ impl<'a> State<'a> {
self.print_anon_const(e); self.print_anon_const(e);
self.word(")"); self.word(")");
} }
hir::TyKind::Err => { hir::TyKind::Err(_) => {
self.popen(); self.popen();
self.word("/*ERROR*/"); self.word("/*ERROR*/");
self.pclose(); self.pclose();
@ -1559,7 +1559,7 @@ impl<'a> State<'a> {
self.word_space("yield"); self.word_space("yield");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP); self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
} }
hir::ExprKind::Err => { hir::ExprKind::Err(_) => {
self.popen(); self.popen();
self.word("/*ERROR*/"); self.word("/*ERROR*/");
self.pclose(); 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::Field(base, field) => self.check_field(expr, &base, field, expected),
ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr), ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr),
ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src), 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::Continue(..)
| hir::ExprKind::Lit(..) | hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..) | hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Err => {} | hir::ExprKind::Err(_) => {}
hir::ExprKind::Loop(blk, ..) => { hir::ExprKind::Loop(blk, ..) => {
self.walk_block(blk); self.walk_block(blk);

View file

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

View file

@ -383,7 +383,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::Repeat(..) | hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..) | hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..) | 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>( pub fn elaborate_obligations<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
mut obligations: Vec<PredicateObligation<'tcx>>, obligations: Vec<PredicateObligation<'tcx>>,
) -> Elaborator<'tcx> { ) -> Elaborator<'tcx> {
let mut visited = PredicateSet::new(tcx); let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
obligations.retain(|obligation| visited.insert(obligation.predicate)); elaborator.extend_deduped(obligations);
Elaborator { stack: obligations, visited } elaborator
} }
fn predicate_obligation<'tcx>( fn predicate_obligation<'tcx>(
@ -132,6 +132,15 @@ fn predicate_obligation<'tcx>(
} }
impl<'tcx> Elaborator<'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> { pub fn filter_to_traits(self) -> FilterToTraits<Self> {
FilterToTraits::new(self) FilterToTraits::new(self)
} }
@ -172,15 +181,7 @@ impl<'tcx> Elaborator<'tcx> {
) )
}); });
debug!(?data, ?obligations, "super_predicates"); debug!(?data, ?obligations, "super_predicates");
self.extend_deduped(obligations);
// 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);
} }
ty::PredicateKind::WellFormed(..) => { ty::PredicateKind::WellFormed(..) => {
// Currently, we do not elaborate WF predicates, // Currently, we do not elaborate WF predicates,
@ -237,10 +238,9 @@ impl<'tcx> Elaborator<'tcx> {
return; return;
} }
let visited = &mut self.visited;
let mut components = smallvec![]; let mut components = smallvec![];
push_outlives_components(tcx, ty_max, &mut components); push_outlives_components(tcx, ty_max, &mut components);
self.stack.extend( self.extend_deduped(
components components
.into_iter() .into_iter()
.filter_map(|component| match component { .filter_map(|component| match component {
@ -280,7 +280,6 @@ impl<'tcx> Elaborator<'tcx> {
.map(|predicate_kind| { .map(|predicate_kind| {
bound_predicate.rebind(predicate_kind).to_predicate(tcx) bound_predicate.rebind(predicate_kind).to_predicate(tcx)
}) })
.filter(|&predicate| visited.insert(predicate))
.map(|predicate| { .map(|predicate| {
predicate_obligation( predicate_obligation(
predicate, 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::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) }, 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 } 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(), span: self.prev_token.span.shrink_to_lo(),
tokens: None, 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); let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
return Some(match (struct_expr, block_tail) { return Some(match (struct_expr, block_tail) {
(Ok(expr), Err(mut err)) => { (Ok(expr), Err(mut err)) => {
@ -1624,7 +1624,7 @@ impl<'a> Parser<'a> {
// Handle `await { <expr> }`. // Handle `await { <expr> }`.
// This needs to be handled separately from the next arm to avoid // This needs to be handled separately from the next arm to avoid
// interpreting `await { <expr> }?` as `<expr>?.await`. // 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 { } else {
self.parse_expr() self.parse_expr()
} }

View file

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

View file

@ -1331,7 +1331,7 @@ impl<'a> Parser<'a> {
}; };
let disr_expr = 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 { let vr = ast::Variant {
ident, ident,
@ -1722,7 +1722,7 @@ impl<'a> Parser<'a> {
} }
if self.token.kind == token::Eq { if self.token.kind == token::Eq {
self.bump(); 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); 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") self.struct_span_err(sp, "default values on `struct` fields aren't supported")
.span_suggestion( .span_suggestion(

View file

@ -653,7 +653,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> { pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
// Parse const argument. // Parse const argument.
let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind { 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 { } else {
self.handle_unambiguous_unbraced_const_arg()? 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)) { let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) {
this.parse_struct_expr(None, path, true)? this.parse_expr_struct(None, path, true)?
} else { } else {
let hi = this.prev_token.span; let hi = this.prev_token.span;
this.mk_expr(lo.to(hi), ExprKind::Path(None, path)) this.mk_expr(lo.to(hi), ExprKind::Path(None, path))
}; };
let expr = this.with_res(Restrictions::STMT_EXPR, |this| { 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 // `DUMMY_SP` will get overwritten later in this function
Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None)) 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, // Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression // since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| { let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
this.parse_assoc_expr_with( this.parse_expr_assoc_with(
0, 0,
LhsExpr::AlreadyParsed { expr, starts_statement: true }, 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. // 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.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?; 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_expr_dot_or_call_with(e, lo, attrs)?;
let e = self.parse_assoc_expr_with( let e = self.parse_expr_assoc_with(
0, 0,
LhsExpr::AlreadyParsed { expr: e, starts_statement: false }, 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 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)) { if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?; 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. // To avoid ambiguity, the type is surrounded by parentheses.
fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> { fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; 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))?; self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
Ok(TyKind::Typeof(expr)) Ok(TyKind::Typeof(expr))
} }

View file

@ -475,7 +475,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::InlineAsm(..) | hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..) | hir::ExprKind::Box(..)
| hir::ExprKind::Type(..) | hir::ExprKind::Type(..)
| hir::ExprKind::Err | hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => { | hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
intravisit::walk_expr(self, expr); intravisit::walk_expr(self, expr);
@ -1129,7 +1129,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::Lit(..) hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..) | hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Err | hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ, | 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::Yield(..)
| hir::ExprKind::Box(..) | hir::ExprKind::Box(..)
| hir::ExprKind::Type(..) | 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); hir::intravisit::walk_expr(self, expr);
} }
ExprKind::Err => { ExprKind::Err(_) => {
self.items.push((ItemKind::Err, span)); self.items.push((ItemKind::Err, span));
} }
} }

View file

@ -2149,3 +2149,17 @@ where
Hash::hash(&len, hasher); 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, frem_fast,
from, from,
from_desugaring, from_desugaring,
from_fn,
from_iter, from_iter,
from_method, from_method,
from_output, from_output,

View file

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

View file

@ -3107,6 +3107,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.tcx.def_span(def_id), self.tcx.def_span(def_id),
"required because it's used within this closure", "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), _ => err.note(&msg),
}; };
} }

View file

@ -2300,12 +2300,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Float(_) | ty::Float(_)
| ty::FnDef(..) | ty::FnDef(..)
| ty::FnPtr(_) | ty::FnPtr(_)
| ty::Str
| ty::Error(_) | ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never | ty::Never
| ty::Char => ty::Binder::dummy(Vec::new()), | 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::Placeholder(..)
| ty::Dynamic(..) | ty::Dynamic(..)
| ty::Param(..) | ty::Param(..)

View file

@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
return; return;
} }
if target_cap < self.capacity() { // There are three cases of interest:
// There are three cases of interest: // All elements are out of desired bounds
// All elements are out of desired bounds // Elements are contiguous, and tail is out of desired bounds
// Elements are contiguous, and head is out of desired bounds // Elements are discontiguous
// Elements are discontiguous, and tail is out of desired bounds //
// // At all other times, element positions are unaffected.
// At all other times, element positions are unaffected.
//
// Indicates that elements at the head should be moved.
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len)); // `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
// Move elements from out of desired bounds (positions after target_cap) // overflow.
if self.len == 0 { let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
self.head = 0;
} else if self.head >= target_cap && tail_outside { if self.len == 0 {
// H := head self.head = 0;
// L := last element } else if self.head >= target_cap && tail_outside {
// H L // Head and tail are both out of bounds, so copy all of them to the front.
// [. . . . . . . . o o o o o o o . ] //
// H L // H := head
// [o o o o o o o . ] // L := last element
unsafe { // H L
// nonoverlapping because self.head >= target_cap >= self.len // [. . . . . . . . o o o o o o o . ]
self.copy_nonoverlapping(self.head, 0, self.len); // H L
} // [o o o o o o o . ]
self.head = 0; unsafe {
} else if self.head < target_cap && tail_outside { // nonoverlapping because `self.head >= target_cap >= self.len`.
// H := head self.copy_nonoverlapping(self.head, 0, self.len);
// 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;
} }
self.head = 0;
self.buf.shrink_to_fit(target_cap); } else if self.head < target_cap && tail_outside {
// Head is in bounds, tail is out of bounds.
debug_assert!(self.head < self.capacity() || self.capacity() == 0); // Copy the overflowing part to the beginning of the
debug_assert!(self.len <= self.capacity()); // 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 /// 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] #[test]
fn test_shrink_to_fit() { fn test_shrink_to_fit() {
// This test checks that every single combination of head and tail position, // 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] #[const_trait]
pub trait From<T>: Sized { pub trait From<T>: Sized {
/// Converts to this type from the input type. /// Converts to this type from the input type.
#[lang = "from"] #[rustc_diagnostic_item = "from_fn"]
#[must_use] #[must_use]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn from(value: T) -> Self; fn from(value: T) -> Self;

View file

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

View file

@ -4,19 +4,24 @@ macro_rules! uint_impl {
ActualT = $ActualT:ident, ActualT = $ActualT:ident,
SignedT = $SignedT:ident, SignedT = $SignedT:ident,
NonZeroT = $NonZeroT:ident, NonZeroT = $NonZeroT:ident,
BITS = $BITS:expr,
MAX = $MaxV:expr, // There are all for use *only* in doc comments.
rot = $rot:expr, // As such, they're all passed as literals -- passing them as a string
rot_op = $rot_op:expr, // literal is fine if they need to be multiple code tokens.
rot_result = $rot_result:expr, // In non-comments, use the associated constants rather than these.
swap_op = $swap_op:expr, BITS = $BITS:literal,
swapped = $swapped:expr, MAX = $MaxV:literal,
reversed = $reversed:expr, rot = $rot:literal,
le_bytes = $le_bytes:expr, rot_op = $rot_op:literal,
be_bytes = $be_bytes:expr, 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, to_xe_bytes_doc = $to_xe_bytes_doc:expr,
from_xe_bytes_doc = $from_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. /// 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), ");")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ``` /// ```
#[stable(feature = "int_bits_const", since = "1.53.0")] #[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. /// 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 // SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds // out of bounds
unsafe { 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 // SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds // out of bounds
unsafe { 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"] without modifying the original"]
#[inline(always)] #[inline(always)]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { 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. /// Shifts self right by `rhs` bits.
@ -1885,7 +1890,7 @@ macro_rules! uint_impl {
without modifying the original"] without modifying the original"]
#[inline(always)] #[inline(always)]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { 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. /// 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))), TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. // 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()), .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) Position::ReborrowStable(precedence)
}, },
}; };
@ -1038,7 +1038,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
if self.0 if self.0
|| matches!( || matches!(
ty.kind, ty.kind,
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
) )
{ {
self.0 = true; 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::Path(_)
| ExprKind::ConstBlock(_) | ExprKind::ConstBlock(_)
| ExprKind::Lit(_) | 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::ConstBlock(_) |
ExprKind::Continue(_) | ExprKind::Continue(_) |
ExprKind::DropTemps(_) | ExprKind::DropTemps(_) |
ExprKind::Err | ExprKind::Err(_) |
ExprKind::InlineAsm(_) | ExprKind::InlineAsm(_) |
ExprKind::Let(_) | ExprKind::Let(_) |
ExprKind::Lit(_) | ExprKind::Lit(_) |

View file

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

View file

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

View file

@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
} }
if_chain! { 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); if same_type_and_consts(a, b);
then { then {

View file

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

View file

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

View file

@ -714,7 +714,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
} }
self.hash_pat(pat); self.hash_pat(pat);
}, },
ExprKind::Err => {}, ExprKind::Err(_) => {},
ExprKind::Lit(ref l) => { ExprKind::Lit(ref l) => {
l.node.hash(&mut self.s); l.node.hash(&mut self.s);
}, },
@ -986,7 +986,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Typeof(anon_const) => { TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body); 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::Ret(..)
| hir::ExprKind::Struct(..) | hir::ExprKind::Struct(..)
| hir::ExprKind::Tup(..) | 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::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
hir::ExprKind::Assign(lhs, rhs, _) => { hir::ExprKind::Assign(lhs, rhs, _) => {
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span)) 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::Path(_)
| ExprKind::Continue(_) | ExprKind::Continue(_)
| ExprKind::InlineAsm(_) | ExprKind::InlineAsm(_)
| ExprKind::Err => (), | ExprKind::Err(_) => (),
} }
ControlFlow::Continue(()) ControlFlow::Continue(())
} }

View file

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

View file

@ -2,9 +2,6 @@
extern crate rustc_driver; extern crate rustc_driver;
// We use the function we generate from `register_diagnostics!`.
use crate::error_codes::error_codes;
use std::env; use std::env;
use std::error::Error; use std::error::Error;
use std::fs::{self, File}; use std::fs::{self, File};
@ -17,22 +14,6 @@ use std::str::FromStr;
use mdbook::book::{parse_summary, BookItem, Chapter}; use mdbook::book::{parse_summary, BookItem, Chapter};
use mdbook::{Config, MDBook}; 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 { enum OutputFormat {
HTML, HTML,
Markdown, Markdown,
@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
write!(output_file, "# Rust Compiler Error Index\n")?; write!(output_file, "# Rust Compiler Error Index\n")?;
for (err_code, description) in error_codes().iter() { for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
match description { write!(output_file, "## {}\n{}\n", err_code, description)?
Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
None => {}
}
} }
Ok(()) 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()); let mut chapters = Vec::with_capacity(err_codes.len());
for (err_code, explanation) in err_codes.iter() { 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); let content = add_rust_attribute_on_codeblock(explanation);
chapters.push(BookItem::Chapter(Chapter { chapters.push(BookItem::Chapter(Chapter {
name: err_code.to_string(), name: err_code.to_string(),
content: format!("# Error code {}\n\n{}\n", err_code, content), content: format!("# Error code {}\n\n{}\n", err_code, content),
number: None, number: None,
sub_items: Vec::new(), sub_items: Vec::new(),
// We generate it into the `error_codes` folder. // We generate it into the `error_codes` folder.
path: Some(PathBuf::from(&format!("{}.html", err_code))), path: Some(PathBuf::from(&format!("{}.html", err_code))),
source_path: None, source_path: None,
parent_names: Vec::new(), parent_names: Vec::new(),
})); }));
} else {
introduction.push_str(&format!(" * {}\n", err_code));
}
} }
let mut config = Config::from_str(include_str!("book_config.toml"))?; 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(); let mut errors = Vec::new();
// Stage 1: create list // 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!("Found {} error codes", error_codes.len());
println!("Highest error code: `{}`", error_codes.iter().max().unwrap()); 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`. /// 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 path = root_path.join(Path::new(ERROR_CODES_PATH));
let file = let file =
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}")); fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
let mut error_codes = Vec::new(); let mut error_codes = Vec::new();
let mut reached_undocumented_codes = false;
for line in file.lines() { for line in file.lines() {
let line = line.trim(); let line = line.trim();
if !reached_undocumented_codes && line.starts_with('E') { if line.starts_with('E') {
let split_line = line.split_once(':'); 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. // 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); 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 --> $DIR/error-with-main.rs:1:1
| |
LL | #[track_caller] LL | #[track_caller]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^ help: remove this annotation
LL | fn main() { LL | fn main() {
| --------- `main` function is not allowed to be `#[track_caller]` | --------- `main` function is not allowed to be `#[track_caller]`