Auto merge of #61649 - Centril:rollup-b4nx9k9, r=Centril
Rollup of 7 pull requests Successful merges: - #61223 (Document tuple's Ord behavior as sequential) - #61615 (syntax: Treat error literals in more principled way) - #61616 (parser: Remove `Deref` impl from `Parser`) - #61621 (Clarify when we run steps with ONLY_HOSTS) - #61627 (Add regression test for #61452.) - #61641 (Revert "Make LocalAnalizer visitor iterate instead of recurse") - #61647 (Use stable wrappers in f32/f64::signum) Failed merges: r? @ghost
This commit is contained in:
commit
6312b89fda
31 changed files with 377 additions and 349 deletions
|
@ -59,7 +59,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
|
|||
|
||||
const DEFAULT: bool = false;
|
||||
|
||||
/// Run this rule for all hosts without cross compiling.
|
||||
/// If true, then this rule should be skipped if --target was specified, but --host was not
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
/// Primary function to execute this rule. Can call `builder.ensure()`
|
||||
|
@ -163,7 +163,7 @@ impl StepDescription {
|
|||
|
||||
// Determine the targets participating in this rule.
|
||||
let targets = if self.only_hosts {
|
||||
if !builder.config.run_host_only {
|
||||
if builder.config.skip_only_host_steps {
|
||||
return; // don't run anything
|
||||
} else {
|
||||
&builder.hosts
|
||||
|
@ -1338,7 +1338,7 @@ mod __test {
|
|||
let mut config = Config::default_opts();
|
||||
// don't save toolstates
|
||||
config.save_toolstates = None;
|
||||
config.run_host_only = true;
|
||||
config.skip_only_host_steps = false;
|
||||
config.dry_run = true;
|
||||
// try to avoid spurious failures in dist where we create/delete each others file
|
||||
let dir = config.out.join("tmp-rustbuild-tests").join(
|
||||
|
@ -1583,7 +1583,7 @@ mod __test {
|
|||
#[test]
|
||||
fn dist_with_target_flag() {
|
||||
let mut config = configure(&["B"], &["C"]);
|
||||
config.run_host_only = false; // as-if --target=C was passed
|
||||
config.skip_only_host_steps = true; // as-if --target=C was passed
|
||||
let build = Build::new(config);
|
||||
let mut builder = Builder::new(&build);
|
||||
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
|
||||
|
@ -1831,7 +1831,7 @@ mod __test {
|
|||
#[test]
|
||||
fn build_with_target_flag() {
|
||||
let mut config = configure(&["B"], &["C"]);
|
||||
config.run_host_only = false;
|
||||
config.skip_only_host_steps = true;
|
||||
let build = Build::new(config);
|
||||
let mut builder = Builder::new(&build);
|
||||
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
|
||||
|
|
|
@ -51,7 +51,7 @@ pub struct Config {
|
|||
pub test_compare_mode: bool,
|
||||
pub llvm_libunwind: bool,
|
||||
|
||||
pub run_host_only: bool,
|
||||
pub skip_only_host_steps: bool,
|
||||
|
||||
pub on_fail: Option<String>,
|
||||
pub stage: Option<u32>,
|
||||
|
@ -416,7 +416,9 @@ impl Config {
|
|||
}
|
||||
|
||||
// If --target was specified but --host wasn't specified, don't run any host-only tests.
|
||||
config.run_host_only = !(flags.host.is_empty() && !flags.target.is_empty());
|
||||
let has_hosts = !flags.host.is_empty();
|
||||
let has_targets = !flags.target.is_empty();
|
||||
config.skip_only_host_steps = !has_hosts && has_targets;
|
||||
|
||||
let toml = file.map(|file| {
|
||||
let contents = t!(fs::read_to_string(&file));
|
||||
|
|
|
@ -1020,7 +1020,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
|||
ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
|
||||
visitor.visit_expr(subexpression)
|
||||
}
|
||||
ExprKind::Lit(_) => {}
|
||||
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_ty(typ)
|
||||
|
@ -1093,7 +1092,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
|||
ExprKind::Yield(ref subexpression) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
}
|
||||
ExprKind::Err => {}
|
||||
ExprKind::Lit(_) | ExprKind::Err => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -170,14 +170,14 @@ impl_stable_hash_for!(struct ::syntax::ast::Lit {
|
|||
|
||||
impl_stable_hash_for!(enum ::syntax::ast::LitKind {
|
||||
Str(value, style),
|
||||
Err(value),
|
||||
ByteStr(value),
|
||||
Byte(value),
|
||||
Char(value),
|
||||
Int(value, lit_int_type),
|
||||
Float(value, float_ty),
|
||||
FloatUnsuffixed(value),
|
||||
Bool(value)
|
||||
Bool(value),
|
||||
Err(value)
|
||||
});
|
||||
|
||||
impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
|
||||
|
|
|
@ -154,62 +154,51 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||
context: PlaceContext,
|
||||
location: Location) {
|
||||
debug!("visit_place(place={:?}, context={:?})", place, context);
|
||||
let mut context = context;
|
||||
let cx = self.fx.cx;
|
||||
|
||||
place.iterate(|place_base, place_projections| {
|
||||
for proj in place_projections {
|
||||
// Allow uses of projections that are ZSTs or from scalar fields.
|
||||
let is_consume = match context {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
|
||||
_ => false
|
||||
};
|
||||
if is_consume {
|
||||
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
|
||||
let base_ty = self.fx.monomorphize(&base_ty);
|
||||
if let mir::Place::Projection(ref proj) = *place {
|
||||
// Allow uses of projections that are ZSTs or from scalar fields.
|
||||
let is_consume = match context {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
|
||||
_ => false
|
||||
};
|
||||
if is_consume {
|
||||
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
|
||||
let base_ty = self.fx.monomorphize(&base_ty);
|
||||
|
||||
// ZSTs don't require any actual memory access.
|
||||
let elem_ty = base_ty
|
||||
.projection_ty(cx.tcx(), &proj.elem)
|
||||
.ty;
|
||||
let elem_ty = self.fx.monomorphize(&elem_ty);
|
||||
if cx.layout_of(elem_ty).is_zst() {
|
||||
// ZSTs don't require any actual memory access.
|
||||
let elem_ty = base_ty
|
||||
.projection_ty(cx.tcx(), &proj.elem)
|
||||
.ty;
|
||||
let elem_ty = self.fx.monomorphize(&elem_ty);
|
||||
if cx.layout_of(elem_ty).is_zst() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let mir::ProjectionElem::Field(..) = proj.elem {
|
||||
let layout = cx.layout_of(base_ty.ty);
|
||||
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
|
||||
// Recurse with the same context, instead of `Projection`,
|
||||
// potentially stopping at non-operand projections,
|
||||
// which would trigger `not_ssa` on locals.
|
||||
self.visit_place(&proj.base, context, location);
|
||||
return;
|
||||
}
|
||||
|
||||
if let mir::ProjectionElem::Field(..) = proj.elem {
|
||||
let layout = cx.layout_of(base_ty.ty);
|
||||
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
|
||||
// Recurse with the same context, instead of `Projection`,
|
||||
// potentially stopping at non-operand projections,
|
||||
// which would trigger `not_ssa` on locals.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A deref projection only reads the pointer, never needs the place.
|
||||
if let mir::ProjectionElem::Deref = proj.elem {
|
||||
return self.visit_place(
|
||||
&proj.base,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
context = if context.is_mutating_use() {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
} else {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
}
|
||||
|
||||
// Default base visit behavior
|
||||
if let mir::PlaceBase::Local(local) = place_base {
|
||||
self.visit_local(local, context, location);
|
||||
// A deref projection only reads the pointer, never needs the place.
|
||||
if let mir::ProjectionElem::Deref = proj.elem {
|
||||
return self.visit_place(
|
||||
&proj.base,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
||||
location
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.super_place(place, context, location);
|
||||
}
|
||||
|
||||
fn visit_local(&mut self,
|
||||
|
|
|
@ -34,15 +34,6 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
|
|||
let allocation = tcx.intern_const_alloc(allocation);
|
||||
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
||||
},
|
||||
LitKind::Err(ref s) => {
|
||||
let s = s.as_str();
|
||||
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
|
||||
let allocation = tcx.intern_const_alloc(allocation);
|
||||
return Ok(tcx.mk_const(ty::Const {
|
||||
val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() },
|
||||
ty: tcx.types.err,
|
||||
}));
|
||||
},
|
||||
LitKind::ByteStr(ref data) => {
|
||||
let id = tcx.allocate_bytes(data);
|
||||
ConstValue::Scalar(Scalar::Ptr(id.into()))
|
||||
|
@ -66,6 +57,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
|
|||
}
|
||||
LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
|
||||
LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
|
||||
LitKind::Err(_) => unreachable!(),
|
||||
};
|
||||
Ok(tcx.mk_const(ty::Const { val: lit, ty }))
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ impl f32 {
|
|||
if self.is_nan() {
|
||||
NAN
|
||||
} else {
|
||||
unsafe { intrinsics::copysignf32(1.0, self) }
|
||||
1.0_f32.copysign(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ impl f64 {
|
|||
if self.is_nan() {
|
||||
NAN
|
||||
} else {
|
||||
unsafe { intrinsics::copysignf64(1.0, self) }
|
||||
1.0_f64.copysign(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -683,6 +683,10 @@ mod prim_str { }
|
|||
/// assert_eq!(tuple.2, 'c');
|
||||
/// ```
|
||||
///
|
||||
/// The sequential nature of the tuple applies to its implementations of various
|
||||
/// traits. For example, in `PartialOrd` and `Ord`, the elements are compared
|
||||
/// sequentially until the first non-equal set is found.
|
||||
///
|
||||
/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
|
||||
///
|
||||
/// # Trait implementations
|
||||
|
|
|
@ -1368,7 +1368,7 @@ pub enum LitKind {
|
|||
FloatUnsuffixed(Symbol),
|
||||
/// A boolean literal.
|
||||
Bool(bool),
|
||||
/// A recovered character literal that contains mutliple `char`s, most likely a typo.
|
||||
/// Placeholder for a literal that wasn't well-formed in some way.
|
||||
Err(Symbol),
|
||||
}
|
||||
|
||||
|
@ -1406,10 +1406,10 @@ impl LitKind {
|
|||
| LitKind::ByteStr(..)
|
||||
| LitKind::Byte(..)
|
||||
| LitKind::Char(..)
|
||||
| LitKind::Err(..)
|
||||
| LitKind::Int(_, LitIntType::Unsuffixed)
|
||||
| LitKind::FloatUnsuffixed(..)
|
||||
| LitKind::Bool(..) => true,
|
||||
| LitKind::Bool(..)
|
||||
| LitKind::Err(..) => true,
|
||||
// suffixed variants
|
||||
LitKind::Int(_, LitIntType::Signed(..))
|
||||
| LitKind::Int(_, LitIntType::Unsigned(..))
|
||||
|
|
|
@ -735,9 +735,9 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
|
|||
raw_attr.clone(),
|
||||
);
|
||||
|
||||
let start_span = parser.span;
|
||||
let start_span = parser.token.span;
|
||||
let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted());
|
||||
let end_span = parser.span;
|
||||
let end_span = parser.token.span;
|
||||
if parser.token != token::Eof {
|
||||
parse_sess.span_diagnostic
|
||||
.span_err(start_span.to(end_span), "invalid crate attribute");
|
||||
|
|
|
@ -121,7 +121,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
let mut expanded_attrs = Vec::with_capacity(1);
|
||||
|
||||
while !parser.check(&token::CloseDelim(token::Paren)) {
|
||||
let lo = parser.span.lo();
|
||||
let lo = parser.token.span.lo();
|
||||
let (path, tokens) = parser.parse_meta_item_unrestricted()?;
|
||||
expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo)));
|
||||
parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
|
||||
|
|
|
@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> {
|
|||
let msg = format!("macro expansion ignores token `{}` and any following",
|
||||
self.this_token_to_string());
|
||||
// Avoid emitting backtrace info twice.
|
||||
let def_site_span = self.span.with_ctxt(SyntaxContext::empty());
|
||||
let def_site_span = self.token.span.with_ctxt(SyntaxContext::empty());
|
||||
let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
|
||||
err.span_label(span, "caused by the macro expansion here");
|
||||
let msg = format!(
|
||||
|
|
|
@ -105,7 +105,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea
|
|||
while self.p.token != token::Eof {
|
||||
match panictry!(self.p.parse_item()) {
|
||||
Some(item) => ret.push(item),
|
||||
None => self.p.diagnostic().span_fatal(self.p.span,
|
||||
None => self.p.diagnostic().span_fatal(self.p.token.span,
|
||||
&format!("expected item, found `{}`",
|
||||
self.p.this_token_to_string()))
|
||||
.raise()
|
||||
|
|
|
@ -675,7 +675,7 @@ pub fn parse(
|
|||
//
|
||||
// This MatcherPos instance is allocated on the stack. All others -- and
|
||||
// there are frequently *no* others! -- are allocated on the heap.
|
||||
let mut initial = initial_matcher_pos(ms, parser.span);
|
||||
let mut initial = initial_matcher_pos(ms, parser.token.span);
|
||||
let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
|
||||
let mut next_items = Vec::new();
|
||||
|
||||
|
@ -721,15 +721,15 @@ pub fn parse(
|
|||
return nameize(sess, ms, matches);
|
||||
} else if eof_items.len() > 1 {
|
||||
return Error(
|
||||
parser.span,
|
||||
parser.token.span,
|
||||
"ambiguity: multiple successful parses".to_string(),
|
||||
);
|
||||
} else {
|
||||
return Failure(
|
||||
Token::new(token::Eof, if parser.span.is_dummy() {
|
||||
parser.span
|
||||
Token::new(token::Eof, if parser.token.span.is_dummy() {
|
||||
parser.token.span
|
||||
} else {
|
||||
sess.source_map().next_point(parser.span)
|
||||
sess.source_map().next_point(parser.token.span)
|
||||
}),
|
||||
"missing tokens in macro arguments",
|
||||
);
|
||||
|
@ -753,7 +753,7 @@ pub fn parse(
|
|||
.join(" or ");
|
||||
|
||||
return Error(
|
||||
parser.span,
|
||||
parser.token.span,
|
||||
format!(
|
||||
"local ambiguity: multiple parsing options: {}",
|
||||
match next_items.len() {
|
||||
|
@ -927,7 +927,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> Nonterminal {
|
|||
sym::ty => token::NtTy(panictry!(p.parse_ty())),
|
||||
// this could be handled like a token, since it is one
|
||||
sym::ident => if let Some((name, is_raw)) = get_macro_name(&p.token) {
|
||||
let span = p.span;
|
||||
let span = p.token.span;
|
||||
p.bump();
|
||||
token::NtIdent(Ident::new(name, span), is_raw)
|
||||
} else {
|
||||
|
|
|
@ -47,7 +47,7 @@ impl<'a> ParserAnyMacro<'a> {
|
|||
let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| {
|
||||
if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") {
|
||||
if !e.span.is_dummy() { // early end of macro arm (#52866)
|
||||
e.replace_span_with(parser.sess.source_map().next_point(parser.span));
|
||||
e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
|
||||
}
|
||||
let msg = &e.message[0];
|
||||
e.message[0] = (
|
||||
|
@ -63,7 +63,7 @@ impl<'a> ParserAnyMacro<'a> {
|
|||
if parser.sess.source_map().span_to_filename(arm_span).is_real() {
|
||||
e.span_label(arm_span, "in this macro arm");
|
||||
}
|
||||
} else if !parser.sess.source_map().span_to_filename(parser.span).is_real() {
|
||||
} else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() {
|
||||
e.span_label(site_span, "in this macro invocation");
|
||||
}
|
||||
e
|
||||
|
|
|
@ -1101,7 +1101,6 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
|
|||
vis.visit_expr(rhs);
|
||||
}
|
||||
ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs),
|
||||
ExprKind::Lit(_lit) => {}
|
||||
ExprKind::Cast(expr, ty) => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_ty(ty);
|
||||
|
@ -1225,7 +1224,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
|
|||
}
|
||||
ExprKind::Try(expr) => vis.visit_expr(expr),
|
||||
ExprKind::TryBlock(body) => vis.visit_block(body),
|
||||
ExprKind::Err => {}
|
||||
ExprKind::Lit(_) | ExprKind::Err => {}
|
||||
}
|
||||
vis.visit_id(id);
|
||||
vis.visit_span(span);
|
||||
|
|
|
@ -39,7 +39,7 @@ impl<'a> Parser<'a> {
|
|||
just_parsed_doc_comment = false;
|
||||
}
|
||||
token::DocComment(s) => {
|
||||
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.span);
|
||||
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.token.span);
|
||||
if attr.style != ast::AttrStyle::Outer {
|
||||
let mut err = self.fatal("expected outer doc comment");
|
||||
err.note("inner doc comments like this (starting with \
|
||||
|
@ -83,7 +83,7 @@ impl<'a> Parser<'a> {
|
|||
self.token);
|
||||
let (span, path, tokens, style) = match self.token.kind {
|
||||
token::Pound => {
|
||||
let lo = self.span;
|
||||
let lo = self.token.span;
|
||||
self.bump();
|
||||
|
||||
if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
|
||||
|
@ -93,7 +93,7 @@ impl<'a> Parser<'a> {
|
|||
self.bump();
|
||||
if let InnerAttributeParsePolicy::NotPermitted { reason } = inner_parse_policy
|
||||
{
|
||||
let span = self.span;
|
||||
let span = self.token.span;
|
||||
self.diagnostic()
|
||||
.struct_span_err(span, reason)
|
||||
.note("inner attributes, like `#![no_std]`, annotate the item \
|
||||
|
@ -201,7 +201,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
token::DocComment(s) => {
|
||||
// we need to get the position of this token before we bump.
|
||||
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.span);
|
||||
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.token.span);
|
||||
if attr.style == ast::AttrStyle::Inner {
|
||||
attrs.push(attr);
|
||||
self.bump();
|
||||
|
@ -249,7 +249,7 @@ impl<'a> Parser<'a> {
|
|||
return Ok(meta);
|
||||
}
|
||||
|
||||
let lo = self.span;
|
||||
let lo = self.token.span;
|
||||
let path = self.parse_path(PathStyle::Mod)?;
|
||||
let node = self.parse_meta_item_kind()?;
|
||||
let span = lo.to(self.prev_span);
|
||||
|
@ -284,7 +284,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let found = self.this_token_to_string();
|
||||
let msg = format!("expected unsuffixed literal or identifier, found `{}`", found);
|
||||
Err(self.diagnostic().struct_span_err(self.span, &msg))
|
||||
Err(self.diagnostic().struct_span_err(self.token.span, &msg))
|
||||
}
|
||||
|
||||
/// matches meta_seq = ( COMMASEP(meta_item_inner) )
|
||||
|
|
|
@ -162,7 +162,7 @@ impl RecoverQPath for Expr {
|
|||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
|
||||
self.span_fatal(self.span, m)
|
||||
self.span_fatal(self.token.span, m)
|
||||
}
|
||||
|
||||
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
|
||||
|
@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
pub fn bug(&self, m: &str) -> ! {
|
||||
self.sess.span_diagnostic.span_bug(self.span, m)
|
||||
self.sess.span_diagnostic.span_bug(self.token.span, m)
|
||||
}
|
||||
|
||||
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
|
||||
|
@ -199,13 +199,13 @@ impl<'a> Parser<'a> {
|
|||
|
||||
crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
|
||||
let mut err = self.struct_span_err(
|
||||
self.span,
|
||||
self.token.span,
|
||||
&format!("expected identifier, found {}", self.this_token_descr()),
|
||||
);
|
||||
if let token::Ident(name, false) = self.token.kind {
|
||||
if Ident::new(name, self.span).is_raw_guess() {
|
||||
if Ident::new(name, self.token.span).is_raw_guess() {
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
self.token.span,
|
||||
"you can escape reserved keywords to use them as identifiers",
|
||||
format!("r#{}", name),
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -213,12 +213,12 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
if let Some(token_descr) = self.token_descr() {
|
||||
err.span_label(self.span, format!("expected identifier, found {}", token_descr));
|
||||
err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
|
||||
} else {
|
||||
err.span_label(self.span, "expected identifier");
|
||||
err.span_label(self.token.span, "expected identifier");
|
||||
if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
self.token.span,
|
||||
"remove this comma",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -277,11 +277,11 @@ impl<'a> Parser<'a> {
|
|||
(self.sess.source_map().next_point(self.prev_span),
|
||||
format!("expected {} here", expect)))
|
||||
};
|
||||
self.last_unexpected_token_span = Some(self.span);
|
||||
self.last_unexpected_token_span = Some(self.token.span);
|
||||
let mut err = self.fatal(&msg_exp);
|
||||
if self.token.is_ident_named(sym::and) {
|
||||
err.span_suggestion_short(
|
||||
self.span,
|
||||
self.token.span,
|
||||
"use `&&` instead of `and` for the boolean operator",
|
||||
"&&".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -289,7 +289,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
if self.token.is_ident_named(sym::or) {
|
||||
err.span_suggestion_short(
|
||||
self.span,
|
||||
self.token.span,
|
||||
"use `||` instead of `or` for the boolean operator",
|
||||
"||".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -326,7 +326,7 @@ impl<'a> Parser<'a> {
|
|||
self.token.is_keyword(kw::While)
|
||||
);
|
||||
let cm = self.sess.source_map();
|
||||
match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
|
||||
match (cm.lookup_line(self.token.span.lo()), cm.lookup_line(sp.lo())) {
|
||||
(Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => {
|
||||
// The spans are in different lines, expected `;` and found `let` or `return`.
|
||||
// High likelihood that it is only a missing `;`.
|
||||
|
@ -352,16 +352,16 @@ impl<'a> Parser<'a> {
|
|||
// | -^^^^^ unexpected token
|
||||
// | |
|
||||
// | expected one of 8 possible tokens here
|
||||
err.span_label(self.span, label_exp);
|
||||
err.span_label(self.token.span, label_exp);
|
||||
}
|
||||
_ if self.prev_span == syntax_pos::DUMMY_SP => {
|
||||
// Account for macro context where the previous span might not be
|
||||
// available to avoid incorrect output (#54841).
|
||||
err.span_label(self.span, "unexpected token");
|
||||
err.span_label(self.token.span, "unexpected token");
|
||||
}
|
||||
_ => {
|
||||
err.span_label(sp, label_exp);
|
||||
err.span_label(self.span, "unexpected token");
|
||||
err.span_label(self.token.span, "unexpected token");
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
|
@ -429,7 +429,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Keep the span at the start so we can highlight the sequence of `>` characters to be
|
||||
// removed.
|
||||
let lo = self.span;
|
||||
let lo = self.token.span;
|
||||
|
||||
// We need to look-ahead to see if we have `>` characters without moving the cursor forward
|
||||
// (since we might have the field access case and the characters we're eating are
|
||||
|
@ -474,7 +474,7 @@ impl<'a> Parser<'a> {
|
|||
// Eat from where we started until the end token so that parsing can continue
|
||||
// as if we didn't have those extra angle brackets.
|
||||
self.eat_to_tokens(&[&end]);
|
||||
let span = lo.until(self.span);
|
||||
let span = lo.until(self.token.span);
|
||||
|
||||
let plural = number_of_gt > 1 || number_of_shr >= 1;
|
||||
self.diagnostic()
|
||||
|
@ -502,7 +502,7 @@ impl<'a> Parser<'a> {
|
|||
match lhs.node {
|
||||
ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
|
||||
// respan to include both operators
|
||||
let op_span = op.span.to(self.span);
|
||||
let op_span = op.span.to(self.token.span);
|
||||
let mut err = self.diagnostic().struct_span_err(op_span,
|
||||
"chained comparison operators require parentheses");
|
||||
if op.node == BinOpKind::Lt &&
|
||||
|
@ -734,15 +734,15 @@ impl<'a> Parser<'a> {
|
|||
let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) {
|
||||
// Point at the end of the macro call when reaching end of macro arguments.
|
||||
(token::Eof, Some(_)) => {
|
||||
let sp = self.sess.source_map().next_point(self.span);
|
||||
let sp = self.sess.source_map().next_point(self.token.span);
|
||||
(sp, sp)
|
||||
}
|
||||
// We don't want to point at the following span after DUMMY_SP.
|
||||
// This happens when the parser finds an empty TokenStream.
|
||||
_ if self.prev_span == DUMMY_SP => (self.span, self.span),
|
||||
_ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span),
|
||||
// EOF, don't want to point at the following char, but rather the last token.
|
||||
(token::Eof, None) => (self.prev_span, self.span),
|
||||
_ => (self.sess.source_map().next_point(self.prev_span), self.span),
|
||||
(token::Eof, None) => (self.prev_span, self.token.span),
|
||||
_ => (self.sess.source_map().next_point(self.prev_span), self.token.span),
|
||||
};
|
||||
let msg = format!(
|
||||
"expected `{}`, found {}",
|
||||
|
@ -789,7 +789,7 @@ impl<'a> Parser<'a> {
|
|||
// interpreting `await { <expr> }?` as `<expr>?.await`.
|
||||
self.parse_block_expr(
|
||||
None,
|
||||
self.span,
|
||||
self.token.span,
|
||||
BlockCheckMode::Default,
|
||||
ThinVec::new(),
|
||||
)
|
||||
|
@ -819,9 +819,9 @@ impl<'a> Parser<'a> {
|
|||
self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
|
||||
{
|
||||
// future.await()
|
||||
let lo = self.span;
|
||||
let lo = self.token.span;
|
||||
self.bump(); // (
|
||||
let sp = lo.to(self.span);
|
||||
let sp = lo.to(self.token.span);
|
||||
self.bump(); // )
|
||||
self.struct_span_err(sp, "incorrect use of `await`")
|
||||
.span_suggestion(
|
||||
|
@ -854,7 +854,7 @@ impl<'a> Parser<'a> {
|
|||
next_sp: Span,
|
||||
maybe_path: bool,
|
||||
) {
|
||||
err.span_label(self.span, "expecting a type here because of type ascription");
|
||||
err.span_label(self.token.span, "expecting a type here because of type ascription");
|
||||
let cm = self.sess.source_map();
|
||||
let next_pos = cm.lookup_char_pos(next_sp.lo());
|
||||
let op_pos = cm.lookup_char_pos(cur_op_span.hi());
|
||||
|
@ -911,7 +911,7 @@ impl<'a> Parser<'a> {
|
|||
// we want to use the last closing delim that would apply
|
||||
for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
|
||||
if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
|
||||
&& Some(self.span) > unmatched.unclosed_span
|
||||
&& Some(self.token.span) > unmatched.unclosed_span
|
||||
{
|
||||
pos = Some(i);
|
||||
}
|
||||
|
@ -1070,28 +1070,28 @@ impl<'a> Parser<'a> {
|
|||
crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> {
|
||||
let token_str = self.this_token_descr();
|
||||
let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
|
||||
err.span_label(self.span, "expected `;` or `{`");
|
||||
err.span_label(self.token.span, "expected `;` or `{`");
|
||||
Err(err)
|
||||
}
|
||||
|
||||
crate fn eat_incorrect_doc_comment(&mut self, applied_to: &str) {
|
||||
if let token::DocComment(_) = self.token.kind {
|
||||
let mut err = self.diagnostic().struct_span_err(
|
||||
self.span,
|
||||
self.token.span,
|
||||
&format!("documentation comments cannot be applied to {}", applied_to),
|
||||
);
|
||||
err.span_label(self.span, "doc comments are not allowed here");
|
||||
err.span_label(self.token.span, "doc comments are not allowed here");
|
||||
err.emit();
|
||||
self.bump();
|
||||
} else if self.token == token::Pound && self.look_ahead(1, |t| {
|
||||
*t == token::OpenDelim(token::Bracket)
|
||||
}) {
|
||||
let lo = self.span;
|
||||
let lo = self.token.span;
|
||||
// Skip every token until next possible arg.
|
||||
while self.token != token::CloseDelim(token::Bracket) {
|
||||
self.bump();
|
||||
}
|
||||
let sp = lo.to(self.span);
|
||||
let sp = lo.to(self.token.span);
|
||||
self.bump();
|
||||
let mut err = self.diagnostic().struct_span_err(
|
||||
sp,
|
||||
|
@ -1217,16 +1217,16 @@ impl<'a> Parser<'a> {
|
|||
crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> {
|
||||
let (span, msg) = match (&self.token.kind, self.subparser_name) {
|
||||
(&token::Eof, Some(origin)) => {
|
||||
let sp = self.sess.source_map().next_point(self.span);
|
||||
let sp = self.sess.source_map().next_point(self.token.span);
|
||||
(sp, format!("expected expression, found end of {}", origin))
|
||||
}
|
||||
_ => (self.span, format!(
|
||||
_ => (self.token.span, format!(
|
||||
"expected expression, found {}",
|
||||
self.this_token_descr(),
|
||||
)),
|
||||
};
|
||||
let mut err = self.struct_span_err(span, &msg);
|
||||
let sp = self.sess.source_map().start_point(self.span);
|
||||
let sp = self.sess.source_map().start_point(self.token.span);
|
||||
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
|
||||
self.sess.expr_parentheses_needed(&mut err, *sp, None);
|
||||
}
|
||||
|
|
|
@ -271,14 +271,13 @@ impl<'a> Parser<'a> {
|
|||
let mut recovered = None;
|
||||
if self.token == token::Dot {
|
||||
// Attempt to recover `.4` as `0.4`.
|
||||
recovered = self.look_ahead(1, |t| {
|
||||
recovered = self.look_ahead(1, |next_token| {
|
||||
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix })
|
||||
= t.kind {
|
||||
let next_span = self.look_ahead_span(1);
|
||||
if self.span.hi() == next_span.lo() {
|
||||
= next_token.kind {
|
||||
if self.token.span.hi() == next_token.span.lo() {
|
||||
let s = String::from("0.") + &symbol.as_str();
|
||||
let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
|
||||
return Some(Token::new(kind, self.span.to(next_span)));
|
||||
return Some(Token::new(kind, self.token.span.to(next_token.span)));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -311,7 +310,11 @@ impl<'a> Parser<'a> {
|
|||
let (lit, span) = (token.expect_lit(), token.span);
|
||||
self.bump();
|
||||
err.report(&self.sess.span_diagnostic, lit, span);
|
||||
let lit = token::Lit::new(token::Err, lit.symbol, lit.suffix);
|
||||
// Pack possible quotes and prefixes from the original literal into
|
||||
// the error literal's symbol so they can be pretty-printed faithfully.
|
||||
let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
|
||||
let symbol = Symbol::intern(&pprust::literal_to_string(suffixless_lit));
|
||||
let lit = token::Lit::new(token::Err, symbol, lit.suffix);
|
||||
Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,8 +239,8 @@ fn maybe_source_file_to_parser(
|
|||
let (stream, unclosed_delims) = maybe_file_to_stream(sess, source_file, None)?;
|
||||
let mut parser = stream_to_parser(sess, stream, None);
|
||||
parser.unclosed_delims = unclosed_delims;
|
||||
if parser.token == token::Eof && parser.span.is_dummy() {
|
||||
parser.token.span = Span::new(end_pos, end_pos, parser.span.ctxt());
|
||||
if parser.token == token::Eof && parser.token.span.is_dummy() {
|
||||
parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
|
||||
}
|
||||
|
||||
Ok(parser)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -168,9 +168,6 @@ pub fn literal_to_string(lit: token::Lit) -> String {
|
|||
let mut out = match kind {
|
||||
token::Byte => format!("b'{}'", symbol),
|
||||
token::Char => format!("'{}'", symbol),
|
||||
token::Bool |
|
||||
token::Float |
|
||||
token::Integer => symbol.to_string(),
|
||||
token::Str => format!("\"{}\"", symbol),
|
||||
token::StrRaw(n) => format!("r{delim}\"{string}\"{delim}",
|
||||
delim="#".repeat(n as usize),
|
||||
|
@ -179,7 +176,10 @@ pub fn literal_to_string(lit: token::Lit) -> String {
|
|||
token::ByteStrRaw(n) => format!("br{delim}\"{string}\"{delim}",
|
||||
delim="#".repeat(n as usize),
|
||||
string=symbol),
|
||||
token::Err => format!("'{}'", symbol),
|
||||
token::Integer |
|
||||
token::Float |
|
||||
token::Bool |
|
||||
token::Err => symbol.to_string(),
|
||||
};
|
||||
|
||||
if let Some(suffix) = suffix {
|
||||
|
|
|
@ -714,7 +714,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
|
||||
visitor.visit_expr(subexpression)
|
||||
}
|
||||
ExprKind::Lit(_) => {}
|
||||
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
visitor.visit_ty(typ)
|
||||
|
@ -826,7 +825,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
ExprKind::TryBlock(ref body) => {
|
||||
visitor.visit_block(body)
|
||||
}
|
||||
ExprKind::Err => {}
|
||||
ExprKind::Lit(_) | ExprKind::Err => {}
|
||||
}
|
||||
|
||||
visitor.visit_expr_post(expression)
|
||||
|
|
|
@ -85,7 +85,7 @@ fn parse_assert<'a>(
|
|||
if parser.token == token::Semi {
|
||||
let mut err = cx.struct_span_warn(sp, "macro requires an expression as an argument");
|
||||
err.span_suggestion(
|
||||
parser.span,
|
||||
parser.token.span,
|
||||
"try removing semicolon",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect
|
||||
|
@ -105,7 +105,7 @@ fn parse_assert<'a>(
|
|||
// turned into an error.
|
||||
let custom_message = if let token::Literal(token::Lit { kind: token::Str, .. })
|
||||
= parser.token.kind {
|
||||
let mut err = cx.struct_span_warn(parser.span, "unexpected string literal");
|
||||
let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal");
|
||||
let comma_span = cx.source_map().next_point(parser.prev_span);
|
||||
err.span_suggestion_short(
|
||||
comma_span,
|
||||
|
|
|
@ -22,7 +22,6 @@ pub fn expand_syntax_ext(
|
|||
match e.node {
|
||||
ast::ExprKind::Lit(ref lit) => match lit.node {
|
||||
ast::LitKind::Str(ref s, _)
|
||||
| ast::LitKind::Err(ref s)
|
||||
| ast::LitKind::Float(ref s, _)
|
||||
| ast::LitKind::FloatUnsuffixed(ref s) => {
|
||||
accumulator.push_str(&s.as_str());
|
||||
|
@ -41,6 +40,9 @@ pub fn expand_syntax_ext(
|
|||
ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => {
|
||||
cx.span_err(e.span, "cannot concatenate a byte string literal");
|
||||
}
|
||||
ast::LitKind::Err(_) => {
|
||||
has_errors = true;
|
||||
}
|
||||
},
|
||||
ast::ExprKind::Err => {
|
||||
has_errors = true;
|
||||
|
|
|
@ -142,7 +142,7 @@ fn parse_args<'a>(
|
|||
|
||||
while p.token != token::Eof {
|
||||
if !p.eat(&token::Comma) {
|
||||
return Err(ecx.struct_span_err(p.span, "expected token: `,`"));
|
||||
return Err(ecx.struct_span_err(p.token.span, "expected token: `,`"));
|
||||
}
|
||||
if p.token == token::Eof {
|
||||
break;
|
||||
|
@ -154,7 +154,7 @@ fn parse_args<'a>(
|
|||
name
|
||||
} else {
|
||||
return Err(ecx.struct_span_err(
|
||||
p.span,
|
||||
p.token.span,
|
||||
"expected ident, positional arguments cannot follow named arguments",
|
||||
));
|
||||
};
|
||||
|
|
14
src/test/ui/async-await/issue-61452.rs
Normal file
14
src/test/ui/async-await/issue-61452.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// edition:2018
|
||||
#![feature(async_await)]
|
||||
|
||||
pub async fn f(x: Option<usize>) {
|
||||
x.take();
|
||||
//~^ ERROR cannot borrow `x` as mutable, as it is not declared as mutable [E0596]
|
||||
}
|
||||
|
||||
pub async fn g(x: usize) {
|
||||
x += 1;
|
||||
//~^ ERROR cannot assign twice to immutable variable `x` [E0384]
|
||||
}
|
||||
|
||||
fn main() {}
|
23
src/test/ui/async-await/issue-61452.stderr
Normal file
23
src/test/ui/async-await/issue-61452.stderr
Normal file
|
@ -0,0 +1,23 @@
|
|||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-61452.rs:5:5
|
||||
|
|
||||
LL | pub async fn f(x: Option<usize>) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | x.take();
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0384]: cannot assign twice to immutable variable `x`
|
||||
--> $DIR/issue-61452.rs:10:5
|
||||
|
|
||||
LL | pub async fn g(x: usize) {
|
||||
| -
|
||||
| |
|
||||
| first assignment to `x`
|
||||
| help: make this binding mutable: `mut x`
|
||||
LL | x += 1;
|
||||
| ^^^^^^ cannot assign twice to immutable variable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0384, E0596.
|
||||
For more information about an error, try `rustc --explain E0384`.
|
|
@ -12,4 +12,9 @@ mod nonexistent_env {
|
|||
//~^ ERROR environment variable `NON_EXISTENT` not defined
|
||||
}
|
||||
|
||||
mod erroneous_literal {
|
||||
include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
|
||||
//~^ ERROR suffixes on a string literal are invalid
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -4,6 +4,12 @@ error: environment variable `NON_EXISTENT` not defined
|
|||
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: suffixes on a string literal are invalid
|
||||
--> $DIR/issue-55897.rs:16:22
|
||||
|
|
||||
LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error[E0432]: unresolved import `prelude`
|
||||
--> $DIR/issue-55897.rs:1:5
|
||||
|
|
||||
|
@ -21,6 +27,6 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
|
|||
|
|
||||
= note: import resolution is stuck, try simplifying macro imports
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0432`.
|
||||
|
|
Loading…
Reference in a new issue