Skip to content

Commit d2f8e39

Browse files
committed
Rework diagnostics for wrong number of generic args
1 parent 34628e5 commit d2f8e39

File tree

121 files changed

+2760
-739
lines changed

Some content is hidden

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

121 files changed

+2760
-739
lines changed

compiler/rustc_ast/src/ast.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,21 @@ impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
242242
/// A path like `Foo(A, B) -> C`.
243243
#[derive(Clone, Encodable, Decodable, Debug)]
244244
pub struct ParenthesizedArgs {
245-
/// Overall span
245+
/// ```text
246+
/// Foo(A, B) -> C
247+
/// ^^^^^^^^^^^^^^
248+
/// ```
246249
pub span: Span,
247250

248251
/// `(A, B)`
249252
pub inputs: Vec<P<Ty>>,
250253

254+
/// ```text
255+
/// Foo(A, B) -> C
256+
/// ^^^^^^
257+
/// ```
258+
pub inputs_span: Span,
259+
251260
/// `C`
252261
pub output: FnRetTy,
253262
}

compiler/rustc_ast/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![feature(const_fn_transmute)]
1414
#![feature(const_panic)]
1515
#![feature(crate_visibility_modifier)]
16+
#![feature(iterator_fold_self)]
1617
#![feature(label_break_value)]
1718
#![feature(nll)]
1819
#![feature(or_patterns)]

compiler/rustc_ast/src/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
565565
args: &mut ParenthesizedArgs,
566566
vis: &mut T,
567567
) {
568-
let ParenthesizedArgs { inputs, output, span } = args;
568+
let ParenthesizedArgs { inputs, output, span, .. } = args;
569569
visit_vec(inputs, |input| vis.visit_ty(input));
570570
noop_visit_fn_ret_ty(output, vis);
571571
vis.visit_span(span);

compiler/rustc_ast_lowering/src/path.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
401401
// compatibility, even in contexts like an impl header where
402402
// we generally don't permit such things (see #51008).
403403
self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
404-
let &ParenthesizedArgs { ref inputs, ref output, span } = data;
404+
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
405405
let inputs = this.arena.alloc_from_iter(
406406
inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
407407
);
408408
let output_ty = match output {
409409
FnRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
410-
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
410+
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
411411
};
412-
let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
412+
let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
413413
let binding = this.output_ty_binding(output_ty.span, output_ty);
414414
(
415415
GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },

compiler/rustc_hir/src/hir.rs

+44-11
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ pub use rustc_ast::{CaptureBy, Movability, Mutability};
1111
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1212
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
1313
use rustc_macros::HashStable_Generic;
14-
use rustc_span::def_id::LocalDefId;
15-
use rustc_span::source_map::Spanned;
14+
use rustc_span::source_map::{SourceMap, Spanned};
1615
use rustc_span::symbol::{kw, sym, Ident, Symbol};
16+
use rustc_span::{def_id::LocalDefId, BytePos};
1717
use rustc_span::{MultiSpan, Span, DUMMY_SP};
1818
use rustc_target::asm::InlineAsmRegOrRegClass;
1919
use rustc_target::spec::abi::Abi;
@@ -231,7 +231,11 @@ impl<'hir> PathSegment<'hir> {
231231
PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
232232
}
233233

234-
pub fn generic_args(&self) -> &GenericArgs<'hir> {
234+
pub fn invalid() -> Self {
235+
Self::from_ident(Ident::invalid())
236+
}
237+
238+
pub fn args(&self) -> &GenericArgs<'hir> {
235239
if let Some(ref args) = self.args {
236240
args
237241
} else {
@@ -275,19 +279,15 @@ impl GenericArg<'_> {
275279
matches!(self, GenericArg::Const(_))
276280
}
277281

278-
pub fn descr(&self) -> &'static str {
279-
match self {
280-
GenericArg::Lifetime(_) => "lifetime",
281-
GenericArg::Type(_) => "type",
282-
GenericArg::Const(_) => "constant",
283-
}
282+
pub fn is_synthetic(&self) -> bool {
283+
matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::invalid())
284284
}
285285

286-
pub fn short_descr(&self) -> &'static str {
286+
pub fn descr(&self) -> &'static str {
287287
match self {
288288
GenericArg::Lifetime(_) => "lifetime",
289289
GenericArg::Type(_) => "type",
290-
GenericArg::Const(_) => "const",
290+
GenericArg::Const(_) => "constant",
291291
}
292292
}
293293

@@ -352,6 +352,39 @@ impl GenericArgs<'_> {
352352

353353
own_counts
354354
}
355+
356+
pub fn span(&self) -> Option<Span> {
357+
self.args
358+
.iter()
359+
.filter(|arg| !arg.is_synthetic())
360+
.map(|arg| arg.span())
361+
.fold_first(|span1, span2| span1.to(span2))
362+
}
363+
364+
/// Returns span encompassing arguments and their surrounding `<>` or `()`
365+
pub fn span_ext(&self, sm: &SourceMap) -> Option<Span> {
366+
let mut span = self.span()?;
367+
368+
let (o, c) = if self.parenthesized { ('(', ')') } else { ('<', '>') };
369+
370+
if let Ok(snippet) = sm.span_to_snippet(span) {
371+
let snippet = snippet.as_bytes();
372+
373+
if snippet[0] != (o as u8) || snippet[snippet.len() - 1] != (c as u8) {
374+
span = sm.span_extend_to_prev_char(span, o, true);
375+
span = span.with_lo(span.lo() - BytePos(1));
376+
377+
span = sm.span_extend_to_next_char(span, c, true);
378+
span = span.with_hi(span.hi() + BytePos(1));
379+
}
380+
}
381+
382+
Some(span)
383+
}
384+
385+
pub fn is_empty(&self) -> bool {
386+
self.args.is_empty()
387+
}
355388
}
356389

357390
/// A modifier on a bound, currently this is only used for `?Sized`, where the

compiler/rustc_hir/src/lang_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ where
157157
}
158158

159159
language_item_table! {
160-
// Variant name, Name, Method name, Target;
160+
// Variant name, Name, Method name, Target;
161161
Bool, sym::bool, bool_impl, Target::Impl;
162162
Char, sym::char, char_impl, Target::Impl;
163163
Str, sym::str, str_impl, Target::Impl;

compiler/rustc_hir/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#![feature(const_fn)] // For the unsizing cast on `&[]`
88
#![feature(const_panic)]
99
#![feature(in_band_lifetimes)]
10+
#![feature(iterator_fold_self)]
1011
#![feature(once_cell)]
1112
#![feature(or_patterns)]
1213
#![recursion_limit = "256"]

compiler/rustc_hir_pretty/src/lib.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ impl<'a> State<'a> {
12131213
self.s.word(".");
12141214
self.print_ident(segment.ident);
12151215

1216-
let generic_args = segment.generic_args();
1216+
let generic_args = segment.args();
12171217
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
12181218
self.print_generic_args(generic_args, segment.infer_args, true);
12191219
}
@@ -1661,19 +1661,15 @@ impl<'a> State<'a> {
16611661
}
16621662
if segment.ident.name != kw::PathRoot {
16631663
self.print_ident(segment.ident);
1664-
self.print_generic_args(
1665-
segment.generic_args(),
1666-
segment.infer_args,
1667-
colons_before_params,
1668-
);
1664+
self.print_generic_args(segment.args(), segment.infer_args, colons_before_params);
16691665
}
16701666
}
16711667
}
16721668

16731669
pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
16741670
if segment.ident.name != kw::PathRoot {
16751671
self.print_ident(segment.ident);
1676-
self.print_generic_args(segment.generic_args(), segment.infer_args, false);
1672+
self.print_generic_args(segment.args(), segment.infer_args, false);
16771673
}
16781674
}
16791675

@@ -1693,7 +1689,7 @@ impl<'a> State<'a> {
16931689
if segment.ident.name != kw::PathRoot {
16941690
self.print_ident(segment.ident);
16951691
self.print_generic_args(
1696-
segment.generic_args(),
1692+
segment.args(),
16971693
segment.infer_args,
16981694
colons_before_params,
16991695
);
@@ -1705,7 +1701,7 @@ impl<'a> State<'a> {
17051701
let item_segment = path.segments.last().unwrap();
17061702
self.print_ident(item_segment.ident);
17071703
self.print_generic_args(
1708-
item_segment.generic_args(),
1704+
item_segment.args(),
17091705
item_segment.infer_args,
17101706
colons_before_params,
17111707
)
@@ -1725,7 +1721,7 @@ impl<'a> State<'a> {
17251721
self.s.word("::");
17261722
self.print_ident(item_segment.ident);
17271723
self.print_generic_args(
1728-
item_segment.generic_args(),
1724+
item_segment.args(),
17291725
item_segment.infer_args,
17301726
colons_before_params,
17311727
)

compiler/rustc_metadata/src/rmeta/decoder.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -721,21 +721,25 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
721721
&self.raw_proc_macros.unwrap()[pos]
722722
}
723723

724-
fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
724+
fn try_item_ident(&self, item_index: DefIndex, sess: &Session) -> Result<Ident, String> {
725725
let name = self
726726
.def_key(item_index)
727727
.disambiguated_data
728728
.data
729729
.get_opt_name()
730-
.expect("no name in item_ident");
730+
.ok_or_else(|| format!("Missing opt name for {:?}", item_index))?;
731731
let span = self
732732
.root
733733
.tables
734734
.ident_span
735735
.get(self, item_index)
736-
.map(|data| data.decode((self, sess)))
737-
.unwrap_or_else(|| panic!("Missing ident span for {:?} ({:?})", name, item_index));
738-
Ident::new(name, span)
736+
.ok_or_else(|| format!("Missing ident span for {:?} ({:?})", name, item_index))?
737+
.decode((self, sess));
738+
Ok(Ident::new(name, span))
739+
}
740+
741+
fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident {
742+
self.try_item_ident(item_index, sess).unwrap()
739743
}
740744

741745
fn def_kind(&self, index: DefIndex) -> DefKind {

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+3
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ provide! { <'tcx> tcx, def_id, other, cdata,
128128
generator_kind => { cdata.generator_kind(def_id.index) }
129129
def_kind => { cdata.def_kind(def_id.index) }
130130
def_span => { cdata.get_span(def_id.index, &tcx.sess) }
131+
def_ident_span => {
132+
cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span)
133+
}
131134
lookup_stability => {
132135
cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s))
133136
}

compiler/rustc_middle/src/query/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,7 @@ rustc_queries! {
873873
query def_kind(def_id: DefId) -> DefKind {
874874
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
875875
}
876+
876877
query def_span(def_id: DefId) -> Span {
877878
desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
878879
// FIXME(mw): DefSpans are not really inputs since they are derived from
@@ -882,15 +883,23 @@ rustc_queries! {
882883
// regardless of HIR hashing.
883884
eval_always
884885
}
886+
887+
query def_ident_span(def_id: DefId) -> Option<Span> {
888+
desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
889+
}
890+
885891
query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> {
886892
desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) }
887893
}
894+
888895
query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> {
889896
desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
890897
}
898+
891899
query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
892900
desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
893901
}
902+
894903
query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] {
895904
desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
896905
}

compiler/rustc_middle/src/ty/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ fn foo(&self) -> Self::T { String::new() }
846846
}
847847

848848
/// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
849-
/// requirement, provide a strucuted suggestion to constrain it to a given type `ty`.
849+
/// requirement, provide a structured suggestion to constrain it to a given type `ty`.
850850
fn constrain_generic_bound_associated_type_structured_suggestion(
851851
self,
852852
db: &mut DiagnosticBuilder<'_>,

compiler/rustc_middle/src/ty/mod.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -871,19 +871,37 @@ impl<'tcx> Generics {
871871
// We could cache this as a property of `GenericParamCount`, but
872872
// the aim is to refactor this away entirely eventually and the
873873
// presence of this method will be a constant reminder.
874-
let mut own_counts: GenericParamCount = Default::default();
874+
let mut own_counts = GenericParamCount::default();
875875

876876
for param in &self.params {
877877
match param.kind {
878878
GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
879879
GenericParamDefKind::Type { .. } => own_counts.types += 1,
880880
GenericParamDefKind::Const => own_counts.consts += 1,
881-
};
881+
}
882882
}
883883

884884
own_counts
885885
}
886886

887+
pub fn own_defaults(&self) -> GenericParamCount {
888+
let mut own_defaults = GenericParamCount::default();
889+
890+
for param in &self.params {
891+
match param.kind {
892+
GenericParamDefKind::Lifetime => (),
893+
GenericParamDefKind::Type { has_default, .. } => {
894+
own_defaults.types += has_default as usize;
895+
}
896+
GenericParamDefKind::Const => {
897+
// FIXME(const_generics:defaults)
898+
}
899+
}
900+
}
901+
902+
own_defaults
903+
}
904+
887905
pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool {
888906
if self.own_requires_monomorphization() {
889907
return true;

compiler/rustc_parse/src/parser/path.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,11 @@ impl<'a> Parser<'a> {
230230
} else {
231231
// `(T, U) -> R`
232232
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
233+
let inputs_span = lo.to(self.prev_token.span);
233234
let span = ident.span.to(self.prev_token.span);
234235
let output =
235236
self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
236-
ParenthesizedArgs { inputs, output, span }.into()
237+
ParenthesizedArgs { span, inputs, inputs_span, output }.into()
237238
};
238239

239240
PathSegment { ident, args, id: ast::DUMMY_NODE_ID }

compiler/rustc_resolve/src/late/lifetimes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14331433
hir::TyKind::Path(ref qpath) => {
14341434
if let QPath::Resolved(_, path) = qpath {
14351435
let last_segment = &path.segments[path.segments.len() - 1];
1436-
let generics = last_segment.generic_args();
1436+
let generics = last_segment.args();
14371437
for arg in generics.args.iter() {
14381438
if let GenericArg::Lifetime(lt) = arg {
14391439
if lt.name.ident() == name {

0 commit comments

Comments
 (0)