1
Fork 0

Refer to const params as "const params" and not "type params"

This commit is contained in:
Esteban Kuber 2021-11-08 21:10:00 +00:00
parent 3fd15c8404
commit 6a691b1d92
3 changed files with 48 additions and 38 deletions

View file

@ -10,7 +10,7 @@ use rustc_middle::hir::map::Map;
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
use rustc_middle::ty::print::Print;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder};
use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::symbol::kw;
use rustc_span::Span;
use std::borrow::Cow;
@ -305,6 +305,15 @@ pub enum UnderspecifiedArgKind {
Const { is_parameter: bool },
}
impl UnderspecifiedArgKind {
fn descr(&self) -> &'static str {
match self {
Self::Type { .. } => "type",
Self::Const { .. } => "const",
}
}
}
impl InferenceDiagnosticsData {
/// Generate a label for a generic argument which can't be inferred. When not
/// much is known about the argument, `use_diag` may be used to describe the
@ -587,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
let param_type = arg_data.kind.descr();
let suffix = match local_visitor.found_node_ty {
Some(ty) if ty.is_closure() => {
let substs =
@ -625,15 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
let ty = ty_to_string(ty);
format!("the explicit type `{}`, with the type parameters specified", ty)
format!("the explicit type `{}`, with the {} parameters specified", ty, param_type)
}
Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => {
let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty);
let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty);
let ty = ty_to_string(ty);
format!(
"the explicit type `{}`, where the type parameter `{}` is specified",
ty, arg_data.name,
"the explicit type `{}`, where the {} parameter `{}` is specified",
ty, param_type, arg_data.name,
)
}
_ => "a type".to_string(),
@ -910,7 +920,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
/// Turn resolved type params into `[type error]` to signal we don't want to display them.
/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After
/// performing that replacement, we'll turn all remaining infer type params to use their name from
/// their definition, and replace all the `[type error]`s back to being infer so they display in
/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params
/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could
/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations.
struct ResolvedTypeParamEraser<'tcx> {
tcx: TyCtxt<'tcx>,
level: usize,
@ -920,7 +935,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> Self {
ResolvedTypeParamEraser { tcx, level: 0 }
}
/// Replace not yet inferred const params with their def name.
fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> {
match c.val {
ty::ConstKind::Infer(..) => {
self.tcx().mk_const_param(index, name, c.ty)
}
_ => c,
}
}
}
impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
@ -940,29 +966,22 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
.map(|(subst, param)| match &(subst.unpack(), &param.kind) {
(_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst,
(crate::infer::GenericArgKind::Const(c), _) => {
match c.val {
ty::ConstKind::Infer(..) => {
// Replace not yet inferred const params with their def name.
self.tcx().mk_const_param(param.index, param.name, c.ty).into()
}
_ => subst,
}
self.replace_infers(c, param.index, param.name).into()
}
_ => subst.super_fold_with(self),
})
.collect();
if self.level == 1
|| substs.iter().any(|subst| match subst.unpack() {
ty::subst::GenericArgKind::Type(t) => match t.kind() {
ty::Error(_) => false,
_ => true,
},
// Account for `const` params here, otherwise `doesnt_infer.rs`
// shows `_` instead of `Foo<{ _: u32 }>`
ty::subst::GenericArgKind::Const(_) => true,
_ => false,
})
{
let should_keep = |subst: &GenericArg<'_>| match subst.unpack() {
ty::subst::GenericArgKind::Type(t) => match t.kind() {
ty::Error(_) => false,
_ => true,
},
// Account for `const` params here, otherwise `doesnt_infer.rs`
// shows `_` instead of `Foo<{ _: u32 }>`
ty::subst::GenericArgKind::Const(_) => true,
_ => false,
};
if self.level == 1 || substs.iter().any(should_keep) {
let substs = self.tcx().intern_substs(&substs[..]);
self.tcx().mk_ty(ty::Adt(def, substs))
} else {
@ -986,18 +1005,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
| ty::Opaque(..)
| ty::Projection(_)
| ty::Never => t.super_fold_with(self),
ty::Array(ty, c) => {
self.tcx().mk_ty(ty::Array(
self.fold_ty(ty),
match c.val {
ty::ConstKind::Infer(..) => {
// Replace not yet inferred const params with their def name.
self.tcx().mk_const_param(0, Symbol::intern("N"), c.ty).into()
}
_ => c,
},
))
}
ty::Array(ty, c) => self
.tcx()
.mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))),
// We don't want to hide type params that haven't been resolved yet.
// This would be the type that will be written out with the type param
// name in the output.