Skip to content

Commit e5430e5

Browse files
committed
the two hardest things in programming, names and...
1 parent 0e84b61 commit e5430e5

File tree

2 files changed

+118
-82
lines changed

2 files changed

+118
-82
lines changed

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

Lines changed: 115 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ fn closure_return_type_suggestion(
178178
);
179179
err.span_label(
180180
span,
181-
InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr),
181+
InferCtxt::cannot_infer_msg("type", &name, &descr, parent_name, parent_descr),
182182
);
183183
}
184184

@@ -220,12 +220,23 @@ impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
220220
}
221221
}
222222

223+
/// Information about a constant or a type containing inference variables.
224+
pub struct InferDiagnosticsData {
225+
pub name: String,
226+
pub span: Option<Span>,
227+
pub description: Cow<'static, str>,
228+
pub parent_name: Option<String>,
229+
pub parent_description: Option<&'static str>,
230+
}
231+
223232
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
224-
pub fn extract_type_name(
233+
/// Extracts data used by diagnostic for either types or constants
234+
/// which were stuck during inference.
235+
pub fn extract_infer_data(
225236
&self,
226237
arg: GenericArg<'tcx>,
227238
highlight: Option<ty::print::RegionHighlightMode>,
228-
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
239+
) -> InferDiagnosticsData {
229240
match arg.unpack() {
230241
GenericArgKind::Type(ty) => {
231242
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
@@ -236,32 +247,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
236247
var_origin.kind
237248
{
238249
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
239-
let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id
240-
{
241-
let parent_name = self
242-
.tcx
243-
.def_key(parent_def_id)
244-
.disambiguated_data
245-
.data
246-
.get_opt_name()
247-
.map(|parent_symbol| parent_symbol.to_string());
248-
249-
(
250-
parent_name,
251-
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
252-
)
253-
} else {
254-
(None, None)
255-
};
250+
let (parent_name, parent_description) =
251+
if let Some(parent_def_id) = parent_def_id {
252+
let parent_name = self
253+
.tcx
254+
.def_key(parent_def_id)
255+
.disambiguated_data
256+
.data
257+
.get_opt_name()
258+
.map(|parent_symbol| parent_symbol.to_string());
259+
260+
(
261+
parent_name,
262+
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
263+
)
264+
} else {
265+
(None, None)
266+
};
256267

257268
if name != kw::SelfUpper {
258-
return (
259-
name.to_string(),
260-
Some(var_origin.span),
261-
"type parameter".into(),
269+
return InferDiagnosticsData {
270+
name: name.to_string(),
271+
span: Some(var_origin.span),
272+
description: "type parameter".into(),
262273
parent_name,
263-
parent_desc,
264-
);
274+
parent_description,
275+
};
265276
}
266277
}
267278
}
@@ -272,56 +283,67 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
272283
printer.region_highlight_mode = highlight;
273284
}
274285
let _ = ty.print(printer);
275-
(s, None, ty.prefix_string(), None, None)
286+
InferDiagnosticsData {
287+
name: s,
288+
span: None,
289+
description: ty.prefix_string(),
290+
parent_name: None,
291+
parent_description: None,
292+
}
276293
}
277294
GenericArgKind::Const(ct) => {
278-
let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
295+
if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
279296
let origin =
280297
self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
281298
if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
282299
origin.kind
283300
{
284301
let parent_def_id = self.tcx.parent(def_id);
285-
let (parent_name, parent_descr) = if let Some(parent_def_id) = parent_def_id
286-
{
287-
let parent_name = self
288-
.tcx
289-
.def_key(parent_def_id)
290-
.disambiguated_data
291-
.data
292-
.get_opt_name()
293-
.map(|parent_symbol| parent_symbol.to_string());
294-
295-
(
296-
parent_name,
297-
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
298-
)
299-
} else {
300-
(None, None)
301-
};
302-
303-
return (
304-
name.to_string(),
305-
Some(origin.span),
306-
"const parameter".into(),
302+
let (parent_name, parent_description) =
303+
if let Some(parent_def_id) = parent_def_id {
304+
let parent_name = self
305+
.tcx
306+
.def_key(parent_def_id)
307+
.disambiguated_data
308+
.data
309+
.get_opt_name()
310+
.map(|parent_symbol| parent_symbol.to_string());
311+
312+
(
313+
parent_name,
314+
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
315+
)
316+
} else {
317+
(None, None)
318+
};
319+
320+
return InferDiagnosticsData {
321+
name: name.to_string(),
322+
span: Some(origin.span),
323+
description: "const parameter".into(),
307324
parent_name,
308-
parent_descr,
309-
);
325+
parent_description,
326+
};
310327
}
311328

312329
debug_assert!(!origin.span.is_dummy());
313-
Some(origin.span)
330+
let mut s = String::new();
331+
let mut printer =
332+
ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
333+
if let Some(highlight) = highlight {
334+
printer.region_highlight_mode = highlight;
335+
}
336+
let _ = ct.print(printer);
337+
InferDiagnosticsData {
338+
name: s,
339+
span: Some(origin.span),
340+
description: "the constant".into(),
341+
parent_name: None,
342+
parent_description: None,
343+
}
314344
} else {
315345
bug!("unexpect const: {:?}", ct);
316-
};
317-
318-
let mut s = String::new();
319-
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
320-
if let Some(highlight) = highlight {
321-
printer.region_highlight_mode = highlight;
322346
}
323-
let _ = ct.print(printer);
324-
(s, span, "the constant".into(), None, None)
325347
}
326348
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
327349
}
@@ -331,18 +353,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
331353
&self,
332354
body_id: Option<hir::BodyId>,
333355
span: Span,
334-
ty: GenericArg<'tcx>,
356+
arg: GenericArg<'tcx>,
335357
error_code: TypeAnnotationNeeded,
336358
) -> DiagnosticBuilder<'tcx> {
337-
let ty = self.resolve_vars_if_possible(&ty);
338-
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(ty, None);
359+
let ty = self.resolve_vars_if_possible(&arg);
360+
let arg_data = self.extract_infer_data(arg, None);
339361
let kind_str = match ty.unpack() {
340362
GenericArgKind::Type(_) => "type",
341363
GenericArgKind::Const(_) => "the value",
342364
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
343365
};
344366

345-
let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into(), span);
367+
let mut local_visitor = FindHirNodeVisitor::new(&self, arg.into(), span);
346368
let ty_to_string = |ty: Ty<'tcx>| -> String {
347369
let mut s = String::new();
348370
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@@ -372,7 +394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
372394
}
373395
let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
374396
pattern.span
375-
} else if let Some(span) = name_sp {
397+
} else if let Some(span) = arg_data.span {
376398
// `span` here lets us point at `sum` instead of the entire right hand side expr:
377399
// error[E0282]: type annotations needed
378400
// --> file2.rs:3:15
@@ -419,7 +441,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
419441
_ => String::new(),
420442
};
421443

422-
// When `name` corresponds to a type argument, show the path of the full type we're
444+
// When `arg_data.name` corresponds to a type argument, show the path of the full type we're
423445
// trying to infer. In the following example, `ty_msg` contains
424446
// " in `std::result::Result<i32, E>`":
425447
// ```
@@ -458,11 +480,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
458480
&mut err,
459481
&decl.output,
460482
self.tcx.hir().body(body_id),
461-
&descr,
462-
&name,
483+
&arg_data.description,
484+
&arg_data.name,
463485
&ret,
464-
parent_name,
465-
parent_descr,
486+
arg_data.parent_name,
487+
arg_data.parent_description,
466488
);
467489
// We don't want to give the other suggestions when the problem is the
468490
// closure return type.
@@ -476,15 +498,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
476498
// nudge them in the right direction.
477499
format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
478500
}
479-
Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => {
501+
Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
480502
let ty = ty_to_string(ty);
481503
format!("the explicit type `{}`, with the type parameters specified", ty)
482504
}
483-
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => {
505+
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => {
484506
let ty = ty_to_string(ty);
485507
format!(
486508
"the explicit type `{}`, where the type parameter `{}` is specified",
487-
ty, name,
509+
ty, arg_data.name,
488510
)
489511
}
490512
_ => "a type".to_string(),
@@ -601,7 +623,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
601623
// | ^^^ cannot infer type for `S`
602624
// |
603625
// = note: type must be known at this point
604-
let span = name_sp.unwrap_or(err_span);
626+
let span = arg_data.span.unwrap_or(err_span);
605627
if !err
606628
.span
607629
.span_labels()
@@ -612,7 +634,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
612634
// Avoid multiple labels pointing at `span`.
613635
err.span_label(
614636
span,
615-
InferCtxt::missing_type_msg(kind_str, &name, &descr, parent_name, parent_descr),
637+
InferCtxt::cannot_infer_msg(
638+
kind_str,
639+
&arg_data.name,
640+
&arg_data.description,
641+
arg_data.parent_name,
642+
arg_data.parent_description,
643+
),
616644
);
617645
}
618646

@@ -672,7 +700,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
672700
ty: Ty<'tcx>,
673701
) -> DiagnosticBuilder<'tcx> {
674702
let ty = self.resolve_vars_if_possible(&ty);
675-
let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(ty.into(), None);
703+
let data = self.extract_infer_data(ty.into(), None);
676704

677705
let mut err = struct_span_err!(
678706
self.tcx.sess,
@@ -683,12 +711,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
683711
);
684712
err.span_label(
685713
span,
686-
InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr),
714+
InferCtxt::cannot_infer_msg(
715+
"type",
716+
&data.name,
717+
&data.description,
718+
data.parent_name,
719+
data.parent_description,
720+
),
687721
);
688722
err
689723
}
690724

691-
fn missing_type_msg(
725+
fn cannot_infer_msg(
692726
kind_str: &str,
693727
type_name: &str,
694728
descr: &str,
@@ -710,6 +744,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
710744
"".to_string()
711745
};
712746

747+
// FIXME: We really shouldn't be dealing with strings here
748+
// but instead use a sensible enum for cases like this.
713749
let preposition = if "the value" == kind_str { "of" } else { "for" };
714750
// For example: "cannot infer type for type parameter `T`"
715751
format!(

compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
396396
) -> Option<RegionNameHighlight> {
397397
let mut highlight = RegionHighlightMode::default();
398398
highlight.highlighting_region_vid(needle_fr, counter);
399-
let type_name = self.infcx.extract_type_name(ty.into(), Some(highlight)).0;
399+
let type_name = self.infcx.extract_infer_data(ty.into(), Some(highlight)).name;
400400

401401
debug!(
402402
"highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -646,7 +646,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
646646

647647
let mut highlight = RegionHighlightMode::default();
648648
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
649-
let type_name = self.infcx.extract_type_name(return_ty.into(), Some(highlight)).0;
649+
let type_name = self.infcx.extract_infer_data(return_ty.into(), Some(highlight)).name;
650650

651651
let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
652652

@@ -698,7 +698,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
698698

699699
let mut highlight = RegionHighlightMode::default();
700700
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
701-
let type_name = self.infcx.extract_type_name(yield_ty.into(), Some(highlight)).0;
701+
let type_name = self.infcx.extract_infer_data(yield_ty.into(), Some(highlight)).name;
702702

703703
let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
704704

0 commit comments

Comments
 (0)