From fb1cca29377d0ed227927e499d3ee6fe4b6af584 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 5 Jan 2024 17:29:57 +0300 Subject: parser: Tiny refactoring --- compiler/rustc_parse/src/parser/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0b24e784126..da57ce01a56 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3735,7 +3735,7 @@ impl<'a> Parser<'a> { } pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P { - P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None }) + self.mk_expr_with_attrs(span, kind, AttrVec::new()) } pub(super) fn mk_expr_err(&self, span: Span) -> P { -- cgit 1.4.1-3-g733a5 From 508d1ff7d84b625aef24c6a9cb25bbf6a76134d8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 5 Jan 2024 17:30:14 +0300 Subject: rustc_span: More consistent span combination operations --- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 4 +- compiler/rustc_span/src/lib.rs | 96 ++++++++++++++++----------------- 3 files changed, 50 insertions(+), 52 deletions(-) (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index da57ce01a56..880743ddd3c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2489,7 +2489,7 @@ impl<'a> Parser<'a> { } ExprKind::Block(_, None) => { this.dcx().emit_err(errors::IfExpressionMissingCondition { - if_span: lo.shrink_to_hi(), + if_span: lo.with_neighbor(cond.span).shrink_to_hi(), block_span: self.sess.source_map().start_point(cond_span), }); std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi())) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0ac0b678aba..2ce27ff66e1 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2118,7 +2118,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); err.span_suggestion( - span.shrink_to_hi(), + span.with_neighbor(self.token.span).shrink_to_hi(), "add a semicolon", ';', Applicability::MaybeIncorrect, @@ -2632,7 +2632,7 @@ impl<'a> Parser<'a> { let is_name_required = match this.token.kind { token::DotDotDot => false, - _ => req_name(this.token.span.edition()), + _ => req_name(this.token.span.with_neighbor(this.prev_token.span).edition()), }; let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 8f64eed9a87..14f9a4ac2a9 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -826,6 +826,39 @@ impl Span { ) } + /// Prepare two spans to a combine operation like `to` or `between`. + /// FIXME: consider using declarative macro metavariable spans for the given spans if they are + /// better suitable for combining (#119412). + fn prepare_to_combine( + a_orig: Span, + b_orig: Span, + ) -> Result<(SpanData, SpanData, Option), Span> { + let (a, b) = (a_orig.data(), b_orig.data()); + + if a.ctxt != b.ctxt { + // Context mismatches usually happen when procedural macros combine spans copied from + // the macro input with spans produced by the macro (`Span::*_site`). + // In that case we consider the combined span to be produced by the macro and return + // the original macro-produced span as the result. + // Otherwise we just fall back to returning the first span. + // Combining locations typically doesn't make sense in case of context mismatches. + // `is_root` here is a fast path optimization. + let a_is_callsite = a.ctxt.is_root() || a.ctxt == b.span().source_callsite().ctxt(); + return Err(if a_is_callsite { b_orig } else { a_orig }); + } + + let parent = if a.parent == b.parent { a.parent } else { None }; + Ok((a, b, parent)) + } + + /// This span, but in a larger context, may switch to the metavariable span if suitable. + pub fn with_neighbor(self, neighbor: Span) -> Span { + match Span::prepare_to_combine(self, neighbor) { + Ok((this, ..)) => Span::new(this.lo, this.hi, this.ctxt, this.parent), + Err(_) => self, + } + } + /// Returns a `Span` that would enclose both `self` and `end`. /// /// Note that this can also be used to extend the span "backwards": @@ -837,26 +870,12 @@ impl Span { /// ^^^^^^^^^^^^^^^^^^^^ /// ``` pub fn to(self, end: Span) -> Span { - let span_data = self.data(); - let end_data = end.data(); - // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). - // Return the macro span on its own to avoid weird diagnostic output. It is preferable to - // have an incomplete span than a completely nonsensical one. - if span_data.ctxt != end_data.ctxt { - if span_data.ctxt.is_root() { - return end; - } else if end_data.ctxt.is_root() { - return self; + match Span::prepare_to_combine(self, end) { + Ok((from, to, parent)) => { + Span::new(cmp::min(from.lo, to.lo), cmp::max(from.hi, to.hi), from.ctxt, parent) } - // Both spans fall within a macro. - // FIXME(estebank): check if it is the *same* macro. + Err(fallback) => fallback, } - Span::new( - cmp::min(span_data.lo, end_data.lo), - cmp::max(span_data.hi, end_data.hi), - if span_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt }, - if span_data.parent == end_data.parent { span_data.parent } else { None }, - ) } /// Returns a `Span` between the end of `self` to the beginning of `end`. @@ -867,14 +886,12 @@ impl Span { /// ^^^^^^^^^^^^^ /// ``` pub fn between(self, end: Span) -> Span { - let span = self.data(); - let end = end.data(); - Span::new( - span.hi, - end.lo, - if end.ctxt.is_root() { end.ctxt } else { span.ctxt }, - if span.parent == end.parent { span.parent } else { None }, - ) + match Span::prepare_to_combine(self, end) { + Ok((from, to, parent)) => { + Span::new(cmp::min(from.hi, to.hi), cmp::max(from.lo, to.lo), from.ctxt, parent) + } + Err(fallback) => fallback, + } } /// Returns a `Span` from the beginning of `self` until the beginning of `end`. @@ -885,31 +902,12 @@ impl Span { /// ^^^^^^^^^^^^^^^^^ /// ``` pub fn until(self, end: Span) -> Span { - // Most of this function's body is copied from `to`. - // We can't just do `self.to(end.shrink_to_lo())`, - // because to also does some magic where it uses min/max so - // it can handle overlapping spans. Some advanced mis-use of - // `until` with different ctxts makes this visible. - let span_data = self.data(); - let end_data = end.data(); - // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). - // Return the macro span on its own to avoid weird diagnostic output. It is preferable to - // have an incomplete span than a completely nonsensical one. - if span_data.ctxt != end_data.ctxt { - if span_data.ctxt.is_root() { - return end; - } else if end_data.ctxt.is_root() { - return self; + match Span::prepare_to_combine(self, end) { + Ok((from, to, parent)) => { + Span::new(cmp::min(from.lo, to.lo), cmp::max(from.lo, to.lo), from.ctxt, parent) } - // Both spans fall within a macro. - // FIXME(estebank): check if it is the *same* macro. + Err(fallback) => fallback, } - Span::new( - span_data.lo, - end_data.lo, - if end_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt }, - if span_data.parent == end_data.parent { span_data.parent } else { None }, - ) } pub fn from_inner(self, inner: InnerSpan) -> Span { -- cgit 1.4.1-3-g733a5