diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 93fac3181ba4b..487a82f802465 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -743,9 +743,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { // or // `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)` let def_id = self.body.source.def_id(); - if let Some(local_def_id) = def_id.as_local() - && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) - && let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value() + let hir_id = def_id + .as_local() + .and_then(|def_id| self.infcx.tcx.hir().maybe_body_owned_by(def_id)) + .and_then(|body| (BindingFinder { span: pat_span }).visit_body(&body).break_value()); + if let Some(hir_id) = hir_id && let node = self.infcx.tcx.hir_node(hir_id) && let hir::Node::LetStmt(hir::LetStmt { pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. }, @@ -767,8 +769,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { return; } + let span = local_decl.source_info.span; + let span = + hir_id.map_or(span, |hir_id| span.with_neighbor(self.infcx.tcx.hir().span(hir_id))); err.span_suggestion_verbose( - local_decl.source_info.span.shrink_to_lo(), + span.shrink_to_lo(), "consider changing this to be mutable", "mut ", Applicability::MachineApplicable, diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index f935f1b77e0b2..976ec063b91e3 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -395,9 +395,22 @@ fn maybe_use_metavar_location( return orig_tt.clone(); } - let insert = |mspans: &mut FxHashMap<_, _>, s, ms| match mspans.try_insert(s, ms) { + let insert = |mspans: &mut FxHashMap<_, _>, s, ms: Span| match mspans.try_insert(s, ms) { Ok(_) => true, - Err(err) => *err.entry.get() == ms, // Tried to insert the same span, still success + Err(mut err) => { + let old_ms = *err.entry.get(); + if ms == old_ms { + // Tried to insert the same span, still success. + return true; + } + if !ms.eq_ctxt(old_ms) && ms.ctxt().outer_expn_data().call_site.eq_ctxt(old_ms) { + // This looks like a variable passed to an inner (possibly recursive) macro call. + // The innermost metavar span is the most useful, so override. + err.entry.insert(ms); + return true; + } + false + } }; marker.visit_span(&mut metavar_span); let no_collision = match orig_tt { @@ -411,16 +424,19 @@ fn maybe_use_metavar_location( }), }; if no_collision || psess.source_map().is_imported(metavar_span) { + if let TokenTree::Token(token, _) = orig_tt { + return TokenTree::Token(token.clone(), Spacing::Alone); + } return orig_tt.clone(); } // Setting metavar spans for the heuristic spans gives better opportunities for combining them // with neighboring spans even despite their different syntactic contexts. match orig_tt { - TokenTree::Token(Token { kind, span }, spacing) => { + TokenTree::Token(Token { kind, span }, _spacing) => { let span = metavar_span.with_ctxt(span.ctxt()); with_metavar_spans(|mspans| insert(mspans, span, metavar_span)); - TokenTree::Token(Token { kind: kind.clone(), span }, *spacing) + TokenTree::Token(Token { kind: kind.clone(), span }, Spacing::Alone) } TokenTree::Delimited(dspan, dspacing, delimiter, tts) => { let open = metavar_span.with_ctxt(dspan.open.ctxt()); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 240a749de96a6..9ca7a8bed7cf8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -56,7 +56,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )); } - if self_ty.span.edition().at_least_rust_2021() { + if tcx.hir().span_in_context(self_ty.hir_id).edition().at_least_rust_2021() { let msg = "trait objects must include the `dyn` keyword"; let label = "add `dyn` keyword before this trait"; let mut diag = diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index a385bc70e359b..7cee8221be745 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2454,7 +2454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Path(QPath::Resolved(_, path)) => { // local binding if let hir::def::Res::Local(hir_id) = path.res { - let span = tcx.hir().span(hir_id); + let span = tcx.hir().span_in_context(hir_id); let filename = tcx.sess.source_map().span_to_filename(span); let parent_node = self.tcx.parent_hir_node(hir_id); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f3a904022e9ed..573236fbce570 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -718,8 +718,9 @@ fn lint_wide_pointer<'tcx>( return; }; + let (l_span, r_span) = (l.span.with_neighbor(e.span), r.span.with_neighbor(e.span)); let (Some(l_span), Some(r_span)) = - (l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span)) + (l_span.find_ancestor_inside(e.span), r_span.find_ancestor_inside(e.span)) else { return cx.emit_span_lint( AMBIGUOUS_WIDE_POINTER_COMPARISONS, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 305ba1ef3bbc8..bf1397ada6237 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -935,6 +935,11 @@ impl<'hir> Map<'hir> { } } + pub fn span_in_context(self, hir_id: HirId) -> Span { + let parent_span = self.span(self.tcx.parent_hir_id(hir_id)); + self.span(hir_id).with_neighbor(parent_span) + } + /// Get a representation of this `id` for debugging purposes. /// NOTE: Do NOT use this in diagnostics! pub fn node_to_string(self, id: HirId) -> String { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3cdc20b6c659f..136a8350731ba 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -249,10 +249,11 @@ impl<'a> Parser<'a> { continue; } + let op_span = op.span; let op = op.node; // Special cases: if op == AssocOp::As { - lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; + lhs = self.parse_assoc_op_cast(lhs, lhs_span, op_span, ExprKind::Cast)?; continue; } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to @@ -274,7 +275,7 @@ impl<'a> Parser<'a> { this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::Unparsed { attrs }) })?; - let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); + let span = self.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span); lhs = match op { AssocOp::Add | AssocOp::Subtract @@ -453,7 +454,7 @@ impl<'a> Parser<'a> { None }; let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span); - let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); + let span = self.mk_expr_sp(&lhs, lhs.span, cur_op_span, rhs_span); let limits = if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; let range = self.mk_range(Some(lhs), rhs, limits); @@ -674,10 +675,11 @@ impl<'a> Parser<'a> { &mut self, lhs: P, lhs_span: Span, + op_span: Span, expr_kind: fn(P, P) -> ExprKind, ) -> PResult<'a, P> { let mk_expr = |this: &mut Self, lhs: P, rhs: P| { - this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs)) + this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs)) }; // Save the state of the parser before parsing type normally, in case there is a @@ -3852,11 +3854,13 @@ impl<'a> Parser<'a> { /// Create expression span ensuring the span of the parent node /// is larger than the span of lhs and rhs, including the attributes. - fn mk_expr_sp(&self, lhs: &P, lhs_span: Span, rhs_span: Span) -> Span { + fn mk_expr_sp(&self, lhs: &P, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span { lhs.attrs .iter() .find(|a| a.style == AttrStyle::Outer) .map_or(lhs_span, |a| a.span) + // An approximation to #126763. + .to(op_span) .to(rhs_span) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index cfd0a72c056d5..d0fe14e50eb0a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -687,9 +687,9 @@ impl<'a> Parser<'a> { self.is_keyword_ahead(0, &[kw::Const]) && self.look_ahead(1, |t| match &t.kind { // async closures do not work with const closures, so we do not parse that here. - token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => { - true - } + token::Ident(kw::Move | kw::Static, IdentIsRaw::No) + | token::OrOr + | token::BinOp(token::Or) => true, _ => false, }) } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index da8d1194325b4..0e1a83dc50e1c 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -211,7 +211,8 @@ impl<'a> Parser<'a> { if self.eat(&token::PathSep) { segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } - self.parse_path_segments(&mut segments, style, ty_generics)?; + let sep_span = self.parse_path_segments(&mut segments, style, ty_generics)?; + let lo = sep_span.map_or(lo, |sep_span| lo.with_neighbor(sep_span)); Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None }) } @@ -220,7 +221,9 @@ impl<'a> Parser<'a> { segments: &mut ThinVec, style: PathStyle, ty_generics: Option<&Generics>, - ) -> PResult<'a, ()> { + ) -> PResult<'a, Option> { + // An approximation to #126763. + let mut sep_span = None; loop { let segment = self.parse_path_segment(style, ty_generics)?; if style.has_generic_ambiguity() { @@ -268,7 +271,9 @@ impl<'a> Parser<'a> { continue; } - return Ok(()); + return Ok(sep_span); + } else { + sep_span = Some(self.prev_token.span); } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 266956d63d710..261babe5aa891 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -876,6 +876,7 @@ impl Span { /// Check if you can select metavar spans for the given spans to get matching contexts. fn try_metavars(a: SpanData, b: SpanData, a_orig: Span, b_orig: Span) -> (SpanData, SpanData) { + let (a_orig, b_orig) = (a_orig.with_parent(None), b_orig.with_parent(None)); let get = |mspans: &FxHashMap<_, _>, s| mspans.get(&s).copied(); match with_metavar_spans(|mspans| (get(mspans, a_orig), get(mspans, b_orig))) { (None, None) => {} @@ -938,7 +939,7 @@ impl Span { pub fn with_neighbor(self, neighbor: Span) -> Span { match Span::prepare_to_combine(self, neighbor) { Ok((this, ..)) => this.span(), - Err(_) => self, + Err(fallback) => self.with_ctxt(fallback.ctxt()), } } diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr index 1de27a072cf73..25b7a93ffe3f3 100644 --- a/tests/ui/consts/const-float-classify.stderr +++ b/tests/ui/consts/const-float-classify.stderr @@ -29,7 +29,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -53,7 +53,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -77,7 +77,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -101,7 +101,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -125,7 +125,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -149,7 +149,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -173,7 +173,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] @@ -197,7 +197,7 @@ error[E0284]: type annotations needed --> $DIR/const-float-classify.rs:21:35 | LL | const _: () = assert!($a == $b); - | ^^ cannot infer the value of the constant `_` + | ^^^^^ cannot infer the value of the constant `_` ... LL | / suite! { LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] diff --git a/tests/ui/lint/wide_pointer_comparisons.rs b/tests/ui/lint/wide_pointer_comparisons.rs index 05097cbf1e3de..a5e3f4754b8f5 100644 --- a/tests/ui/lint/wide_pointer_comparisons.rs +++ b/tests/ui/lint/wide_pointer_comparisons.rs @@ -146,12 +146,10 @@ fn main() { { macro_rules! cmp { ($a:tt, $b:tt) => { $a == $b } + //~^ WARN ambiguous wide pointer comparison } - // FIXME: This lint uses some custom span combination logic. - // Rewrite it to adapt to the new metavariable span rules. cmp!(a, b); - //~^ WARN ambiguous wide pointer comparison } { diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 81a221c0ee640..3a743623fb17d 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -586,18 +586,22 @@ LL | std::ptr::eq(*a, *b) | ~~~~~~~~~~~~~ ~ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - --> $DIR/wide_pointer_comparisons.rs:153:14 + --> $DIR/wide_pointer_comparisons.rs:148:33 | +LL | ($a:tt, $b:tt) => { $a == $b } + | ^^^^^^^^ +... LL | cmp!(a, b); - | ^^^^ + | ---------- in this macro invocation | + = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | -LL | cmp!(std::ptr::addr_eq(a, b)); - | ++++++++++++++++++ ~ + +LL | ($a:tt, $b:tt) => { std::ptr::addr_eq($a, $b) } + | ++++++++++++++++++ ~ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - --> $DIR/wide_pointer_comparisons.rs:159:39 + --> $DIR/wide_pointer_comparisons.rs:157:39 | LL | ($a:ident, $b:ident) => { $a == $b } | ^^^^^^^^ @@ -612,10 +616,10 @@ LL | ($a:ident, $b:ident) => { std::ptr::addr_eq($a, $b) } | ++++++++++++++++++ ~ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - --> $DIR/wide_pointer_comparisons.rs:169:37 + --> $DIR/wide_pointer_comparisons.rs:167:37 | LL | ($a:expr, $b:expr) => { $a == $b } - | ^^ + | ^^^^^ ... LL | cmp!(&a, &b); | ------------ in this macro invocation diff --git a/tests/ui/methods/method-on-ambiguous-numeric-type.stderr b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr index 124270402727d..060595e1d406b 100644 --- a/tests/ui/methods/method-on-ambiguous-numeric-type.stderr +++ b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr @@ -47,8 +47,8 @@ LL | local_bar_tt.pow(2); | help: you must specify a type for this binding, like `i32` | -LL | local_mac_tt!(local_bar_tt: i32); - | +++++ +LL | ($tt:tt) => { let $tt: i32 = 42; } + | +++++ error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` --> $DIR/method-on-ambiguous-numeric-type.rs:37:9