1
Fork 0

merge need_type_info_err(_const)

This commit is contained in:
Bastian Kauschke 2020-09-23 09:24:58 +02:00
parent e0bc267512
commit 45d92b43e3
13 changed files with 148 additions and 131 deletions

View file

@ -176,7 +176,10 @@ fn closure_return_type_suggestion(
suggestion,
Applicability::HasPlaceholders,
);
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr));
err.span_label(
span,
InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr),
);
}
/// Given a closure signature, return a `String` containing a list of all its argument types.
@ -220,60 +223,119 @@ impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn extract_type_name(
&self,
ty: Ty<'tcx>,
arg: GenericArg<'tcx>,
highlight: Option<ty::print::RegionHighlightMode>,
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
let mut inner = self.inner.borrow_mut();
let ty_vars = &inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id {
let parent_name = self
.tcx
.def_key(parent_def_id)
.disambiguated_data
.data
.get_opt_name()
.map(|parent_symbol| parent_symbol.to_string());
match arg.unpack() {
GenericArgKind::Type(ty) => {
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
let mut inner = self.inner.borrow_mut();
let ty_vars = &inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
var_origin.kind
{
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id
{
let parent_name = self
.tcx
.def_key(parent_def_id)
.disambiguated_data
.data
.get_opt_name()
.map(|parent_symbol| parent_symbol.to_string());
(parent_name, Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)))
} else {
(None, None)
};
(
parent_name,
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
)
} else {
(None, None)
};
if name != kw::SelfUpper {
return (
name.to_string(),
Some(var_origin.span),
"type parameter".into(),
parent_name,
parent_desc,
);
if name != kw::SelfUpper {
return (
name.to_string(),
Some(var_origin.span),
"type parameter".into(),
parent_name,
parent_desc,
);
}
}
}
}
}
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ty.print(printer);
(s, None, ty.prefix_string(), None, None)
}
GenericArgKind::Const(ct) => {
if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
let origin =
self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
origin.kind
{
let parent_def_id = self.tcx.parent(def_id);
let (parent_name, parent_descr) = if let Some(parent_def_id) = parent_def_id
{
let parent_name = self
.tcx
.def_key(parent_def_id)
.disambiguated_data
.data
.get_opt_name()
.map(|parent_symbol| parent_symbol.to_string());
(
parent_name,
Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
)
} else {
(None, None)
};
return (
name.to_string(),
Some(origin.span),
"const parameter".into(),
parent_name,
parent_descr,
);
}
}
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ct.print(printer);
(s, None, "<TODO>".into(), None, None)
}
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
}
let _ = ty.print(printer);
(s, None, ty.prefix_string(), None, None)
}
// FIXME(eddyb) generalize all of this to handle `ty::Const` inference variables as well.
pub fn need_type_info_err(
&self,
body_id: Option<hir::BodyId>,
span: Span,
ty: Ty<'tcx>,
ty: GenericArg<'tcx>,
error_code: TypeAnnotationNeeded,
) -> DiagnosticBuilder<'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(ty, None);
let kind_str = match ty.unpack() {
GenericArgKind::Type(_) => "type",
GenericArgKind::Const(_) => "the value",
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
};
let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into(), span);
let ty_to_string = |ty: Ty<'tcx>| -> String {
@ -545,55 +607,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// Avoid multiple labels pointing at `span`.
err.span_label(
span,
InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr),
InferCtxt::missing_type_msg(kind_str, &name, &descr, parent_name, parent_descr),
);
}
err
}
// FIXME(const_generics): We should either try and merge this with `need_type_info_err`
// or improve the errors created here.
//
// Unlike for type inference variables, we don't yet store the origin of const inference variables.
// This is needed for to get a more relevant error span.
pub fn need_type_info_err_const(
&self,
body_id: Option<hir::BodyId>,
span: Span,
ct: &'tcx ty::Const<'tcx>,
error_code: TypeAnnotationNeeded,
) -> DiagnosticBuilder<'tcx> {
let mut local_visitor = FindHirNodeVisitor::new(&self, ct.into(), span);
if let Some(body_id) = body_id {
let expr = self.tcx.hir().expect_expr(body_id.hir_id);
local_visitor.visit_expr(expr);
}
let mut param_name = None;
let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind {
param_name = Some(param);
}
origin.span
} else {
local_visitor.target_span
};
let error_code = error_code.into();
let mut err =
self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
if let Some(param_name) = param_name {
err.note(&format!("cannot infer the value of the const parameter `{}`", param_name));
} else {
err.note("unable to infer the value of a const parameter");
}
err
}
/// If the `FnSig` for the method call can be found and type arguments are identified as
/// needed, suggest annotating the call, otherwise point out the resulting type of the call.
fn annotate_method_call(
@ -647,7 +667,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
) -> DiagnosticBuilder<'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(ty.into(), None);
let mut err = struct_span_err!(
self.tcx.sess,
@ -656,18 +676,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"type inside {} must be known in this context",
kind,
);
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr));
err.span_label(
span,
InferCtxt::missing_type_msg("type", &name, &descr, parent_name, parent_descr),
);
err
}
fn missing_type_msg(
kind_str: &str,
type_name: &str,
descr: &str,
parent_name: Option<String>,
parent_descr: Option<&str>,
) -> Cow<'static, str> {
) -> String {
if type_name == "_" {
"cannot infer type".into()
format!("cannot infer {}", kind_str)
} else {
let parent_desc = if let Some(parent_name) = parent_name {
let parent_type_descr = if let Some(parent_descr) = parent_descr {
@ -681,7 +705,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"".to_string()
};
format!("cannot infer type for {} `{}`{}", descr, type_name, parent_desc).into()
let preposition = if "value" == kind_str { "of" } else { "for" };
// For example: "cannot infer type for type parameter `T`"
format!(
"cannot infer {} {} {} `{}`{}",
kind_str, preposition, descr, type_name, parent_desc
)
.into()
}
}
}

View file

@ -1163,7 +1163,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
GenericParamDefKind::Const { .. } => {
let origin = ConstVariableOrigin {
kind: ConstVariableOriginKind::ConstParameterDefinition(param.name),
kind: ConstVariableOriginKind::ConstParameterDefinition(
param.name,
param.def_id,
),
span,
};
let const_var_id =