Skip to content

Commit d9ac2be

Browse files
committed
Handle proc-macro spans pointing at attribute in suggestions
Hide invalid proc-macro suggestions and track spans coming from proc-macros pointing at attribute. Effectively, unless the proc-macro keeps user spans, suggestions will not be produced for the code they produce. Account for desugaring when checking if a span can be used for suggestions Fix rust-lang#106720.
1 parent 2e7034e commit d9ac2be

File tree

69 files changed

+2905
-2666
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2905
-2666
lines changed

compiler/rustc_ast_lowering/src/path.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
286286
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span)
287287
} else if generic_args.is_empty() {
288288
// If there are brackets, but not generic arguments, then use the opening bracket
289-
generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
289+
self.tcx.adjust_span(generic_args.span).with_hi(generic_args.span.lo() + BytePos(1))
290290
} else {
291291
// Else use an empty span right after the opening bracket.
292-
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
292+
self.tcx
293+
.adjust_span(generic_args.span)
294+
.with_lo(generic_args.span.lo() + BytePos(1))
295+
.shrink_to_lo()
293296
};
294297

295298
generic_args.args.insert_many(

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2073,12 +2073,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
20732073
Ok(string) => {
20742074
if string.starts_with("async ") {
20752075
let pos = args_span.lo() + BytePos(6);
2076-
(args_span.with_lo(pos).with_hi(pos), "move ")
2076+
(self.infcx.tcx.adjust_span(args_span).with_lo(pos).with_hi(pos), "move ")
20772077
} else if string.starts_with("async|") {
20782078
let pos = args_span.lo() + BytePos(5);
2079-
(args_span.with_lo(pos).with_hi(pos), " move")
2079+
(self.infcx.tcx.adjust_span(args_span).with_lo(pos).with_hi(pos), " move")
20802080
} else {
2081-
(args_span.shrink_to_lo(), "move ")
2081+
(self.infcx.tcx.adjust_span(args_span).shrink_to_lo(), "move ")
20822082
}
20832083
}
20842084
Err(_) => (args_span, "move |<args>| <body>"),

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -457,15 +457,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
457457
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
458458
Ok(snippet) if snippet.starts_with('*') => {
459459
err.span_suggestion_verbose(
460-
span.with_hi(span.lo() + BytePos(1)),
460+
self.infcx.tcx.adjust_span(span).with_hi(span.lo() + BytePos(1)),
461461
"consider removing the dereference here",
462462
String::new(),
463463
Applicability::MaybeIncorrect,
464464
);
465465
}
466466
_ => {
467467
err.span_suggestion_verbose(
468-
span.shrink_to_lo(),
468+
self.infcx.tcx.adjust_span(span).shrink_to_lo(),
469469
"consider borrowing here",
470470
'&',
471471
Applicability::MaybeIncorrect,

compiler/rustc_builtin_macros/src/alloc_error_handler.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use thin_vec::{thin_vec, ThinVec};
1010

1111
pub fn expand(
1212
ecx: &mut ExtCtxt<'_>,
13-
_span: Span,
13+
span: Span,
1414
meta_item: &ast::MetaItem,
1515
item: Annotatable,
1616
) -> Vec<Annotatable> {
@@ -36,7 +36,7 @@ pub fn expand(
3636
};
3737

3838
// Generate a bunch of new items using the AllocFnFactory
39-
let span = ecx.with_def_site_ctxt(item.span);
39+
let span = ecx.with_def_site_ctxt(span);
4040

4141
// Generate item statements for the allocator methods.
4242
let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];

compiler/rustc_builtin_macros/src/derive.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
138138
}
139139
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
140140
};
141-
struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",)
141+
struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal")
142142
.span_label(lit.span, "not a trait")
143143
.help(&help_msg)
144144
.emit();

compiler/rustc_const_eval/src/transform/check_consts/ops.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,15 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
256256
{
257257
let rhs_pos =
258258
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
259-
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
259+
let rhs_span =
260+
tcx.adjust_span(span).with_lo(rhs_pos).with_hi(rhs_pos);
260261
err.multipart_suggestion(
261262
"consider dereferencing here",
262263
vec![
263-
(span.shrink_to_lo(), deref.clone()),
264+
(
265+
tcx.adjust_span(span).shrink_to_lo(),
266+
deref.clone(),
267+
),
264268
(rhs_span, deref),
265269
],
266270
Applicability::MachineApplicable,

compiler/rustc_errors/src/diagnostic.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,10 @@ impl Diagnostic {
621621
.map(|(span, snippet)| SubstitutionPart { snippet, span })
622622
.collect::<Vec<_>>();
623623

624+
if !parts.iter().all(|sub| sub.span.can_be_used_for_suggestions()) {
625+
return self;
626+
}
627+
624628
parts.sort_unstable_by_key(|part| part.span);
625629

626630
assert!(!parts.is_empty());
@@ -711,6 +715,9 @@ impl Diagnostic {
711715
!(sp.is_empty() && suggestion.to_string().is_empty()),
712716
"Span must not be empty and have no suggestion"
713717
);
718+
if !sp.can_be_used_for_suggestions() {
719+
return self;
720+
}
714721
self.push_suggestion(CodeSuggestion {
715722
substitutions: vec![Substitution {
716723
parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
@@ -774,6 +781,9 @@ impl Diagnostic {
774781
!(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())),
775782
"Span must not be empty and have no suggestion"
776783
);
784+
if !sp.can_be_used_for_suggestions() {
785+
return self;
786+
}
777787

778788
let substitutions = suggestions
779789
.into_iter()
@@ -799,12 +809,16 @@ impl Diagnostic {
799809
) -> &mut Self {
800810
let substitutions = suggestions
801811
.into_iter()
802-
.map(|sugg| {
812+
.filter_map(|sugg| {
803813
let mut parts = sugg
804814
.into_iter()
805815
.map(|(span, snippet)| SubstitutionPart { snippet, span })
806816
.collect::<Vec<_>>();
807817

818+
if !parts.iter().all(|sub| sub.span.can_be_used_for_suggestions()) {
819+
return None;
820+
}
821+
808822
parts.sort_unstable_by_key(|part| part.span);
809823

810824
assert!(!parts.is_empty());
@@ -819,7 +833,7 @@ impl Diagnostic {
819833
"suggestion must not have overlapping parts",
820834
);
821835

822-
Substitution { parts }
836+
Some(Substitution { parts })
823837
})
824838
.collect();
825839

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1351,7 +1351,7 @@ fn compare_number_of_method_arguments<'tcx>(
13511351
if pos == 0 {
13521352
arg.span
13531353
} else {
1354-
arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
1354+
tcx.adjust_span(arg.span).with_lo(trait_m_sig.decl.inputs[0].span.lo())
13551355
}
13561356
})
13571357
})
@@ -1367,7 +1367,7 @@ fn compare_number_of_method_arguments<'tcx>(
13671367
if pos == 0 {
13681368
arg.span
13691369
} else {
1370-
arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
1370+
tcx.adjust_span(arg.span).with_lo(impl_m_sig.decl.inputs[0].span.lo())
13711371
}
13721372
})
13731373
.unwrap_or_else(|| tcx.def_span(impl_m.def_id));
@@ -1464,7 +1464,8 @@ fn compare_synthetic_generics<'tcx>(
14641464

14651465
// in case there are no generics, take the spot between the function name
14661466
// and the opening paren of the argument list
1467-
let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
1467+
let new_generics_span =
1468+
tcx.adjust_span(tcx.def_ident_span(impl_def_id)?).shrink_to_hi();
14681469
// in case there are generics, just replace them
14691470
let generics_span =
14701471
impl_m.generics.span.substitute_dummy(new_generics_span);

compiler/rustc_hir_analysis/src/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ fn missing_items_err(
220220
let hi = full_impl_span.hi() - BytePos(1);
221221
// Point at the place right before the closing brace of the relevant `impl` to suggest
222222
// adding the associated item at the end of its body.
223-
let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi);
223+
let sugg_sp = tcx.adjust_span(full_impl_span).with_lo(hi).with_hi(hi);
224224
// Obtain the level of indentation ending in `sugg_sp`.
225225
let padding =
226226
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());

compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -610,10 +610,10 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
610610

611611
AngleBrackets::Available => {
612612
let (sugg_span, is_first) = if self.num_provided_lifetime_args() == 0 {
613-
(self.gen_args.span().unwrap().shrink_to_lo(), true)
613+
(self.tcx.adjust_span(self.gen_args.span().unwrap()).shrink_to_lo(), true)
614614
} else {
615615
let last_lt = &self.gen_args.args[self.num_provided_lifetime_args() - 1];
616-
(last_lt.span().shrink_to_hi(), false)
616+
(self.tcx.adjust_span(last_lt.span()).shrink_to_hi(), false)
617617
};
618618
let has_non_lt_args = self.num_provided_type_or_const_args() != 0;
619619
let has_bindings = !self.gen_args.bindings.is_empty();
@@ -658,14 +658,14 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
658658
);
659659
}
660660
AngleBrackets::Available => {
661-
let gen_args_span = self.gen_args.span().unwrap();
661+
let gen_args_span = self.tcx.adjust_span(self.gen_args.span().unwrap());
662662
let sugg_offset =
663663
self.get_lifetime_args_offset() + self.num_provided_type_or_const_args();
664664

665665
let (sugg_span, is_first) = if sugg_offset == 0 {
666-
(gen_args_span.shrink_to_lo(), true)
666+
(self.tcx.adjust_span(gen_args_span).shrink_to_lo(), true)
667667
} else {
668-
let arg_span = self.gen_args.args[sugg_offset - 1].span();
668+
let arg_span = self.tcx.adjust_span(self.gen_args.args[sugg_offset - 1].span());
669669
// If we came here then inferred lifetime's spans can only point
670670
// to either the opening bracket or to the space right after.
671671
// Both of these spans have an `hi` lower than or equal to the span
@@ -770,7 +770,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
770770
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
771771
let sugg = vec![
772772
(self.path_segment.ident.span, format!("{}::{}", snippet, self.path_segment.ident)),
773-
(span.with_lo(self.path_segment.ident.span.hi()), "".to_owned())
773+
(self.tcx.adjust_span(span).with_lo(self.path_segment.ident.span.hi()), "".to_owned())
774774
];
775775

776776
err.multipart_suggestion(
@@ -953,11 +953,8 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
953953
}
954954
} else if remove_entire_generics {
955955
let span = self
956-
.path_segment
957-
.args
958-
.unwrap()
959-
.span_ext()
960-
.unwrap()
956+
.tcx
957+
.adjust_span(self.path_segment.args.unwrap().span_ext().unwrap())
961958
.with_lo(self.path_segment.ident.span.hi());
962959

963960
let msg = format!(

0 commit comments

Comments
 (0)