mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
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:
commit
c4e0cd9660
@ -1445,6 +1445,7 @@ name = "error_index_generator"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"mdbook",
|
||||
"rustc_error_codes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -88,8 +88,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
|
||||
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
|
||||
} else {
|
||||
self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
|
||||
hir::ExprKind::Err
|
||||
let guar = self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
|
||||
hir::ExprKind::Err(guar)
|
||||
}
|
||||
} else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
|
||||
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
|
||||
@ -266,8 +266,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
|
||||
}
|
||||
ExprKind::Underscore => {
|
||||
self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
|
||||
hir::ExprKind::Err
|
||||
let guar = self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
|
||||
hir::ExprKind::Err(guar)
|
||||
}
|
||||
ExprKind::Path(qself, path) => {
|
||||
let qpath = self.lower_qpath(
|
||||
@ -299,8 +299,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let rest = match &se.rest {
|
||||
StructRest::Base(e) => Some(self.lower_expr(e)),
|
||||
StructRest::Rest(sp) => {
|
||||
self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
|
||||
Some(&*self.arena.alloc(self.expr_err(*sp)))
|
||||
let guar =
|
||||
self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
|
||||
Some(&*self.arena.alloc(self.expr_err(*sp, guar)))
|
||||
}
|
||||
StructRest::None => None,
|
||||
};
|
||||
@ -318,7 +319,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
)
|
||||
}
|
||||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
||||
ExprKind::Err => hir::ExprKind::Err,
|
||||
ExprKind::Err => hir::ExprKind::Err(
|
||||
self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"),
|
||||
),
|
||||
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
||||
|
||||
ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
|
||||
@ -761,7 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.expr_ident_mut(span, task_context_ident, task_context_hid)
|
||||
} else {
|
||||
// Use of `await` outside of an async context, we cannot use `task_context` here.
|
||||
self.expr_err(span)
|
||||
self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id"))
|
||||
};
|
||||
let new_unchecked = self.expr_call_lang_item_fn_mut(
|
||||
span,
|
||||
|
@ -102,7 +102,12 @@ fn make_count<'hir>(
|
||||
let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]);
|
||||
ctx.expr_call_mut(sp, count_param, value)
|
||||
} else {
|
||||
ctx.expr(sp, hir::ExprKind::Err)
|
||||
ctx.expr(
|
||||
sp,
|
||||
hir::ExprKind::Err(
|
||||
ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
None => ctx.expr_lang_item_type_relative(sp, hir::LangItem::FormatCount, sym::Implied),
|
||||
@ -135,7 +140,10 @@ fn make_format_spec<'hir>(
|
||||
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
|
||||
ctx.expr_usize(sp, i)
|
||||
}
|
||||
Err(_) => ctx.expr(sp, hir::ExprKind::Err),
|
||||
Err(_) => ctx.expr(
|
||||
sp,
|
||||
hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")),
|
||||
),
|
||||
};
|
||||
let &FormatOptions {
|
||||
ref width,
|
||||
@ -294,7 +302,12 @@ fn expand_format_args<'hir>(
|
||||
));
|
||||
make_argument(ctx, sp, arg, ty)
|
||||
} else {
|
||||
ctx.expr(macsp, hir::ExprKind::Err)
|
||||
ctx.expr(
|
||||
macsp,
|
||||
hir::ExprKind::Err(
|
||||
ctx.tcx.sess.delay_span_bug(macsp, format!("no arg at {arg_index}")),
|
||||
),
|
||||
)
|
||||
}
|
||||
}));
|
||||
let elements: Vec<_> = arguments
|
||||
|
@ -7,6 +7,7 @@ use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::AssocCtxt;
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
@ -284,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
|
||||
},
|
||||
ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
|
||||
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: Some(ty), .. }) => {
|
||||
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
|
||||
// We lower
|
||||
//
|
||||
// type Foo = impl Trait
|
||||
@ -299,18 +300,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
&generics,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
}
|
||||
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => {
|
||||
let mut generics = generics.clone();
|
||||
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
|
||||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
id,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.arena.alloc(this.ty(span, hir::TyKind::Err)),
|
||||
|this| match ty {
|
||||
None => {
|
||||
let guar = this.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
"expected to lower type alias type, but it was missing",
|
||||
);
|
||||
this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
|
||||
}
|
||||
Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
|
||||
},
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
}
|
||||
@ -798,8 +797,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
|
||||
/// Construct `ExprKind::Err` for the given `span`.
|
||||
pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
|
||||
self.expr(span, hir::ExprKind::Err)
|
||||
pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
|
||||
self.expr(span, hir::ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
||||
@ -847,7 +846,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
None => {
|
||||
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
|
||||
let guar = this.tcx.sess.delay_span_bug(
|
||||
i.span,
|
||||
"expected to lower associated type, but it was missing",
|
||||
);
|
||||
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
|
||||
hir::ImplItemKind::Type(ty)
|
||||
}
|
||||
Some(ty) => {
|
||||
@ -973,7 +976,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
|
||||
match block {
|
||||
Some(block) => self.lower_block_expr(block),
|
||||
None => self.expr_err(span),
|
||||
None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")),
|
||||
}
|
||||
}
|
||||
|
||||
@ -983,7 +986,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
&[],
|
||||
match expr {
|
||||
Some(expr) => this.lower_expr_mut(expr),
|
||||
None => this.expr_err(span),
|
||||
None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")),
|
||||
},
|
||||
)
|
||||
})
|
||||
|
@ -1082,11 +1082,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
hir::TypeBindingKind::Constraint { bounds }
|
||||
}
|
||||
DesugarKind::Error(position) => {
|
||||
self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
|
||||
let guar = self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
|
||||
span: constraint.span,
|
||||
position: DiagnosticArgFromDisplay(position),
|
||||
});
|
||||
let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err));
|
||||
let err_ty =
|
||||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::TypeBindingKind::Equality { term: err_ty.into() }
|
||||
}
|
||||
}
|
||||
@ -1255,7 +1256,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
|
||||
let kind = match &t.kind {
|
||||
TyKind::Infer => hir::TyKind::Infer,
|
||||
TyKind::Err => hir::TyKind::Err,
|
||||
TyKind::Err => {
|
||||
hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered"))
|
||||
}
|
||||
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
|
||||
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
|
||||
TyKind::Ref(region, mt) => {
|
||||
@ -1381,7 +1384,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
path
|
||||
}
|
||||
ImplTraitContext::FeatureGated(position, feature) => {
|
||||
self.tcx
|
||||
let guar = self
|
||||
.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedImplTrait {
|
||||
@ -1391,24 +1395,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
*feature,
|
||||
)
|
||||
.emit();
|
||||
hir::TyKind::Err
|
||||
hir::TyKind::Err(guar)
|
||||
}
|
||||
ImplTraitContext::Disallowed(position) => {
|
||||
self.tcx.sess.emit_err(MisplacedImplTrait {
|
||||
let guar = self.tcx.sess.emit_err(MisplacedImplTrait {
|
||||
span: t.span,
|
||||
position: DiagnosticArgFromDisplay(position),
|
||||
});
|
||||
hir::TyKind::Err
|
||||
hir::TyKind::Err(guar)
|
||||
}
|
||||
}
|
||||
}
|
||||
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
|
||||
TyKind::CVarArgs => {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
let guar = self.tcx.sess.delay_span_bug(
|
||||
t.span,
|
||||
"`TyKind::CVarArgs` should have been handled elsewhere",
|
||||
);
|
||||
hir::TyKind::Err
|
||||
hir::TyKind::Err(guar)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -330,8 +330,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
ExprKind::Path(..) if allow_paths => {}
|
||||
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
|
||||
_ => {
|
||||
self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
|
||||
return self.arena.alloc(self.expr_err(expr.span));
|
||||
let guar = self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
|
||||
return self.arena.alloc(self.expr_err(expr.span, guar));
|
||||
}
|
||||
}
|
||||
self.lower_expr(expr)
|
||||
|
@ -152,7 +152,7 @@ pub fn parse_asm_args<'a>(
|
||||
ast::InlineAsmOperand::InOut { reg, expr, late: true }
|
||||
}
|
||||
} else if p.eat_keyword(kw::Const) {
|
||||
let anon_const = p.parse_anon_const_expr()?;
|
||||
let anon_const = p.parse_expr_anon_const()?;
|
||||
ast::InlineAsmOperand::Const { anon_const }
|
||||
} else if p.eat_keyword(sym::sym) {
|
||||
let expr = p.parse_expr()?;
|
||||
|
@ -485,7 +485,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
|
||||
let normalised =
|
||||
if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
|
||||
match registry.try_find_description(&normalised) {
|
||||
Ok(Some(description)) => {
|
||||
Ok(description) => {
|
||||
let mut is_in_code_block = false;
|
||||
let mut text = String::new();
|
||||
// Slice off the leading newline and print.
|
||||
@ -509,9 +509,6 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
|
||||
print!("{text}");
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
early_error(output, &format!("no extended information for {code}"));
|
||||
}
|
||||
Err(InvalidErrorCode) => {
|
||||
early_error(output, &format!("{code} is not a valid error code"));
|
||||
}
|
||||
|
@ -513,7 +513,9 @@ E0790: include_str!("./error_codes/E0790.md"),
|
||||
E0791: include_str!("./error_codes/E0791.md"),
|
||||
E0792: include_str!("./error_codes/E0792.md"),
|
||||
E0793: include_str!("./error_codes/E0793.md"),
|
||||
;
|
||||
}
|
||||
|
||||
// Undocumented removed error codes. Note that many removed error codes are documented.
|
||||
// E0006, // merged with E0005
|
||||
// E0008, // cannot bind by-move into a pattern guard
|
||||
// E0019, // merged into E0015
|
||||
@ -570,7 +572,7 @@ E0793: include_str!("./error_codes/E0793.md"),
|
||||
// E0246, // invalid recursive type
|
||||
// E0247,
|
||||
// E0248, // value used as a type, now reported earlier during resolution
|
||||
// as E0412
|
||||
// // as E0412
|
||||
// E0249,
|
||||
// E0257,
|
||||
// E0258,
|
||||
@ -631,14 +633,14 @@ E0793: include_str!("./error_codes/E0793.md"),
|
||||
// E0558, // replaced with a generic attribute input check
|
||||
// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
|
||||
// E0564, // only named lifetimes are allowed in `impl Trait`,
|
||||
// but `{}` was found in the type `{}`
|
||||
// // but `{}` was found in the type `{}`
|
||||
// E0598, // lifetime of {} is too short to guarantee its contents can be...
|
||||
// E0611, // merged into E0616
|
||||
// E0612, // merged into E0609
|
||||
// E0613, // Removed (merged with E0609)
|
||||
// E0629, // missing 'feature' (rustc_const_unstable)
|
||||
// E0630, // rustc_const_unstable attribute must be paired with stable/unstable
|
||||
// attribute
|
||||
// // attribute
|
||||
// E0645, // trait aliases not finished
|
||||
// E0694, // an unknown tool name found in scoped attributes
|
||||
// E0702, // replaced with a generic attribute input check
|
||||
@ -647,4 +649,3 @@ E0793: include_str!("./error_codes/E0793.md"),
|
||||
// E0721, // `await` keyword
|
||||
// E0723, // unstable feature in `const` context
|
||||
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
|
||||
}
|
||||
|
@ -5,10 +5,9 @@
|
||||
//! the goal being to make their maintenance easier.
|
||||
|
||||
macro_rules! register_diagnostics {
|
||||
($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
|
||||
pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[
|
||||
$( (stringify!($ecode), Some($message)), )*
|
||||
$( (stringify!($code), None), )*
|
||||
($($ecode:ident: $message:expr,)*) => (
|
||||
pub static DIAGNOSTICS: &[(&str, &str)] = &[
|
||||
$( (stringify!($ecode), $message), )*
|
||||
];
|
||||
)
|
||||
}
|
||||
|
@ -580,7 +580,7 @@ impl DiagnosticCode {
|
||||
let je_result =
|
||||
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
|
||||
|
||||
DiagnosticCode { code: s, explanation: je_result.unwrap_or(None) }
|
||||
DiagnosticCode { code: s, explanation: je_result.ok() }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ pub use rustc_error_messages::{
|
||||
pub use rustc_lint_defs::{pluralize, Applicability};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::HashStableContext;
|
||||
pub use rustc_span::ErrorGuaranteed;
|
||||
use rustc_span::{Loc, Span};
|
||||
|
||||
use std::borrow::Cow;
|
||||
@ -1477,9 +1477,7 @@ impl HandlerInner {
|
||||
.emitted_diagnostic_codes
|
||||
.iter()
|
||||
.filter_map(|x| match &x {
|
||||
DiagnosticId::Error(s)
|
||||
if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
|
||||
{
|
||||
DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => {
|
||||
Some(s.clone())
|
||||
}
|
||||
_ => None,
|
||||
@ -1846,17 +1844,3 @@ pub enum TerminalUrl {
|
||||
Yes,
|
||||
Auto,
|
||||
}
|
||||
|
||||
/// Useful type to use with `Result<>` indicate that an error has already
|
||||
/// been reported to the user, so no need to continue checking.
|
||||
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct ErrorGuaranteed(());
|
||||
|
||||
impl ErrorGuaranteed {
|
||||
/// To be used only if you really know what you are doing... ideally, we would find a way to
|
||||
/// eliminate all calls to this method.
|
||||
pub fn unchecked_claim_error_was_emitted() -> Self {
|
||||
ErrorGuaranteed(())
|
||||
}
|
||||
}
|
||||
|
@ -5,21 +5,17 @@ pub struct InvalidErrorCode;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Registry {
|
||||
long_descriptions: FxHashMap<&'static str, Option<&'static str>>,
|
||||
long_descriptions: FxHashMap<&'static str, &'static str>,
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
|
||||
pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
|
||||
Registry { long_descriptions: long_descriptions.iter().copied().collect() }
|
||||
}
|
||||
|
||||
/// Returns `InvalidErrorCode` if the code requested does not exist in the
|
||||
/// registry. Otherwise, returns an `Option` where `None` means the error
|
||||
/// code is valid but has no extended information.
|
||||
pub fn try_find_description(
|
||||
&self,
|
||||
code: &str,
|
||||
) -> Result<Option<&'static str>, InvalidErrorCode> {
|
||||
/// registry.
|
||||
pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
|
||||
self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
|
||||
}
|
||||
}
|
||||
|
@ -369,10 +369,10 @@ impl<'hir> GenericArgs<'hir> {
|
||||
|
||||
pub fn has_err(&self) -> bool {
|
||||
self.args.iter().any(|arg| match arg {
|
||||
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
|
||||
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)),
|
||||
_ => false,
|
||||
}) || self.bindings.iter().any(|arg| match arg.kind {
|
||||
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err),
|
||||
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err(_)),
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
@ -1688,7 +1688,7 @@ impl Expr<'_> {
|
||||
ExprKind::Struct(..) => ExprPrecedence::Struct,
|
||||
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
|
||||
ExprKind::Yield(..) => ExprPrecedence::Yield,
|
||||
ExprKind::Err => ExprPrecedence::Err,
|
||||
ExprKind::Err(_) => ExprPrecedence::Err,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1754,7 +1754,7 @@ impl Expr<'_> {
|
||||
| ExprKind::Yield(..)
|
||||
| ExprKind::Cast(..)
|
||||
| ExprKind::DropTemps(..)
|
||||
| ExprKind::Err => false,
|
||||
| ExprKind::Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1840,7 +1840,7 @@ impl Expr<'_> {
|
||||
| ExprKind::Binary(..)
|
||||
| ExprKind::Yield(..)
|
||||
| ExprKind::DropTemps(..)
|
||||
| ExprKind::Err => true,
|
||||
| ExprKind::Err(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2013,7 +2013,7 @@ pub enum ExprKind<'hir> {
|
||||
Yield(&'hir Expr<'hir>, YieldSource),
|
||||
|
||||
/// A placeholder for an expression that wasn't syntactically well formed in some way.
|
||||
Err,
|
||||
Err(rustc_span::ErrorGuaranteed),
|
||||
}
|
||||
|
||||
/// Represents an optionally `Self`-qualified value/type path or associated extension.
|
||||
@ -2676,7 +2676,7 @@ pub enum TyKind<'hir> {
|
||||
/// specified. This can appear anywhere in a type.
|
||||
Infer,
|
||||
/// Placeholder for a type that has failed to be defined.
|
||||
Err,
|
||||
Err(rustc_span::ErrorGuaranteed),
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
|
@ -790,7 +790,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||
ExprKind::Yield(ref subexpression, _) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
}
|
||||
ExprKind::Lit(_) | ExprKind::Err => {}
|
||||
ExprKind::Lit(_) | ExprKind::Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,7 +844,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
||||
visitor.visit_lifetime(lifetime);
|
||||
}
|
||||
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
|
||||
TyKind::Infer | TyKind::Err => {}
|
||||
TyKind::Infer | TyKind::Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,8 +302,6 @@ language_item_table! {
|
||||
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
|
||||
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
|
||||
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
|
||||
|
||||
|
@ -131,7 +131,7 @@ hir_analysis_where_clause_on_main = `main` function is not allowed to have a `wh
|
||||
.label = `main` cannot have a `where` clause
|
||||
|
||||
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
|
||||
.label = `main` function is not allowed to be `#[track_caller]`
|
||||
.suggestion = remove this annotation
|
||||
|
||||
hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
|
||||
.label = `start` is not allowed to be `#[track_caller]`
|
||||
|
@ -3113,7 +3113,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// handled specially and will not descend into this routine.
|
||||
self.ty_infer(None, ast_ty.span)
|
||||
}
|
||||
hir::TyKind::Err => tcx.ty_error_misc(),
|
||||
hir::TyKind::Err(guar) => tcx.ty_error(*guar),
|
||||
};
|
||||
|
||||
self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
|
||||
|
@ -329,8 +329,9 @@ pub(crate) struct WhereClauseOnMain {
|
||||
#[diag(hir_analysis_track_caller_on_main)]
|
||||
pub(crate) struct TrackCallerOnMain {
|
||||
#[primary_span]
|
||||
#[suggestion(applicability = "maybe-incorrect", code = "")]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
#[label(hir_analysis_track_caller_on_main)]
|
||||
pub annotated: Span,
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ impl<'a> State<'a> {
|
||||
self.print_anon_const(e);
|
||||
self.word(")");
|
||||
}
|
||||
hir::TyKind::Err => {
|
||||
hir::TyKind::Err(_) => {
|
||||
self.popen();
|
||||
self.word("/*ERROR*/");
|
||||
self.pclose();
|
||||
@ -1559,7 +1559,7 @@ impl<'a> State<'a> {
|
||||
self.word_space("yield");
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
|
||||
}
|
||||
hir::ExprKind::Err => {
|
||||
hir::ExprKind::Err(_) => {
|
||||
self.popen();
|
||||
self.word("/*ERROR*/");
|
||||
self.pclose();
|
||||
|
@ -354,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected),
|
||||
ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr),
|
||||
ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src),
|
||||
hir::ExprKind::Err => tcx.ty_error_misc(),
|
||||
hir::ExprKind::Err(guar) => tcx.ty_error(guar),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
hir::ExprKind::Continue(..)
|
||||
| hir::ExprKind::Lit(..)
|
||||
| hir::ExprKind::ConstBlock(..)
|
||||
| hir::ExprKind::Err => {}
|
||||
| hir::ExprKind::Err(_) => {}
|
||||
|
||||
hir::ExprKind::Loop(blk, ..) => {
|
||||
self.walk_block(blk);
|
||||
|
@ -219,7 +219,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
|
||||
| ExprKind::Struct(..)
|
||||
| ExprKind::Repeat(..)
|
||||
| ExprKind::Yield(..)
|
||||
| ExprKind::Err => (),
|
||||
| ExprKind::Err(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -483,7 +483,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
|
||||
| ExprKind::Closure { .. }
|
||||
| ExprKind::ConstBlock(..)
|
||||
| ExprKind::DropTemps(..)
|
||||
| ExprKind::Err
|
||||
| ExprKind::Err(_)
|
||||
| ExprKind::Field(..)
|
||||
| ExprKind::Index(..)
|
||||
| ExprKind::InlineAsm(..)
|
||||
|
@ -383,7 +383,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
| hir::ExprKind::Repeat(..)
|
||||
| hir::ExprKind::InlineAsm(..)
|
||||
| hir::ExprKind::Box(..)
|
||||
| hir::ExprKind::Err => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
|
||||
| hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,11 +116,11 @@ pub fn elaborate_predicates_with_span<'tcx>(
|
||||
|
||||
pub fn elaborate_obligations<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut obligations: Vec<PredicateObligation<'tcx>>,
|
||||
obligations: Vec<PredicateObligation<'tcx>>,
|
||||
) -> Elaborator<'tcx> {
|
||||
let mut visited = PredicateSet::new(tcx);
|
||||
obligations.retain(|obligation| visited.insert(obligation.predicate));
|
||||
Elaborator { stack: obligations, visited }
|
||||
let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
|
||||
elaborator.extend_deduped(obligations);
|
||||
elaborator
|
||||
}
|
||||
|
||||
fn predicate_obligation<'tcx>(
|
||||
@ -132,6 +132,15 @@ fn predicate_obligation<'tcx>(
|
||||
}
|
||||
|
||||
impl<'tcx> Elaborator<'tcx> {
|
||||
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>) {
|
||||
// Only keep those bounds that we haven't already seen.
|
||||
// This is necessary to prevent infinite recursion in some
|
||||
// cases. One common case is when people define
|
||||
// `trait Sized: Sized { }` rather than `trait Sized { }`.
|
||||
// let visited = &mut self.visited;
|
||||
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
|
||||
}
|
||||
|
||||
pub fn filter_to_traits(self) -> FilterToTraits<Self> {
|
||||
FilterToTraits::new(self)
|
||||
}
|
||||
@ -172,15 +181,7 @@ impl<'tcx> Elaborator<'tcx> {
|
||||
)
|
||||
});
|
||||
debug!(?data, ?obligations, "super_predicates");
|
||||
|
||||
// Only keep those bounds that we haven't already seen.
|
||||
// This is necessary to prevent infinite recursion in some
|
||||
// cases. One common case is when people define
|
||||
// `trait Sized: Sized { }` rather than `trait Sized { }`.
|
||||
let visited = &mut self.visited;
|
||||
let obligations = obligations.filter(|o| visited.insert(o.predicate));
|
||||
|
||||
self.stack.extend(obligations);
|
||||
self.extend_deduped(obligations);
|
||||
}
|
||||
ty::PredicateKind::WellFormed(..) => {
|
||||
// Currently, we do not elaborate WF predicates,
|
||||
@ -237,10 +238,9 @@ impl<'tcx> Elaborator<'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let visited = &mut self.visited;
|
||||
let mut components = smallvec![];
|
||||
push_outlives_components(tcx, ty_max, &mut components);
|
||||
self.stack.extend(
|
||||
self.extend_deduped(
|
||||
components
|
||||
.into_iter()
|
||||
.filter_map(|component| match component {
|
||||
@ -280,7 +280,6 @@ impl<'tcx> Elaborator<'tcx> {
|
||||
.map(|predicate_kind| {
|
||||
bound_predicate.rebind(predicate_kind).to_predicate(tcx)
|
||||
})
|
||||
.filter(|&predicate| visited.insert(predicate))
|
||||
.map(|predicate| {
|
||||
predicate_obligation(
|
||||
predicate,
|
||||
|
@ -758,7 +758,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
|
||||
|
||||
hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
|
||||
hir::ExprKind::Err => unreachable!(),
|
||||
hir::ExprKind::Err(_) => unreachable!(),
|
||||
};
|
||||
|
||||
Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
|
||||
|
@ -693,7 +693,7 @@ impl<'a> Parser<'a> {
|
||||
span: self.prev_token.span.shrink_to_lo(),
|
||||
tokens: None,
|
||||
};
|
||||
let struct_expr = snapshot.parse_struct_expr(None, path, false);
|
||||
let struct_expr = snapshot.parse_expr_struct(None, path, false);
|
||||
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
|
||||
return Some(match (struct_expr, block_tail) {
|
||||
(Ok(expr), Err(mut err)) => {
|
||||
@ -1624,7 +1624,7 @@ impl<'a> Parser<'a> {
|
||||
// Handle `await { <expr> }`.
|
||||
// This needs to be handled separately from the next arm to avoid
|
||||
// interpreting `await { <expr> }?` as `<expr>?.await`.
|
||||
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)
|
||||
self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)
|
||||
} else {
|
||||
self.parse_expr()
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ impl<'a> Parser<'a> {
|
||||
self.collect_tokens_no_attrs(|this| this.parse_expr())
|
||||
}
|
||||
|
||||
pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
|
||||
pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> {
|
||||
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a sequence of expressions delimited by parentheses.
|
||||
fn parse_paren_expr_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
|
||||
fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
|
||||
self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r)
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ impl<'a> Parser<'a> {
|
||||
r: Restrictions,
|
||||
already_parsed_attrs: Option<AttrWrapper>,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
|
||||
self.with_res(r, |this| this.parse_expr_assoc(already_parsed_attrs))
|
||||
}
|
||||
|
||||
/// Parses an associative expression.
|
||||
@ -144,15 +144,15 @@ impl<'a> Parser<'a> {
|
||||
/// This parses an expression accounting for associativity and precedence of the operators in
|
||||
/// the expression.
|
||||
#[inline]
|
||||
fn parse_assoc_expr(
|
||||
fn parse_expr_assoc(
|
||||
&mut self,
|
||||
already_parsed_attrs: Option<AttrWrapper>,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
self.parse_assoc_expr_with(0, already_parsed_attrs.into())
|
||||
self.parse_expr_assoc_with(0, already_parsed_attrs.into())
|
||||
}
|
||||
|
||||
/// Parses an associative expression with operators of at least `min_prec` precedence.
|
||||
pub(super) fn parse_assoc_expr_with(
|
||||
pub(super) fn parse_expr_assoc_with(
|
||||
&mut self,
|
||||
min_prec: usize,
|
||||
lhs: LhsExpr,
|
||||
@ -167,9 +167,9 @@ impl<'a> Parser<'a> {
|
||||
_ => None,
|
||||
};
|
||||
if self.token.is_range_separator() {
|
||||
return self.parse_prefix_range_expr(attrs);
|
||||
return self.parse_expr_prefix_range(attrs);
|
||||
} else {
|
||||
self.parse_prefix_expr(attrs)?
|
||||
self.parse_expr_prefix(attrs)?
|
||||
}
|
||||
};
|
||||
let last_type_ascription_set = self.last_type_ascription.is_some();
|
||||
@ -293,7 +293,7 @@ impl<'a> Parser<'a> {
|
||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
||||
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
|
||||
// generalise it to the Fixity::None code.
|
||||
lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?;
|
||||
lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -306,7 +306,7 @@ impl<'a> Parser<'a> {
|
||||
Fixity::None => 1,
|
||||
};
|
||||
let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
|
||||
this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
||||
this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
||||
})?;
|
||||
|
||||
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
||||
@ -458,7 +458,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
|
||||
/// The other two variants are handled in `parse_prefix_range_expr` below.
|
||||
fn parse_range_expr(
|
||||
fn parse_expr_range(
|
||||
&mut self,
|
||||
prec: usize,
|
||||
lhs: P<Expr>,
|
||||
@ -466,7 +466,7 @@ impl<'a> Parser<'a> {
|
||||
cur_op_span: Span,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||
Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
|
||||
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -491,7 +491,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
|
||||
fn parse_prefix_range_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
||||
// Check for deprecated `...` syntax.
|
||||
if self.token == token::DotDotDot {
|
||||
self.err_dotdotdot_syntax(self.token.span);
|
||||
@ -518,7 +518,7 @@ impl<'a> Parser<'a> {
|
||||
this.bump();
|
||||
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
|
||||
// RHS must be parsed with more associativity than the dots.
|
||||
this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
||||
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
||||
.map(|x| (lo.to(x.span), Some(x)))?
|
||||
} else {
|
||||
(lo, None)
|
||||
@ -529,7 +529,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a prefix-unary-operator expr.
|
||||
fn parse_prefix_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_prefix(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
||||
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
||||
let lo = self.token.span;
|
||||
|
||||
@ -547,20 +547,20 @@ impl<'a> Parser<'a> {
|
||||
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
|
||||
match this.token.uninterpolate().kind {
|
||||
// `!expr`
|
||||
token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
|
||||
token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
|
||||
// `~expr`
|
||||
token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
|
||||
// `-expr`
|
||||
token::BinOp(token::Minus) => {
|
||||
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
|
||||
make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
|
||||
}
|
||||
// `*expr`
|
||||
token::BinOp(token::Star) => {
|
||||
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
|
||||
make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
|
||||
}
|
||||
// `&expr` and `&&expr`
|
||||
token::BinOp(token::And) | token::AndAnd => {
|
||||
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
|
||||
make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
|
||||
}
|
||||
// `+lit`
|
||||
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
|
||||
@ -579,7 +579,7 @@ impl<'a> Parser<'a> {
|
||||
this.sess.emit_err(err);
|
||||
|
||||
this.bump();
|
||||
this.parse_prefix_expr(None)
|
||||
this.parse_expr_prefix(None)
|
||||
}
|
||||
// Recover from `++x`:
|
||||
token::BinOp(token::Plus)
|
||||
@ -592,28 +592,28 @@ impl<'a> Parser<'a> {
|
||||
this.bump();
|
||||
this.bump();
|
||||
|
||||
let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
|
||||
let operand_expr = this.parse_expr_dot_or_call(Default::default())?;
|
||||
this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
|
||||
}
|
||||
token::Ident(..) if this.token.is_keyword(kw::Box) => {
|
||||
make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
|
||||
make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
|
||||
}
|
||||
token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
|
||||
make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
|
||||
}
|
||||
_ => return this.parse_dot_or_call_expr(Some(attrs)),
|
||||
_ => return this.parse_expr_dot_or_call(Some(attrs)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
|
||||
fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
|
||||
self.bump();
|
||||
let expr = self.parse_prefix_expr(None);
|
||||
let expr = self.parse_expr_prefix(None);
|
||||
let (span, expr) = self.interpolated_or_expr_span(expr)?;
|
||||
Ok((lo.to(span), expr))
|
||||
}
|
||||
|
||||
fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
|
||||
let (span, expr) = self.parse_prefix_expr_common(lo)?;
|
||||
fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
|
||||
let (span, expr) = self.parse_expr_prefix_common(lo)?;
|
||||
Ok((span, self.mk_unary(op, expr)))
|
||||
}
|
||||
|
||||
@ -621,12 +621,12 @@ impl<'a> Parser<'a> {
|
||||
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
self.sess.emit_err(errors::TildeAsUnaryOperator(lo));
|
||||
|
||||
self.parse_unary_expr(lo, UnOp::Not)
|
||||
self.parse_expr_unary(lo, UnOp::Not)
|
||||
}
|
||||
|
||||
/// Parse `box expr`.
|
||||
fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
let (span, expr) = self.parse_prefix_expr_common(lo)?;
|
||||
fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
let (span, expr) = self.parse_expr_prefix_common(lo)?;
|
||||
self.sess.gated_spans.gate(sym::box_syntax, span);
|
||||
Ok((span, ExprKind::Box(expr)))
|
||||
}
|
||||
@ -664,7 +664,7 @@ impl<'a> Parser<'a> {
|
||||
),
|
||||
});
|
||||
|
||||
self.parse_unary_expr(lo, UnOp::Not)
|
||||
self.parse_expr_unary(lo, UnOp::Not)
|
||||
}
|
||||
|
||||
/// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
|
||||
@ -722,7 +722,7 @@ impl<'a> Parser<'a> {
|
||||
segments[0].ident.span,
|
||||
),
|
||||
};
|
||||
match self.parse_labeled_expr(label, false) {
|
||||
match self.parse_expr_labeled(label, false) {
|
||||
Ok(expr) => {
|
||||
type_err.cancel();
|
||||
self.sess.emit_err(errors::MalformedLoopLabel {
|
||||
@ -816,7 +816,7 @@ impl<'a> Parser<'a> {
|
||||
("cast", None)
|
||||
};
|
||||
|
||||
let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
|
||||
let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?;
|
||||
|
||||
// Check if an illegal postfix operator has been added after the cast.
|
||||
// If the resulting expression is not a cast, it is an illegal postfix operator.
|
||||
@ -887,15 +887,15 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
|
||||
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
self.expect_and()?;
|
||||
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
|
||||
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
|
||||
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
|
||||
let expr = if self.token.is_range_separator() {
|
||||
self.parse_prefix_range_expr(None)
|
||||
self.parse_expr_prefix_range(None)
|
||||
} else {
|
||||
self.parse_prefix_expr(None)
|
||||
self.parse_expr_prefix(None)
|
||||
};
|
||||
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
|
||||
let span = lo.to(hi);
|
||||
@ -925,16 +925,16 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
|
||||
fn parse_dot_or_call_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
|
||||
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
||||
self.collect_tokens_for_expr(attrs, |this, attrs| {
|
||||
let base = this.parse_bottom_expr();
|
||||
let base = this.parse_expr_bottom();
|
||||
let (span, base) = this.interpolated_or_expr_span(base)?;
|
||||
this.parse_dot_or_call_expr_with(base, span, attrs)
|
||||
this.parse_expr_dot_or_call_with(base, span, attrs)
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn parse_dot_or_call_expr_with(
|
||||
pub(super) fn parse_expr_dot_or_call_with(
|
||||
&mut self,
|
||||
e0: P<Expr>,
|
||||
lo: Span,
|
||||
@ -943,7 +943,7 @@ impl<'a> Parser<'a> {
|
||||
// Stitch the list of outer attributes onto the return value.
|
||||
// A little bit ugly, but the best way given the current code
|
||||
// structure
|
||||
let res = self.parse_dot_or_call_expr_with_(e0, lo);
|
||||
let res = self.parse_expr_dot_or_call_with_(e0, lo);
|
||||
if attrs.is_empty() {
|
||||
res
|
||||
} else {
|
||||
@ -957,7 +957,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
loop {
|
||||
let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
|
||||
// we are using noexpect here because we don't expect a `?` directly after a `return`
|
||||
@ -980,15 +980,15 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
if has_dot {
|
||||
// expr.f
|
||||
e = self.parse_dot_suffix_expr(lo, e)?;
|
||||
e = self.parse_expr_dot_suffix(lo, e)?;
|
||||
continue;
|
||||
}
|
||||
if self.expr_is_complete(&e) {
|
||||
return Ok(e);
|
||||
}
|
||||
e = match self.token.kind {
|
||||
token::OpenDelim(Delimiter::Parenthesis) => self.parse_fn_call_expr(lo, e),
|
||||
token::OpenDelim(Delimiter::Bracket) => self.parse_index_expr(lo, e)?,
|
||||
token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
|
||||
token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
|
||||
_ => return Ok(e),
|
||||
}
|
||||
}
|
||||
@ -1000,14 +1000,14 @@ impl<'a> Parser<'a> {
|
||||
&& self.look_ahead(3, |t| t.can_begin_expr())
|
||||
}
|
||||
|
||||
fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_dot_suffix(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
match self.token.uninterpolate().kind {
|
||||
token::Ident(..) => self.parse_dot_suffix(base, lo),
|
||||
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
|
||||
Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None))
|
||||
Ok(self.parse_expr_tuple_field_access(lo, base, symbol, suffix, None))
|
||||
}
|
||||
token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
|
||||
Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix))
|
||||
Ok(self.parse_expr_tuple_field_access_float(lo, base, symbol, suffix))
|
||||
}
|
||||
_ => {
|
||||
self.error_unexpected_after_dot();
|
||||
@ -1029,7 +1029,7 @@ impl<'a> Parser<'a> {
|
||||
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
|
||||
// we should break everything including floats into more basic proc-macro style
|
||||
// tokens in the lexer (probably preferable).
|
||||
fn parse_tuple_field_access_expr_float(
|
||||
fn parse_expr_tuple_field_access_float(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
base: P<Expr>,
|
||||
@ -1072,7 +1072,7 @@ impl<'a> Parser<'a> {
|
||||
match &*components {
|
||||
// 1e2
|
||||
[IdentLike(i)] => {
|
||||
self.parse_tuple_field_access_expr(lo, base, Symbol::intern(&i), suffix, None)
|
||||
self.parse_expr_tuple_field_access(lo, base, Symbol::intern(&i), suffix, None)
|
||||
}
|
||||
// 1.
|
||||
[IdentLike(i), Punct('.')] => {
|
||||
@ -1088,7 +1088,7 @@ impl<'a> Parser<'a> {
|
||||
let symbol = Symbol::intern(&i);
|
||||
self.token = Token::new(token::Ident(symbol, false), ident_span);
|
||||
let next_token = (Token::new(token::Dot, dot_span), self.token_spacing);
|
||||
self.parse_tuple_field_access_expr(lo, base, symbol, None, Some(next_token))
|
||||
self.parse_expr_tuple_field_access(lo, base, symbol, None, Some(next_token))
|
||||
}
|
||||
// 1.2 | 1.2e3
|
||||
[IdentLike(i1), Punct('.'), IdentLike(i2)] => {
|
||||
@ -1109,11 +1109,11 @@ impl<'a> Parser<'a> {
|
||||
// See issue #76399 and PR #76285 for more details
|
||||
let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone);
|
||||
let base1 =
|
||||
self.parse_tuple_field_access_expr(lo, base, symbol1, None, Some(next_token1));
|
||||
self.parse_expr_tuple_field_access(lo, base, symbol1, None, Some(next_token1));
|
||||
let symbol2 = Symbol::intern(&i2);
|
||||
let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span);
|
||||
self.bump_with((next_token2, self.token_spacing)); // `.`
|
||||
self.parse_tuple_field_access_expr(lo, base1, symbol2, suffix, None)
|
||||
self.parse_expr_tuple_field_access(lo, base1, symbol2, suffix, None)
|
||||
}
|
||||
// 1e+ | 1e- (recovered)
|
||||
[IdentLike(_), Punct('+' | '-')] |
|
||||
@ -1131,7 +1131,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_tuple_field_access_expr(
|
||||
fn parse_expr_tuple_field_access(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
base: P<Expr>,
|
||||
@ -1152,7 +1152,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse a function call expression, `expr(...)`.
|
||||
fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
|
||||
fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
|
||||
let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
|
||||
&& self.look_ahead_type_ascription_as_field()
|
||||
{
|
||||
@ -1163,7 +1163,7 @@ impl<'a> Parser<'a> {
|
||||
let open_paren = self.token.span;
|
||||
|
||||
let mut seq = self
|
||||
.parse_paren_expr_seq()
|
||||
.parse_expr_paren_seq()
|
||||
.map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
|
||||
if let Some(expr) =
|
||||
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
|
||||
@ -1236,7 +1236,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse an indexing expression `expr[...]`.
|
||||
fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
|
||||
let prev_span = self.prev_token.span;
|
||||
let open_delim_span = self.token.span;
|
||||
self.bump(); // `[`
|
||||
@ -1259,7 +1259,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||
// Method call `expr.f()`
|
||||
let args = self.parse_paren_expr_seq()?;
|
||||
let args = self.parse_expr_paren_seq()?;
|
||||
let fn_span = fn_span_lo.to(self.prev_token.span);
|
||||
let span = lo.to(self.prev_token.span);
|
||||
Ok(self.mk_expr(
|
||||
@ -1287,7 +1287,7 @@ impl<'a> Parser<'a> {
|
||||
///
|
||||
/// N.B., this does not parse outer attributes, and is private because it only works
|
||||
/// correctly if called from `parse_dot_or_call_expr()`.
|
||||
fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
|
||||
maybe_recover_from_interpolated_ty_qpath!(self, true);
|
||||
maybe_whole_expr!(self);
|
||||
|
||||
@ -1300,13 +1300,13 @@ impl<'a> Parser<'a> {
|
||||
// This match arm is a special-case of the `_` match arm below and
|
||||
// could be removed without changing functionality, but it's faster
|
||||
// to have it here, especially for programs with large constants.
|
||||
self.parse_lit_expr()
|
||||
self.parse_expr_lit()
|
||||
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||
self.parse_tuple_parens_expr()
|
||||
self.parse_expr_tuple_parens()
|
||||
} else if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
||||
self.parse_block_expr(None, lo, BlockCheckMode::Default)
|
||||
self.parse_expr_block(None, lo, BlockCheckMode::Default)
|
||||
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
|
||||
self.parse_closure_expr().map_err(|mut err| {
|
||||
self.parse_expr_closure().map_err(|mut err| {
|
||||
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
|
||||
// then suggest parens around the lhs.
|
||||
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
|
||||
@ -1315,42 +1315,42 @@ impl<'a> Parser<'a> {
|
||||
err
|
||||
})
|
||||
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
|
||||
self.parse_array_or_repeat_expr(Delimiter::Bracket)
|
||||
self.parse_expr_array_or_repeat(Delimiter::Bracket)
|
||||
} else if self.check_path() {
|
||||
self.parse_path_start_expr()
|
||||
self.parse_expr_path_start()
|
||||
} else if self.check_keyword(kw::Move)
|
||||
|| self.check_keyword(kw::Static)
|
||||
|| self.check_const_closure()
|
||||
{
|
||||
self.parse_closure_expr()
|
||||
self.parse_expr_closure()
|
||||
} else if self.eat_keyword(kw::If) {
|
||||
self.parse_if_expr()
|
||||
self.parse_expr_if()
|
||||
} else if self.check_keyword(kw::For) {
|
||||
if self.choose_generics_over_qpath(1) {
|
||||
self.parse_closure_expr()
|
||||
self.parse_expr_closure()
|
||||
} else {
|
||||
assert!(self.eat_keyword(kw::For));
|
||||
self.parse_for_expr(None, self.prev_token.span)
|
||||
self.parse_expr_for(None, self.prev_token.span)
|
||||
}
|
||||
} else if self.eat_keyword(kw::While) {
|
||||
self.parse_while_expr(None, self.prev_token.span)
|
||||
self.parse_expr_while(None, self.prev_token.span)
|
||||
} else if let Some(label) = self.eat_label() {
|
||||
self.parse_labeled_expr(label, true)
|
||||
self.parse_expr_labeled(label, true)
|
||||
} else if self.eat_keyword(kw::Loop) {
|
||||
let sp = self.prev_token.span;
|
||||
self.parse_loop_expr(None, self.prev_token.span).map_err(|mut err| {
|
||||
self.parse_expr_loop(None, self.prev_token.span).map_err(|mut err| {
|
||||
err.span_label(sp, "while parsing this `loop` expression");
|
||||
err
|
||||
})
|
||||
} else if self.eat_keyword(kw::Match) {
|
||||
let match_sp = self.prev_token.span;
|
||||
self.parse_match_expr().map_err(|mut err| {
|
||||
self.parse_expr_match().map_err(|mut err| {
|
||||
err.span_label(match_sp, "while parsing this `match` expression");
|
||||
err
|
||||
})
|
||||
} else if self.eat_keyword(kw::Unsafe) {
|
||||
let sp = self.prev_token.span;
|
||||
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|
||||
self.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|
||||
|mut err| {
|
||||
err.span_label(sp, "while parsing this `unsafe` expression");
|
||||
err
|
||||
@ -1364,17 +1364,17 @@ impl<'a> Parser<'a> {
|
||||
self.expect_keyword(kw::Try)?;
|
||||
self.parse_try_block(lo)
|
||||
} else if self.eat_keyword(kw::Return) {
|
||||
self.parse_return_expr()
|
||||
self.parse_expr_return()
|
||||
} else if self.eat_keyword(kw::Continue) {
|
||||
self.parse_continue_expr(lo)
|
||||
self.parse_expr_continue(lo)
|
||||
} else if self.eat_keyword(kw::Break) {
|
||||
self.parse_break_expr()
|
||||
self.parse_expr_break()
|
||||
} else if self.eat_keyword(kw::Yield) {
|
||||
self.parse_yield_expr()
|
||||
self.parse_expr_yield()
|
||||
} else if self.is_do_yeet() {
|
||||
self.parse_yeet_expr()
|
||||
self.parse_expr_yeet()
|
||||
} else if self.check_keyword(kw::Let) {
|
||||
self.parse_let_expr()
|
||||
self.parse_expr_let()
|
||||
} else if self.eat_keyword(kw::Underscore) {
|
||||
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
|
||||
} else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
|
||||
@ -1397,19 +1397,19 @@ impl<'a> Parser<'a> {
|
||||
// Check for `async {` and `async move {`.
|
||||
self.parse_async_block()
|
||||
} else {
|
||||
self.parse_closure_expr()
|
||||
self.parse_expr_closure()
|
||||
}
|
||||
} else if self.eat_keyword(kw::Await) {
|
||||
self.recover_incorrect_await_syntax(lo, self.prev_token.span)
|
||||
} else {
|
||||
self.parse_lit_expr()
|
||||
self.parse_expr_lit()
|
||||
}
|
||||
} else {
|
||||
self.parse_lit_expr()
|
||||
self.parse_expr_lit()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_lit_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
match self.parse_opt_token_lit() {
|
||||
Some((token_lit, _)) => {
|
||||
@ -1420,7 +1420,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_tuple_parens_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_tuple_parens(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
let (es, trailing_comma) = match self.parse_seq_to_end(
|
||||
@ -1444,7 +1444,7 @@ impl<'a> Parser<'a> {
|
||||
self.maybe_recover_from_bad_qpath(expr)
|
||||
}
|
||||
|
||||
fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
self.bump(); // `[` or other open delim
|
||||
|
||||
@ -1457,7 +1457,7 @@ impl<'a> Parser<'a> {
|
||||
let first_expr = self.parse_expr()?;
|
||||
if self.eat(&token::Semi) {
|
||||
// Repeating array syntax: `[ 0; 512 ]`
|
||||
let count = self.parse_anon_const_expr()?;
|
||||
let count = self.parse_expr_anon_const()?;
|
||||
self.expect(close)?;
|
||||
ExprKind::Repeat(first_expr, count)
|
||||
} else if self.eat(&token::Comma) {
|
||||
@ -1476,7 +1476,7 @@ impl<'a> Parser<'a> {
|
||||
self.maybe_recover_from_bad_qpath(expr)
|
||||
}
|
||||
|
||||
fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let (qself, path) = if self.eat_lt() {
|
||||
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
|
||||
(Some(qself), path)
|
||||
@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `'label: $expr`. The label is already parsed.
|
||||
fn parse_labeled_expr(
|
||||
fn parse_expr_labeled(
|
||||
&mut self,
|
||||
label_: Label,
|
||||
mut consume_colon: bool,
|
||||
@ -1522,15 +1522,15 @@ impl<'a> Parser<'a> {
|
||||
let label = Some(label_);
|
||||
let ate_colon = self.eat(&token::Colon);
|
||||
let expr = if self.eat_keyword(kw::While) {
|
||||
self.parse_while_expr(label, lo)
|
||||
self.parse_expr_while(label, lo)
|
||||
} else if self.eat_keyword(kw::For) {
|
||||
self.parse_for_expr(label, lo)
|
||||
self.parse_expr_for(label, lo)
|
||||
} else if self.eat_keyword(kw::Loop) {
|
||||
self.parse_loop_expr(label, lo)
|
||||
self.parse_expr_loop(label, lo)
|
||||
} else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
|
||||
|| self.token.is_whole_block()
|
||||
{
|
||||
self.parse_block_expr(label, lo, BlockCheckMode::Default)
|
||||
self.parse_expr_block(label, lo, BlockCheckMode::Default)
|
||||
} else if !ate_colon
|
||||
&& self.may_recover()
|
||||
&& (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
|
||||
@ -1670,7 +1670,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `"return" expr?`.
|
||||
fn parse_return_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.prev_token.span;
|
||||
let kind = ExprKind::Ret(self.parse_expr_opt()?);
|
||||
let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
|
||||
@ -1678,7 +1678,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `"do" "yeet" expr?`.
|
||||
fn parse_yeet_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
|
||||
self.bump(); // `do`
|
||||
@ -1700,13 +1700,13 @@ impl<'a> Parser<'a> {
|
||||
/// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
|
||||
/// expression only gets a warning for compatibility reasons; and a labeled break
|
||||
/// with a labeled loop does not even get a warning because there is no ambiguity.
|
||||
fn parse_break_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.prev_token.span;
|
||||
let mut label = self.eat_label();
|
||||
let kind = if self.token == token::Colon && let Some(label) = label.take() {
|
||||
// The value expression can be a labeled loop, see issue #86948, e.g.:
|
||||
// `loop { break 'label: loop { break 'label 42; }; }`
|
||||
let lexpr = self.parse_labeled_expr(label, true)?;
|
||||
let lexpr = self.parse_expr_labeled(label, true)?;
|
||||
self.sess.emit_err(errors::LabeledLoopInBreak {
|
||||
span: lexpr.span,
|
||||
sub: errors::WrapExpressionInParentheses {
|
||||
@ -1759,7 +1759,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `"continue" label?`.
|
||||
fn parse_continue_expr(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let mut label = self.eat_label();
|
||||
|
||||
// Recover `continue label` -> `continue 'label`
|
||||
@ -1776,7 +1776,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `"yield" expr?`.
|
||||
fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.prev_token.span;
|
||||
let kind = ExprKind::Yield(self.parse_expr_opt()?);
|
||||
let span = lo.to(self.prev_token.span);
|
||||
@ -1993,7 +1993,7 @@ impl<'a> Parser<'a> {
|
||||
/// expression.
|
||||
fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
|
||||
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
|
||||
match snapshot.parse_expr_array_or_repeat(Delimiter::Brace) {
|
||||
Ok(arr) => {
|
||||
self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces {
|
||||
span: arr.span,
|
||||
@ -2056,7 +2056,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a block or unsafe block.
|
||||
pub(super) fn parse_block_expr(
|
||||
pub(super) fn parse_expr_block(
|
||||
&mut self,
|
||||
opt_label: Option<Label>,
|
||||
lo: Span,
|
||||
@ -2086,7 +2086,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a closure expression (e.g., `move |args| expr`).
|
||||
fn parse_closure_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
|
||||
let binder = if self.check_keyword(kw::For) {
|
||||
@ -2123,7 +2123,7 @@ impl<'a> Parser<'a> {
|
||||
_ => {
|
||||
// If an explicit return type is given, require a block to appear (RFC 968).
|
||||
let body_lo = self.token.span;
|
||||
self.parse_block_expr(None, body_lo, BlockCheckMode::Default)?
|
||||
self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
|
||||
}
|
||||
};
|
||||
|
||||
@ -2236,9 +2236,9 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses an `if` expression (`if` token already eaten).
|
||||
fn parse_if_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.prev_token.span;
|
||||
let cond = self.parse_cond_expr()?;
|
||||
let cond = self.parse_expr_cond()?;
|
||||
self.parse_if_after_cond(lo, cond)
|
||||
}
|
||||
|
||||
@ -2316,12 +2316,12 @@ impl<'a> Parser<'a> {
|
||||
self.error_on_if_block_attrs(lo, false, block.span, attrs);
|
||||
block
|
||||
};
|
||||
let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
|
||||
let els = if self.eat_keyword(kw::Else) { Some(self.parse_expr_else()?) } else { None };
|
||||
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
|
||||
}
|
||||
|
||||
/// Parses the condition of a `if` or `while` expression.
|
||||
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let cond =
|
||||
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
|
||||
|
||||
@ -2334,7 +2334,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a `let $pat = $expr` pseudo-expression.
|
||||
fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_let(&mut self) -> PResult<'a, P<Expr>> {
|
||||
// This is a *approximate* heuristic that detects if `let` chains are
|
||||
// being parsed in the right position. It's approximate because it
|
||||
// doesn't deny all invalid `let` expressions, just completely wrong usages.
|
||||
@ -2364,7 +2364,7 @@ impl<'a> Parser<'a> {
|
||||
self.expect(&token::Eq)?;
|
||||
}
|
||||
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
|
||||
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
|
||||
this.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())
|
||||
})?;
|
||||
let span = lo.to(expr.span);
|
||||
self.sess.gated_spans.gate(sym::let_chains, span);
|
||||
@ -2372,11 +2372,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses an `else { ... }` expression (`else` token already eaten).
|
||||
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let else_span = self.prev_token.span; // `else`
|
||||
let attrs = self.parse_outer_attributes()?; // For recovery.
|
||||
let expr = if self.eat_keyword(kw::If) {
|
||||
self.parse_if_expr()?
|
||||
self.parse_expr_if()?
|
||||
} else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
|
||||
self.parse_simple_block()?
|
||||
} else {
|
||||
@ -2450,7 +2450,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
|
||||
fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
// Record whether we are about to parse `for (`.
|
||||
// This is used below for recovery in case of `for ( $stuff ) $block`
|
||||
// in which case we will suggest `for $stuff $block`.
|
||||
@ -2508,8 +2508,8 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a `while` or `while let` expression (`while` token already eaten).
|
||||
fn parse_while_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let cond = self.parse_cond_expr().map_err(|mut err| {
|
||||
fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let cond = self.parse_expr_cond().map_err(|mut err| {
|
||||
err.span_label(lo, "while parsing the condition of this `while` expression");
|
||||
err
|
||||
})?;
|
||||
@ -2526,7 +2526,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses `loop { ... }` (`loop` token already eaten).
|
||||
fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let loop_span = self.prev_token.span;
|
||||
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
Ok(self.mk_expr_with_attrs(
|
||||
@ -2544,7 +2544,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parses a `match ... { ... }` expression (`match` token already eaten).
|
||||
fn parse_match_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||
fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let match_span = self.prev_token.span;
|
||||
let lo = self.prev_token.span;
|
||||
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
|
||||
@ -2914,7 +2914,7 @@ impl<'a> Parser<'a> {
|
||||
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
|
||||
return Some(Err(err));
|
||||
}
|
||||
let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
|
||||
let expr = self.parse_expr_struct(qself.clone(), path.clone(), true);
|
||||
if let (Ok(expr), false) = (&expr, struct_allowed) {
|
||||
// This is a struct literal, but we don't can't accept them here.
|
||||
self.sess.emit_err(errors::StructLiteralNotAllowedHere {
|
||||
@ -3043,7 +3043,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Precondition: already parsed the '{'.
|
||||
pub(super) fn parse_struct_expr(
|
||||
pub(super) fn parse_expr_struct(
|
||||
&mut self,
|
||||
qself: Option<P<ast::QSelf>>,
|
||||
pth: ast::Path,
|
||||
|
@ -1331,7 +1331,7 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
let disr_expr =
|
||||
if this.eat(&token::Eq) { Some(this.parse_anon_const_expr()?) } else { None };
|
||||
if this.eat(&token::Eq) { Some(this.parse_expr_anon_const()?) } else { None };
|
||||
|
||||
let vr = ast::Variant {
|
||||
ident,
|
||||
@ -1722,7 +1722,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
if self.token.kind == token::Eq {
|
||||
self.bump();
|
||||
let const_expr = self.parse_anon_const_expr()?;
|
||||
let const_expr = self.parse_expr_anon_const()?;
|
||||
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
|
||||
self.struct_span_err(sp, "default values on `struct` fields aren't supported")
|
||||
.span_suggestion(
|
||||
|
@ -653,7 +653,7 @@ impl<'a> Parser<'a> {
|
||||
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
|
||||
// Parse const argument.
|
||||
let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind {
|
||||
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)?
|
||||
self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?
|
||||
} else {
|
||||
self.handle_unambiguous_unbraced_const_arg()?
|
||||
};
|
||||
|
@ -146,14 +146,14 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) {
|
||||
this.parse_struct_expr(None, path, true)?
|
||||
this.parse_expr_struct(None, path, true)?
|
||||
} else {
|
||||
let hi = this.prev_token.span;
|
||||
this.mk_expr(lo.to(hi), ExprKind::Path(None, path))
|
||||
};
|
||||
|
||||
let expr = this.with_res(Restrictions::STMT_EXPR, |this| {
|
||||
this.parse_dot_or_call_expr_with(expr, lo, attrs)
|
||||
this.parse_expr_dot_or_call_with(expr, lo, attrs)
|
||||
})?;
|
||||
// `DUMMY_SP` will get overwritten later in this function
|
||||
Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None))
|
||||
@ -163,7 +163,7 @@ impl<'a> Parser<'a> {
|
||||
// Perform this outside of the `collect_tokens_trailing_token` closure,
|
||||
// since our outer attributes do not apply to this part of the expression
|
||||
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
|
||||
this.parse_assoc_expr_with(
|
||||
this.parse_expr_assoc_with(
|
||||
0,
|
||||
LhsExpr::AlreadyParsed { expr, starts_statement: true },
|
||||
)
|
||||
@ -199,8 +199,8 @@ impl<'a> Parser<'a> {
|
||||
// Since none of the above applied, this is an expression statement macro.
|
||||
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
|
||||
let e = self.maybe_recover_from_bad_qpath(e)?;
|
||||
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
|
||||
let e = self.parse_assoc_expr_with(
|
||||
let e = self.parse_expr_dot_or_call_with(e, lo, attrs)?;
|
||||
let e = self.parse_expr_assoc_with(
|
||||
0,
|
||||
LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
|
||||
)?;
|
||||
|
@ -433,7 +433,7 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
let ty = if self.eat(&token::Semi) {
|
||||
let mut length = self.parse_anon_const_expr()?;
|
||||
let mut length = self.parse_expr_anon_const()?;
|
||||
if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
|
||||
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
|
||||
self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
|
||||
@ -494,7 +494,7 @@ impl<'a> Parser<'a> {
|
||||
// To avoid ambiguity, the type is surrounded by parentheses.
|
||||
fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
|
||||
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
let expr = self.parse_anon_const_expr()?;
|
||||
let expr = self.parse_expr_anon_const()?;
|
||||
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||
Ok(TyKind::Typeof(expr))
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
||||
| hir::ExprKind::InlineAsm(..)
|
||||
| hir::ExprKind::Box(..)
|
||||
| hir::ExprKind::Type(..)
|
||||
| hir::ExprKind::Err
|
||||
| hir::ExprKind::Err(_)
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
|
||||
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
|
||||
intravisit::walk_expr(self, expr);
|
||||
@ -1129,7 +1129,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
hir::ExprKind::Lit(..)
|
||||
| hir::ExprKind::ConstBlock(..)
|
||||
| hir::ExprKind::Err
|
||||
| hir::ExprKind::Err(_)
|
||||
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
|
||||
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
|
||||
|
||||
@ -1427,7 +1427,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
| hir::ExprKind::Yield(..)
|
||||
| hir::ExprKind::Box(..)
|
||||
| hir::ExprKind::Type(..)
|
||||
| hir::ExprKind::Err => {}
|
||||
| hir::ExprKind::Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
||||
hir::intravisit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
ExprKind::Err => {
|
||||
ExprKind::Err(_) => {
|
||||
self.items.push((ItemKind::Err, span));
|
||||
}
|
||||
}
|
||||
|
@ -2149,3 +2149,17 @@ where
|
||||
Hash::hash(&len, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
/// Useful type to use with `Result<>` indicate that an error has already
|
||||
/// been reported to the user, so no need to continue checking.
|
||||
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct ErrorGuaranteed(());
|
||||
|
||||
impl ErrorGuaranteed {
|
||||
/// To be used only if you really know what you are doing... ideally, we would find a way to
|
||||
/// eliminate all calls to this method.
|
||||
pub fn unchecked_claim_error_was_emitted() -> Self {
|
||||
ErrorGuaranteed(())
|
||||
}
|
||||
}
|
||||
|
@ -740,6 +740,7 @@ symbols! {
|
||||
frem_fast,
|
||||
from,
|
||||
from_desugaring,
|
||||
from_fn,
|
||||
from_iter,
|
||||
from_method,
|
||||
from_output,
|
||||
|
@ -21,12 +21,14 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||
| ty::Float(_)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Str
|
||||
| ty::Error(_)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Never
|
||||
| ty::Char => Ok(vec![]),
|
||||
|
||||
// Treat this like `struct str([u8]);`
|
||||
ty::Str => Ok(vec![tcx.mk_slice(tcx.types.u8)]),
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
|
@ -3107,6 +3107,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
self.tcx.def_span(def_id),
|
||||
"required because it's used within this closure",
|
||||
),
|
||||
ty::Str => err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes"),
|
||||
_ => err.note(&msg),
|
||||
};
|
||||
}
|
||||
|
@ -2300,12 +2300,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| ty::Float(_)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Str
|
||||
| ty::Error(_)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Never
|
||||
| ty::Char => ty::Binder::dummy(Vec::new()),
|
||||
|
||||
// Treat this like `struct str([u8]);`
|
||||
ty::Str => ty::Binder::dummy(vec![self.tcx().mk_slice(self.tcx().types.u8)]),
|
||||
|
||||
ty::Placeholder(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
|
@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
return;
|
||||
}
|
||||
|
||||
if target_cap < self.capacity() {
|
||||
// There are three cases of interest:
|
||||
// All elements are out of desired bounds
|
||||
// Elements are contiguous, and head is out of desired bounds
|
||||
// Elements are discontiguous, and tail is out of desired bounds
|
||||
//
|
||||
// At all other times, element positions are unaffected.
|
||||
//
|
||||
// Indicates that elements at the head should be moved.
|
||||
// There are three cases of interest:
|
||||
// All elements are out of desired bounds
|
||||
// Elements are contiguous, and tail is out of desired bounds
|
||||
// Elements are discontiguous
|
||||
//
|
||||
// At all other times, element positions are unaffected.
|
||||
|
||||
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
|
||||
// Move elements from out of desired bounds (positions after target_cap)
|
||||
if self.len == 0 {
|
||||
self.head = 0;
|
||||
} else if self.head >= target_cap && tail_outside {
|
||||
// H := head
|
||||
// L := last element
|
||||
// H L
|
||||
// [. . . . . . . . o o o o o o o . ]
|
||||
// H L
|
||||
// [o o o o o o o . ]
|
||||
unsafe {
|
||||
// nonoverlapping because self.head >= target_cap >= self.len
|
||||
self.copy_nonoverlapping(self.head, 0, self.len);
|
||||
}
|
||||
self.head = 0;
|
||||
} else if self.head < target_cap && tail_outside {
|
||||
// H := head
|
||||
// L := last element
|
||||
// H L
|
||||
// [. . . o o o o o o o . . . . . . ]
|
||||
// L H
|
||||
// [o o . o o o o o ]
|
||||
let len = self.head + self.len - target_cap;
|
||||
unsafe {
|
||||
self.copy_nonoverlapping(target_cap, 0, len);
|
||||
}
|
||||
} else if self.head >= target_cap {
|
||||
// H := head
|
||||
// L := last element
|
||||
// L H
|
||||
// [o o o o o . . . . . . . . . o o ]
|
||||
// L H
|
||||
// [o o o o o . o o ]
|
||||
let len = self.capacity() - self.head;
|
||||
let new_head = target_cap - len;
|
||||
unsafe {
|
||||
// can't use copy_nonoverlapping here for the same reason
|
||||
// as in `handle_capacity_increase()`
|
||||
self.copy(self.head, new_head, len);
|
||||
}
|
||||
self.head = new_head;
|
||||
// `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
|
||||
// overflow.
|
||||
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
|
||||
|
||||
if self.len == 0 {
|
||||
self.head = 0;
|
||||
} else if self.head >= target_cap && tail_outside {
|
||||
// Head and tail are both out of bounds, so copy all of them to the front.
|
||||
//
|
||||
// H := head
|
||||
// L := last element
|
||||
// H L
|
||||
// [. . . . . . . . o o o o o o o . ]
|
||||
// H L
|
||||
// [o o o o o o o . ]
|
||||
unsafe {
|
||||
// nonoverlapping because `self.head >= target_cap >= self.len`.
|
||||
self.copy_nonoverlapping(self.head, 0, self.len);
|
||||
}
|
||||
|
||||
self.buf.shrink_to_fit(target_cap);
|
||||
|
||||
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
|
||||
debug_assert!(self.len <= self.capacity());
|
||||
self.head = 0;
|
||||
} else if self.head < target_cap && tail_outside {
|
||||
// Head is in bounds, tail is out of bounds.
|
||||
// Copy the overflowing part to the beginning of the
|
||||
// buffer. This won't overlap because `target_cap >= self.len`.
|
||||
//
|
||||
// H := head
|
||||
// L := last element
|
||||
// H L
|
||||
// [. . . o o o o o o o . . . . . . ]
|
||||
// L H
|
||||
// [o o . o o o o o ]
|
||||
let len = self.head + self.len - target_cap;
|
||||
unsafe {
|
||||
self.copy_nonoverlapping(target_cap, 0, len);
|
||||
}
|
||||
} else if !self.is_contiguous() {
|
||||
// The head slice is at least partially out of bounds, tail is in bounds.
|
||||
// Copy the head backwards so it lines up with the target capacity.
|
||||
// This won't overlap because `target_cap >= self.len`.
|
||||
//
|
||||
// H := head
|
||||
// L := last element
|
||||
// L H
|
||||
// [o o o o o . . . . . . . . . o o ]
|
||||
// L H
|
||||
// [o o o o o . o o ]
|
||||
let head_len = self.capacity() - self.head;
|
||||
let new_head = target_cap - head_len;
|
||||
unsafe {
|
||||
// can't use `copy_nonoverlapping()` here because the new and old
|
||||
// regions for the head might overlap.
|
||||
self.copy(self.head, new_head, head_len);
|
||||
}
|
||||
self.head = new_head;
|
||||
}
|
||||
self.buf.shrink_to_fit(target_cap);
|
||||
|
||||
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
|
||||
debug_assert!(self.len <= self.capacity());
|
||||
}
|
||||
|
||||
/// Shortens the deque, keeping the first `len` elements and dropping
|
||||
|
@ -748,6 +748,48 @@ fn test_drain() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_108453() {
|
||||
let mut deque = VecDeque::with_capacity(10);
|
||||
|
||||
deque.push_back(1u8);
|
||||
deque.push_back(2);
|
||||
deque.push_back(3);
|
||||
|
||||
deque.push_front(10);
|
||||
deque.push_front(9);
|
||||
|
||||
deque.shrink_to(9);
|
||||
|
||||
assert_eq!(deque.into_iter().collect::<Vec<_>>(), vec![9, 10, 1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shrink_to() {
|
||||
// test deques with capacity 16 with all possible head positions, lengths and target capacities.
|
||||
let cap = 16;
|
||||
|
||||
for len in 0..cap {
|
||||
for head in 0..cap {
|
||||
let expected = (1..=len).collect::<VecDeque<_>>();
|
||||
|
||||
for target_cap in len..cap {
|
||||
let mut deque = VecDeque::with_capacity(cap);
|
||||
// currently, `with_capacity` always allocates the exact capacity if it's greater than 8.
|
||||
assert_eq!(deque.capacity(), cap);
|
||||
|
||||
// we can let the head point anywhere in the buffer since the deque is empty.
|
||||
deque.head = head;
|
||||
deque.extend(1..=len);
|
||||
|
||||
deque.shrink_to(target_cap);
|
||||
|
||||
assert_eq!(deque, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shrink_to_fit() {
|
||||
// This test checks that every single combination of head and tail position,
|
||||
|
@ -542,7 +542,7 @@ pub trait Into<T>: Sized {
|
||||
#[const_trait]
|
||||
pub trait From<T>: Sized {
|
||||
/// Converts to this type from the input type.
|
||||
#[lang = "from"]
|
||||
#[rustc_diagnostic_item = "from_fn"]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from(value: T) -> Self;
|
||||
|
@ -3,21 +3,26 @@ macro_rules! int_impl {
|
||||
Self = $SelfT:ty,
|
||||
ActualT = $ActualT:ident,
|
||||
UnsignedT = $UnsignedT:ty,
|
||||
BITS = $BITS:expr,
|
||||
BITS_MINUS_ONE = $BITS_MINUS_ONE:expr,
|
||||
Min = $Min:expr,
|
||||
Max = $Max:expr,
|
||||
rot = $rot:expr,
|
||||
rot_op = $rot_op:expr,
|
||||
rot_result = $rot_result:expr,
|
||||
swap_op = $swap_op:expr,
|
||||
swapped = $swapped:expr,
|
||||
reversed = $reversed:expr,
|
||||
le_bytes = $le_bytes:expr,
|
||||
be_bytes = $be_bytes:expr,
|
||||
|
||||
// There are all for use *only* in doc comments.
|
||||
// As such, they're all passed as literals -- passing them as a string
|
||||
// literal is fine if they need to be multiple code tokens.
|
||||
// In non-comments, use the associated constants rather than these.
|
||||
BITS = $BITS:literal,
|
||||
BITS_MINUS_ONE = $BITS_MINUS_ONE:literal,
|
||||
Min = $Min:literal,
|
||||
Max = $Max:literal,
|
||||
rot = $rot:literal,
|
||||
rot_op = $rot_op:literal,
|
||||
rot_result = $rot_result:literal,
|
||||
swap_op = $swap_op:literal,
|
||||
swapped = $swapped:literal,
|
||||
reversed = $reversed:literal,
|
||||
le_bytes = $le_bytes:literal,
|
||||
be_bytes = $be_bytes:literal,
|
||||
to_xe_bytes_doc = $to_xe_bytes_doc:expr,
|
||||
from_xe_bytes_doc = $from_xe_bytes_doc:expr,
|
||||
bound_condition = $bound_condition:expr,
|
||||
bound_condition = $bound_condition:literal,
|
||||
) => {
|
||||
/// The smallest value that can be represented by this integer type
|
||||
#[doc = concat!("(−2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")]
|
||||
@ -30,7 +35,7 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")]
|
||||
/// ```
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
|
||||
pub const MIN: Self = !Self::MAX;
|
||||
|
||||
/// The largest value that can be represented by this integer type
|
||||
#[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> − 1", $bound_condition, ").")]
|
||||
@ -43,7 +48,7 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")]
|
||||
/// ```
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX: Self = !Self::MIN;
|
||||
pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self;
|
||||
|
||||
/// The size of this integer type in bits.
|
||||
///
|
||||
@ -53,7 +58,7 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
|
||||
/// ```
|
||||
#[stable(feature = "int_bits_const", since = "1.53.0")]
|
||||
pub const BITS: u32 = $BITS;
|
||||
pub const BITS: u32 = <$UnsignedT>::BITS;
|
||||
|
||||
/// Converts a string slice in a given base to an integer.
|
||||
///
|
||||
@ -1380,7 +1385,7 @@ macro_rules! int_impl {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
self.unchecked_shl(rhs & ($BITS - 1))
|
||||
self.unchecked_shl(rhs & (Self::BITS - 1))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1410,7 +1415,7 @@ macro_rules! int_impl {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
self.unchecked_shr(rhs & ($BITS - 1))
|
||||
self.unchecked_shr(rhs & (Self::BITS - 1))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1916,7 +1921,7 @@ macro_rules! int_impl {
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
|
||||
(self.wrapping_shl(rhs), rhs >= Self::BITS)
|
||||
}
|
||||
|
||||
/// Shifts self right by `rhs` bits.
|
||||
@ -1939,7 +1944,7 @@ macro_rules! int_impl {
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
|
||||
(self.wrapping_shr(rhs), rhs >= Self::BITS)
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
|
@ -4,19 +4,24 @@ macro_rules! uint_impl {
|
||||
ActualT = $ActualT:ident,
|
||||
SignedT = $SignedT:ident,
|
||||
NonZeroT = $NonZeroT:ident,
|
||||
BITS = $BITS:expr,
|
||||
MAX = $MaxV:expr,
|
||||
rot = $rot:expr,
|
||||
rot_op = $rot_op:expr,
|
||||
rot_result = $rot_result:expr,
|
||||
swap_op = $swap_op:expr,
|
||||
swapped = $swapped:expr,
|
||||
reversed = $reversed:expr,
|
||||
le_bytes = $le_bytes:expr,
|
||||
be_bytes = $be_bytes:expr,
|
||||
|
||||
// There are all for use *only* in doc comments.
|
||||
// As such, they're all passed as literals -- passing them as a string
|
||||
// literal is fine if they need to be multiple code tokens.
|
||||
// In non-comments, use the associated constants rather than these.
|
||||
BITS = $BITS:literal,
|
||||
MAX = $MaxV:literal,
|
||||
rot = $rot:literal,
|
||||
rot_op = $rot_op:literal,
|
||||
rot_result = $rot_result:literal,
|
||||
swap_op = $swap_op:literal,
|
||||
swapped = $swapped:literal,
|
||||
reversed = $reversed:literal,
|
||||
le_bytes = $le_bytes:literal,
|
||||
be_bytes = $be_bytes:literal,
|
||||
to_xe_bytes_doc = $to_xe_bytes_doc:expr,
|
||||
from_xe_bytes_doc = $from_xe_bytes_doc:expr,
|
||||
bound_condition = $bound_condition:expr,
|
||||
bound_condition = $bound_condition:literal,
|
||||
) => {
|
||||
/// The smallest value that can be represented by this integer type.
|
||||
///
|
||||
@ -51,7 +56,7 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
|
||||
/// ```
|
||||
#[stable(feature = "int_bits_const", since = "1.53.0")]
|
||||
pub const BITS: u32 = $BITS;
|
||||
pub const BITS: u32 = Self::MAX.count_ones();
|
||||
|
||||
/// Converts a string slice in a given base to an integer.
|
||||
///
|
||||
@ -1403,7 +1408,7 @@ macro_rules! uint_impl {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
self.unchecked_shl(rhs & ($BITS - 1))
|
||||
self.unchecked_shl(rhs & (Self::BITS - 1))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1436,7 +1441,7 @@ macro_rules! uint_impl {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
self.unchecked_shr(rhs & ($BITS - 1))
|
||||
self.unchecked_shr(rhs & (Self::BITS - 1))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1860,7 +1865,7 @@ macro_rules! uint_impl {
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
|
||||
(self.wrapping_shl(rhs), rhs >= Self::BITS)
|
||||
}
|
||||
|
||||
/// Shifts self right by `rhs` bits.
|
||||
@ -1885,7 +1890,7 @@ macro_rules! uint_impl {
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
|
||||
(self.wrapping_shr(rhs), rhs >= Self::BITS)
|
||||
}
|
||||
|
||||
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
||||
|
@ -1661,7 +1661,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||
}
|
||||
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
|
||||
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
|
||||
TyKind::Infer | TyKind::Err | TyKind::Typeof(..) => Infer,
|
||||
TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) => Infer,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1022,7 +1022,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
|
||||
))
|
||||
.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
|
||||
),
|
||||
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
|
||||
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err(_) => {
|
||||
Position::ReborrowStable(precedence)
|
||||
},
|
||||
};
|
||||
@ -1038,7 +1038,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
|
||||
if self.0
|
||||
|| matches!(
|
||||
ty.kind,
|
||||
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err
|
||||
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
|
||||
)
|
||||
{
|
||||
self.0 = true;
|
||||
|
@ -224,7 +224,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
|
||||
| ExprKind::Path(_)
|
||||
| ExprKind::ConstBlock(_)
|
||||
| ExprKind::Lit(_)
|
||||
| ExprKind::Err => NeverLoopResult::Otherwise,
|
||||
| ExprKind::Err(_) => NeverLoopResult::Otherwise,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
|
||||
ExprKind::ConstBlock(_) |
|
||||
ExprKind::Continue(_) |
|
||||
ExprKind::DropTemps(_) |
|
||||
ExprKind::Err |
|
||||
ExprKind::Err(_) |
|
||||
ExprKind::InlineAsm(_) |
|
||||
ExprKind::Let(_) |
|
||||
ExprKind::Lit(_) |
|
||||
|
@ -49,10 +49,10 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
|
||||
(arg, arg.span)
|
||||
},
|
||||
ExprKind::Call(path, [arg])
|
||||
if path_def_id(cx, path).map_or(false, |id| {
|
||||
if match_def_path(cx, id, &paths::FROM_STR_METHOD) {
|
||||
if path_def_id(cx, path).map_or(false, |did| {
|
||||
if match_def_path(cx, did, &paths::FROM_STR_METHOD) {
|
||||
true
|
||||
} else if cx.tcx.lang_items().from_fn() == Some(id) {
|
||||
} else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
|
||||
!is_copy(cx, typeck.expr_ty(expr))
|
||||
} else {
|
||||
false
|
||||
|
@ -7,6 +7,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -54,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
|
||||
);
|
||||
} else {
|
||||
if_chain! {
|
||||
if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
|
||||
if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id);
|
||||
if let [.., last_arg] = args;
|
||||
if let ExprKind::Lit(spanned) = &last_arg.kind;
|
||||
if let LitKind::Str(symbol, _) = spanned.node;
|
||||
|
@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if Some(def_id) == cx.tcx.lang_items().from_fn();
|
||||
if cx.tcx.is_diagnostic_item(sym::from_fn, def_id);
|
||||
if same_type_and_consts(a, b);
|
||||
|
||||
then {
|
||||
|
@ -588,7 +588,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||
},
|
||||
}
|
||||
},
|
||||
ExprKind::Err => kind!("Err"),
|
||||
ExprKind::Err(_) => kind!("Err"),
|
||||
ExprKind::DropTemps(expr) => {
|
||||
bind!(self, expr);
|
||||
kind!("DropTemps({expr})");
|
||||
|
@ -193,7 +193,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
||||
| ExprKind::Ret(_)
|
||||
| ExprKind::InlineAsm(_)
|
||||
| ExprKind::Yield(..)
|
||||
| ExprKind::Err => {
|
||||
| ExprKind::Err(_) => {
|
||||
self.eagerness = ForceNoChange;
|
||||
return;
|
||||
},
|
||||
|
@ -714,7 +714,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
}
|
||||
self.hash_pat(pat);
|
||||
},
|
||||
ExprKind::Err => {},
|
||||
ExprKind::Err(_) => {},
|
||||
ExprKind::Lit(ref l) => {
|
||||
l.node.hash(&mut self.s);
|
||||
},
|
||||
@ -986,7 +986,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
TyKind::Typeof(anon_const) => {
|
||||
self.hash_body(anon_const.body);
|
||||
},
|
||||
TyKind::Err | TyKind::Infer | TyKind::Never => {},
|
||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ impl<'a> Sugg<'a> {
|
||||
| hir::ExprKind::Ret(..)
|
||||
| hir::ExprKind::Struct(..)
|
||||
| hir::ExprKind::Tup(..)
|
||||
| hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
|
||||
| hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
|
||||
hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
|
||||
hir::ExprKind::Assign(lhs, rhs, _) => {
|
||||
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
||||
|
@ -665,7 +665,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
|
||||
| ExprKind::Path(_)
|
||||
| ExprKind::Continue(_)
|
||||
| ExprKind::InlineAsm(_)
|
||||
| ExprKind::Err => (),
|
||||
| ExprKind::Err(_) => (),
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
mdbook = { version = "0.4", default-features = false, features = ["search"] }
|
||||
rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
|
||||
|
||||
[[bin]]
|
||||
name = "error_index_generator"
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
extern crate rustc_driver;
|
||||
|
||||
// We use the function we generate from `register_diagnostics!`.
|
||||
use crate::error_codes::error_codes;
|
||||
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fs::{self, File};
|
||||
@ -17,22 +14,6 @@ use std::str::FromStr;
|
||||
use mdbook::book::{parse_summary, BookItem, Chapter};
|
||||
use mdbook::{Config, MDBook};
|
||||
|
||||
macro_rules! register_diagnostics {
|
||||
($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
|
||||
pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
|
||||
let mut errors: Vec<(&str, Option<&str>)> = vec![
|
||||
$((stringify!($error_code), Some($message)),)+
|
||||
$((stringify!($undocumented), None),)*
|
||||
];
|
||||
errors.sort();
|
||||
errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
|
||||
mod error_codes;
|
||||
|
||||
enum OutputFormat {
|
||||
HTML,
|
||||
Markdown,
|
||||
@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
|
||||
|
||||
write!(output_file, "# Rust Compiler Error Index\n")?;
|
||||
|
||||
for (err_code, description) in error_codes().iter() {
|
||||
match description {
|
||||
Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
|
||||
None => {}
|
||||
}
|
||||
for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
|
||||
write!(output_file, "## {}\n{}\n", err_code, description)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -105,27 +83,23 @@ This page lists all the error codes emitted by the Rust compiler.
|
||||
"
|
||||
);
|
||||
|
||||
let err_codes = error_codes();
|
||||
let err_codes = rustc_error_codes::DIAGNOSTICS;
|
||||
let mut chapters = Vec::with_capacity(err_codes.len());
|
||||
|
||||
for (err_code, explanation) in err_codes.iter() {
|
||||
if let Some(explanation) = explanation {
|
||||
introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
|
||||
introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
|
||||
|
||||
let content = add_rust_attribute_on_codeblock(explanation);
|
||||
chapters.push(BookItem::Chapter(Chapter {
|
||||
name: err_code.to_string(),
|
||||
content: format!("# Error code {}\n\n{}\n", err_code, content),
|
||||
number: None,
|
||||
sub_items: Vec::new(),
|
||||
// We generate it into the `error_codes` folder.
|
||||
path: Some(PathBuf::from(&format!("{}.html", err_code))),
|
||||
source_path: None,
|
||||
parent_names: Vec::new(),
|
||||
}));
|
||||
} else {
|
||||
introduction.push_str(&format!(" * {}\n", err_code));
|
||||
}
|
||||
let content = add_rust_attribute_on_codeblock(explanation);
|
||||
chapters.push(BookItem::Chapter(Chapter {
|
||||
name: err_code.to_string(),
|
||||
content: format!("# Error code {}\n\n{}\n", err_code, content),
|
||||
number: None,
|
||||
sub_items: Vec::new(),
|
||||
// We generate it into the `error_codes` folder.
|
||||
path: Some(PathBuf::from(&format!("{}.html", err_code))),
|
||||
source_path: None,
|
||||
parent_names: Vec::new(),
|
||||
}));
|
||||
}
|
||||
|
||||
let mut config = Config::from_str(include_str!("book_config.toml"))?;
|
||||
|
@ -45,7 +45,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
|
||||
let mut errors = Vec::new();
|
||||
|
||||
// Stage 1: create list
|
||||
let error_codes = extract_error_codes(root_path, &mut errors, verbose);
|
||||
let error_codes = extract_error_codes(root_path, &mut errors);
|
||||
println!("Found {} error codes", error_codes.len());
|
||||
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
|
||||
|
||||
@ -65,18 +65,17 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
|
||||
}
|
||||
|
||||
/// Stage 1: Parses a list of error codes from `error_codes.rs`.
|
||||
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
|
||||
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
|
||||
let path = root_path.join(Path::new(ERROR_CODES_PATH));
|
||||
let file =
|
||||
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
|
||||
|
||||
let mut error_codes = Vec::new();
|
||||
let mut reached_undocumented_codes = false;
|
||||
|
||||
for line in file.lines() {
|
||||
let line = line.trim();
|
||||
|
||||
if !reached_undocumented_codes && line.starts_with('E') {
|
||||
if line.starts_with('E') {
|
||||
let split_line = line.split_once(':');
|
||||
|
||||
// Extract the error code from the line, emitting a fatal error if it is not in a correct format.
|
||||
@ -111,23 +110,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool
|
||||
}
|
||||
|
||||
error_codes.push(err_code);
|
||||
} else if reached_undocumented_codes && line.starts_with('E') {
|
||||
let err_code = match line.split_once(',') {
|
||||
None => line,
|
||||
Some((err_code, _)) => err_code,
|
||||
}
|
||||
.to_string();
|
||||
|
||||
verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
|
||||
|
||||
if error_codes.contains(&err_code) {
|
||||
errors.push(format!("Found duplicate error code: `{}`", err_code));
|
||||
}
|
||||
|
||||
error_codes.push(err_code);
|
||||
} else if line == ";" {
|
||||
// Once we reach the undocumented error codes, adapt to different syntax.
|
||||
reached_undocumented_codes = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
13
tests/ui/auto-traits/str-contains-slice-conceptually.rs
Normal file
13
tests/ui/auto-traits/str-contains-slice-conceptually.rs
Normal 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`
|
||||
}
|
16
tests/ui/auto-traits/str-contains-slice-conceptually.stderr
Normal file
16
tests/ui/auto-traits/str-contains-slice-conceptually.stderr
Normal 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`.
|
@ -2,7 +2,7 @@ error: `main` function is not allowed to be `#[track_caller]`
|
||||
--> $DIR/error-with-main.rs:1:1
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^ help: remove this annotation
|
||||
LL | fn main() {
|
||||
| --------- `main` function is not allowed to be `#[track_caller]`
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user