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.
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());
-
- (parent_name, Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)))
- } else {
- (None, None)
- };
+ 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)
+ };
+
+ 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 _ = 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 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 {
// 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(
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,
"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 {
"".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()
}
}
}
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFolder;
-use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{
self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
TypeFoldable, WithConstness,
// check upstream for type errors and don't add the obligations to
// begin with in those cases.
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
- self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+ self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0282).emit();
return;
}
- let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+ let mut err =
+ self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0283);
err.note(&format!("cannot satisfy `{}`", predicate));
if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
return;
}
- match arg.unpack() {
- GenericArgKind::Lifetime(lt) => {
- span_bug!(span, "unexpected well formed predicate: {:?}", lt)
- }
- GenericArgKind::Type(ty) => {
- self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
- }
- GenericArgKind::Const(ct) => {
- self.need_type_info_err_const(body_id, span, ct, ErrorCode::E0282)
- }
- }
+ self.need_type_info_err(body_id, span, arg, ErrorCode::E0282)
}
ty::PredicateAtom::Subtype(data) => {
let SubtypePredicate { a_is_expected: _, a, b } = data;
// both must be type variables, or the other would've been instantiated
assert!(a.is_ty_var() && b.is_ty_var());
- self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+ self.need_type_info_err(body_id, span, a.into(), ErrorCode::E0282)
}
ty::PredicateAtom::Projection(data) => {
let trait_ref = ty::Binder::bind(data).to_poly_trait_ref(self.tcx);
}
if self_ty.needs_infer() && ty.needs_infer() {
// We do this for the `foo.collect()?` case to produce a suggestion.
- let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+ let mut err =
+ self.need_type_info_err(body_id, span, self_ty.into(), ErrorCode::E0284);
err.note(&format!("cannot satisfy `{}`", predicate));
err
} else {