Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,54 @@ pub struct DelimSpan {

impl DelimSpan {
pub fn from_single(sp: Span) -> Self {
DelimSpan { open: sp, close: sp }
let default_open = sp.shrink_to_lo();
let default_close = sp.shrink_to_hi();

let Some(sm) = rustc_span::source_map::get_source_map() else {
// No source map available.
return Self { open: default_open, close: default_close };
};

let (open, close) = sm
.span_to_source(sp, |src, start, end| {
let Some(src) = src.get(start..end) else {
return Ok((default_close, default_close));
};

// Only check the first and last characters.
// If there is white space or other characters
// other than `( ... )`, `[ ... ]`, and `{ ... }`.
// I assume that is intentionally included in this
// span so we don't want to shrink the span by
// searching for the delimiters, and setting
// the open and close spans to some more interior
// position.
let mut chars = src.chars();
// just using '_' as a place holder.
let first = chars.next().unwrap_or('_');
let last = chars.last().unwrap_or('_');

// Thought maybe scan through if first is '(', '[', or '{'
// and see if the last matches up e.g. make sure it's not some
// extra mismatched delimiter.

let open = sp.subspan(0..first.len_utf8()).unwrap_or(default_open);

let len = (sp.hi() - sp.lo()).0 as usize;
let pos = len.checked_sub(last.len_utf8()).unwrap_or(0);
let close = sp.subspan(pos..).unwrap_or(default_close);

Ok(match (first, last) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why the logic above is so overcomplicated.
let first = src[0] and let last = src[src.len() - 1].
open is sp.with_lo(sp.lo() + BytePos(1)) if the source map check passes, close is sp.with_hi(sp.hi() - BytePos(1)) .

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let first = chars.next().unwrap_or('_');
let last = chars.last().unwrap_or('_');

Won't panic even if the length is some reason Zero. Also it won't panic if the first and last glyphs are not an ASCII code points still, although I could use src.as_bytes() since it is unlikely that a non-ASCII Delimiter would be added to the language. So it would probably be fair to remove needing to use the len_utf8() and just work on the bytes directly instead of a &str

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything we are checking for is ASCII, we can work with byte positions in src.
The empty string case needs to be excluded from the start, yeah.

('(', ')') | ('{', '}') | ('[', ']') => (open, close),
('(', _) | ('{', _) | ('[', _) => (open, default_close),
(_, ')') | (_, '}') | (_, ']') => (default_open, close),
(_, _) => (default_close, default_open),
})
})
.ok()
.unwrap_or((default_open, default_close));

DelimSpan { open, close }
}

pub fn from_pair(open: Span, close: Span) -> Self {
Expand Down
33 changes: 32 additions & 1 deletion compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ use std::cmp::{self, Ordering};
use std::fmt::Display;
use std::hash::Hash;
use std::io::{self, Read};
use std::ops::{Add, Range, Sub};
use std::ops::{Add, Bound, Range, RangeBounds, Sub};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;
Expand Down Expand Up @@ -1176,6 +1176,37 @@ impl Span {
pub fn normalize_to_macro_rules(self) -> Span {
self.map_ctxt(|ctxt| ctxt.normalize_to_macro_rules())
}

/// This function is similar to `Span::from_inner`, but it
/// will return `None` if the relative Range span exceeds
/// the bounds of span.
pub fn subspan<I: Copy, R: RangeBounds<I>>(self, subspan: R) -> Option<Span>
where
u32: TryFrom<I>,
{
let lo = self.lo().0;
let hi = self.hi().0;

let start = match subspan.start_bound() {
Bound::Included(s) => u32::try_from(*s).ok()?,
Bound::Excluded(s) => u32::try_from(*s).ok()?.checked_add(1)?,
Bound::Unbounded => 0,
};

let end = match subspan.end_bound() {
Bound::Included(e) => u32::try_from(*e).ok()?.checked_add(1)?,
Bound::Excluded(e) => u32::try_from(*e).ok()?,
Bound::Unbounded => hi - lo,
};

let new_lo = lo.checked_add(start)?;
let new_hi = lo.checked_add(end)?;
if new_lo > hi || new_hi > hi {
return None;
}

Some(self.with_lo(BytePos(new_lo)).with_hi(BytePos(new_hi)))
}
}

impl Default for Span {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/tests/ui/uninhabited_references.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ error: dereferencing a reference to an uninhabited type would be undefined behav
--> tests/ui/uninhabited_references.rs:12:30
|
LL | fn $name(x: &$ty) -> &$ty {
| ^^^^
| ^
...
LL | ret_something!(id_never, !);
| --------------------------- in this macro invocation
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/attributes/nonterminal-expansion.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable
--> $DIR/nonterminal-expansion.rs:7:22
--> $DIR/nonterminal-expansion.rs:7:24
|
LL | #[repr(align($n))]
| ^^
| ^
...
LL | pass_nonterminal!(n!());
| ----------------------- in this macro invocation
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/span-semicolon-issue-139049.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0597]: `l` does not live long enough
--> $DIR/span-semicolon-issue-139049.rs:11:41
|
LL | macro_rules! perform { ($e:expr) => { D(&$e).end() } }
| --^^^-
| --^---
| | |
| | borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
Expand All @@ -24,7 +24,7 @@ error[E0597]: `l` does not live long enough
--> $DIR/span-semicolon-issue-139049.rs:11:41
|
LL | macro_rules! perform { ($e:expr) => { D(&$e).end() } }
| --^^^-
| --^---
| | |
| | borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//@ run-rustfix
//@ edition:2018
//@ check-pass
#![warn(rust_2021_compatibility)]
Expand All @@ -25,7 +24,6 @@ macro_rules! m {
fn main() {
let a = (Foo(0), Foo(1));
m!({
//~^ HELP: add a dummy
let x = a.0;
println!("{:?}", x);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/closure-body-macro-fragment.rs:16:17
--> $DIR/closure-body-macro-fragment.rs:15:17
|
LL | let f = || $body;
| ^^
Expand All @@ -8,7 +8,6 @@ LL | }};
| - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure
...
LL | / m!({
LL | |
LL | | let x = a.0;
| | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0`
LL | | println!("{:?}", x);
Expand All @@ -17,17 +16,16 @@ LL | | });
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/closure-body-macro-fragment.rs:4:9
--> $DIR/closure-body-macro-fragment.rs:3:9
|
LL | #![warn(rust_2021_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]`
= note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
help: add a dummy let to cause `a` to be fully captured
|
LL ~ m!({
LL + let _ = &a;
|
LL | m!(@ $body{ let _ = &a; });
| +++++++++++++ +

warning: 1 warning emitted

Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ LL | #[cfg(a = b"hi")]
= note: expected a normal string literal, not a byte string literal

error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable
--> $DIR/cfg-attr-syntax-validation.rs:51:25
--> $DIR/cfg-attr-syntax-validation.rs:51:30
|
LL | #[cfg(feature = $expr)]
| ^^^^^
| ^
...
LL | generate_s10!(concat!("nonexistent"));
| ------------------------------------- in this macro invocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ LL | #[cfg_attr(true)]
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>

error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable
--> $DIR/cfg_attr-attr-syntax-validation.rs:30:30
--> $DIR/cfg_attr-attr-syntax-validation.rs:30:35
|
LL | #[cfg_attr(feature = $expr)]
| ---------------------^^^^^-- help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]`
| --------------------------^- help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]`
...
LL | generate_s10!(concat!("nonexistent"));
| ------------------------------------- in this macro invocation
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/did_you_mean/bad-assoc-expr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,16 @@ error: missing angle brackets in associated item path
--> $DIR/bad-assoc-expr.rs:23:19
|
LL | ($ty: ty) => ($ty::clone(&0))
| ^^^
| ^
...
LL | expr!(u8);
| --------- in this macro invocation
|
= note: this error originates in the macro `expr` (in Nightly builds, run with -Z macro-backtrace for more info)
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
LL | ($ty: ty) => (<$ty>::clone(&0))
| + +
LL | ($ty: ty) => (<>$ty::clone(&0))
| ++

error: aborting due to 9 previous errors

6 changes: 3 additions & 3 deletions tests/ui/did_you_mean/bad-assoc-pat.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@ error: missing angle brackets in associated item path
--> $DIR/bad-assoc-pat.rs:21:19
|
LL | ($ty: ty) => ($ty::AssocItem)
| ^^^
| ^
...
LL | pat!(u8) => {}
| -------- in this macro invocation
|
= note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info)
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
LL | ($ty: ty) => (<$ty>::AssocItem)
| + +
LL | ($ty: ty) => (<>$ty::AssocItem)
| ++

error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope
--> $DIR/bad-assoc-pat.rs:3:15
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,16 @@ error: missing angle brackets in associated item path
--> $DIR/bad-assoc-ty.rs:44:19
|
LL | ($ty: ty) => ($ty::AssocTy);
| ^^^
| ^
...
LL | type J = ty!(u8);
| ------- in this macro invocation
|
= note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
LL | ($ty: ty) => (<$ty>::AssocTy);
| + +
LL | ($ty: ty) => (<>$ty::AssocTy);
| ++

error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:5:10
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,16 @@ error: missing angle brackets in associated item path
--> $DIR/bad-assoc-ty.rs:44:19
|
LL | ($ty: ty) => ($ty::AssocTy);
| ^^^
| ^
...
LL | type J = ty!(u8);
| ------- in this macro invocation
|
= note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
LL | ($ty: ty) => (<$ty>::AssocTy);
| + +
LL | ($ty: ty) => (<>$ty::AssocTy);
| ++

error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:5:10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ error[E0005]: refutable pattern in local binding
--> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17
|
LL | let ...$e;
| ^^^^^ pattern `1_i32..=i32::MAX` not covered
| ^^^ pattern `1_i32..=i32::MAX` not covered
...
LL | mac!(0);
| ------- in this macro invocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ LL + let $e..;
|

error[E0005]: refutable pattern in local binding
--> $DIR/half-open-range-pats-inclusive-no-end.rs:18:17
--> $DIR/half-open-range-pats-inclusive-no-end.rs:18:19
|
LL | let $e...;
| ^^^^^ pattern `i32::MIN..=-1_i32` not covered
| ^^^ pattern `i32::MIN..=-1_i32` not covered
...
LL | mac!(0);
| ------- in this macro invocation
Expand All @@ -99,10 +99,10 @@ LL | mac!(0);
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0005]: refutable pattern in local binding
--> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17
--> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19
|
LL | let $e..=;
| ^^^^^ pattern `i32::MIN..=-1_i32` not covered
| ^^^ pattern `i32::MIN..=-1_i32` not covered
...
LL | mac!(0);
| ------- in this macro invocation
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/imports/import-prefix-macro-2.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: expected identifier, found metavariable
--> $DIR/import-prefix-macro-2.rs:11:26
--> $DIR/import-prefix-macro-2.rs:11:28
|
LL | ($p: path) => (use ::$p {S, Z});
| ^^ expected identifier, found metavariable
| ^ expected identifier, found metavariable
...
LL | import! { a::b::c }
| ------------------- in this macro invocation
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/lint/lint-double-negations-macro.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ warning: use of a double negation
--> $DIR/lint-double-negations-macro.rs:9:9
|
LL | --$e
| ^^^^
| ^^
...
LL | bad_macro!(1);
| ------------- in this macro invocation
Expand All @@ -13,8 +13,8 @@ LL | bad_macro!(1);
= note: this warning originates in the macro `bad_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
help: add parentheses for clarity
|
LL | -(-$e)
| + +
LL | -(-)$e
| + +

warning: 1 warning emitted

Loading
Loading