Add an ErrorGuaranteed
to ast::TyKind::Err
.
This makes it more like `hir::TyKind::Err`, and avoids a `span_delayed_bug` call in `LoweringContext::lower_ty_direct`. It also requires adding `ast::TyKind::Dummy`, now that `ast::TyKind::Err` can't be used for that purpose in the absence of an error emission. There are a couple of cases that aren't as neat as I would have liked, marked with `FIXME` comments.
This commit is contained in:
parent
502ce8287b
commit
5233bc91da
14 changed files with 75 additions and 36 deletions
|
@ -46,14 +46,14 @@ use std::ops::{Deref, DerefMut};
|
|||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
/// Creates a placeholder argument.
|
||||
pub(super) fn dummy_arg(ident: Ident) -> Param {
|
||||
pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
|
||||
let pat = P(Pat {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingAnnotation::NONE, ident, None),
|
||||
span: ident.span,
|
||||
tokens: None,
|
||||
});
|
||||
let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None };
|
||||
let ty = Ty { kind: TyKind::Err(guar), span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None };
|
||||
Param {
|
||||
attrs: AttrVec::default(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
@ -1540,14 +1540,14 @@ impl<'a> Parser<'a> {
|
|||
pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
|
||||
if self.token == token::Question {
|
||||
self.bump();
|
||||
self.dcx().emit_err(QuestionMarkInType {
|
||||
let guar = self.dcx().emit_err(QuestionMarkInType {
|
||||
span: self.prev_token.span,
|
||||
sugg: QuestionMarkInTypeSugg {
|
||||
left: ty.span.shrink_to_lo(),
|
||||
right: self.prev_token.span,
|
||||
},
|
||||
});
|
||||
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
|
||||
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err(guar))
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
|
@ -2304,8 +2304,8 @@ impl<'a> Parser<'a> {
|
|||
|
||||
pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
|
||||
let span = param.pat.span;
|
||||
param.ty.kind = TyKind::Err;
|
||||
self.dcx().emit_err(SelfParamNotFirst { span });
|
||||
let guar = self.dcx().emit_err(SelfParamNotFirst { span });
|
||||
param.ty.kind = TyKind::Err(guar);
|
||||
Ok(param)
|
||||
}
|
||||
|
||||
|
@ -2437,7 +2437,7 @@ impl<'a> Parser<'a> {
|
|||
pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut ThinVec<Param>) {
|
||||
let mut seen_inputs = FxHashSet::default();
|
||||
for input in fn_inputs.iter_mut() {
|
||||
let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) =
|
||||
let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err(_)) =
|
||||
(&input.pat.kind, &input.ty.kind)
|
||||
{
|
||||
Some(*ident)
|
||||
|
@ -2644,8 +2644,10 @@ impl<'a> Parser<'a> {
|
|||
"::",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.emit();
|
||||
return Ok(GenericArg::Type(self.mk_ty(start.to(expr.span), TyKind::Err)));
|
||||
let guar = err.emit();
|
||||
return Ok(GenericArg::Type(
|
||||
self.mk_ty(start.to(expr.span), TyKind::Err(guar)),
|
||||
));
|
||||
} else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
|
||||
{
|
||||
// Avoid the following output by checking that we consumed a full const arg:
|
||||
|
|
|
@ -591,7 +591,23 @@ impl<'a> Parser<'a> {
|
|||
let ty_second = if self.token == token::DotDot {
|
||||
// We need to report this error after `cfg` expansion for compatibility reasons
|
||||
self.bump(); // `..`, do not add it to expected tokens
|
||||
Some(self.mk_ty(self.prev_token.span, TyKind::Err))
|
||||
|
||||
// FIXME(nnethercote): AST validation later detects this
|
||||
// `TyKind::Err` and emits an errors. So why the unchecked
|
||||
// ErrorGuaranteed?
|
||||
// - A `span_delayed_bug` doesn't work here, because rustfmt can
|
||||
// hit this path but then not hit the follow-up path in the AST
|
||||
// validator that issues the error, which results in ICEs.
|
||||
// - `TyKind::Dummy` doesn't work, because it ends up reaching HIR
|
||||
// lowering, which results in ICEs. Changing `TyKind::Dummy` to
|
||||
// `TyKind::Err` during AST validation might fix that, but that's
|
||||
// not possible because AST validation doesn't allow mutability.
|
||||
//
|
||||
// #121072 will hopefully remove all this special handling of the
|
||||
// obsolete `impl Trait for ..` and then this can go away.
|
||||
#[allow(deprecated)]
|
||||
let guar = rustc_errors::ErrorGuaranteed::unchecked_error_guaranteed();
|
||||
Some(self.mk_ty(self.prev_token.span, TyKind::Err(guar)))
|
||||
} else if has_for || self.token.can_begin_type() {
|
||||
Some(self.parse_ty()?)
|
||||
} else {
|
||||
|
@ -2628,13 +2644,13 @@ impl<'a> Parser<'a> {
|
|||
p.recover_diff_marker();
|
||||
let snapshot = p.create_snapshot_for_diagnostic();
|
||||
let param = p.parse_param_general(req_name, first_param).or_else(|e| {
|
||||
e.emit();
|
||||
let guar = e.emit();
|
||||
let lo = p.prev_token.span;
|
||||
p.restore_snapshot(snapshot);
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(Delimiter::Parenthesis)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span))))
|
||||
Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span)), guar))
|
||||
});
|
||||
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||
first_param = false;
|
||||
|
@ -2671,8 +2687,8 @@ impl<'a> Parser<'a> {
|
|||
return if let Some(ident) =
|
||||
this.parameter_without_type(&mut err, pat, is_name_required, first_param)
|
||||
{
|
||||
err.emit();
|
||||
Ok((dummy_arg(ident), TrailingToken::None))
|
||||
let guar = err.emit();
|
||||
Ok((dummy_arg(ident, guar), TrailingToken::None))
|
||||
} else {
|
||||
Err(err)
|
||||
};
|
||||
|
|
|
@ -678,8 +678,9 @@ impl<'a> Parser<'a> {
|
|||
c.into()
|
||||
}
|
||||
Some(GenericArg::Lifetime(lt)) => {
|
||||
self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
|
||||
self.mk_ty(span, ast::TyKind::Err).into()
|
||||
let guar =
|
||||
self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
|
||||
self.mk_ty(span, ast::TyKind::Err(guar)).into()
|
||||
}
|
||||
None => {
|
||||
let after_eq = eq.shrink_to_hi();
|
||||
|
@ -779,7 +780,7 @@ impl<'a> Parser<'a> {
|
|||
// type to determine if error recovery has occurred and if the input is not a
|
||||
// syntactically valid type after all.
|
||||
if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind
|
||||
&& let ast::TyKind::Err = inner_ty.kind
|
||||
&& let ast::TyKind::Err(_) = inner_ty.kind
|
||||
&& let Some(snapshot) = snapshot
|
||||
&& let Some(expr) =
|
||||
self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
|
||||
|
|
|
@ -346,8 +346,10 @@ impl<'a> Parser<'a> {
|
|||
AllowCVariadic::No => {
|
||||
// FIXME(Centril): Should we just allow `...` syntactically
|
||||
// anywhere in a type and use semantic restrictions instead?
|
||||
self.dcx().emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
|
||||
TyKind::Err
|
||||
let guar = self
|
||||
.dcx()
|
||||
.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
|
||||
TyKind::Err(guar)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -493,8 +495,8 @@ impl<'a> Parser<'a> {
|
|||
{
|
||||
// Recover from `[LIT; EXPR]` and `[LIT]`
|
||||
self.bump();
|
||||
err.emit();
|
||||
self.mk_ty(self.prev_token.span, TyKind::Err)
|
||||
let guar = err.emit();
|
||||
self.mk_ty(self.prev_token.span, TyKind::Err(guar))
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue