Refer to const params as "const params" and not "type params"
This commit is contained in:
parent
3fd15c8404
commit
6a691b1d92
3 changed files with 48 additions and 38 deletions
|
@ -10,7 +10,7 @@ use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
|
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
|
||||||
use rustc_middle::ty::print::Print;
|
use rustc_middle::ty::print::Print;
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
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::symbol::kw;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -305,6 +305,15 @@ pub enum UnderspecifiedArgKind {
|
||||||
Const { is_parameter: bool },
|
Const { is_parameter: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UnderspecifiedArgKind {
|
||||||
|
fn descr(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Type { .. } => "type",
|
||||||
|
Self::Const { .. } => "const",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl InferenceDiagnosticsData {
|
impl InferenceDiagnosticsData {
|
||||||
/// Generate a label for a generic argument which can't be inferred. When not
|
/// 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
|
/// 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 {
|
let suffix = match local_visitor.found_node_ty {
|
||||||
Some(ty) if ty.is_closure() => {
|
Some(ty) if ty.is_closure() => {
|
||||||
let substs =
|
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 == "_" => {
|
Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
|
||||||
let ty = ty_to_string(ty);
|
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 => {
|
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 = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty);
|
||||||
let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty);
|
let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty);
|
||||||
let ty = ty_to_string(ty);
|
let ty = ty_to_string(ty);
|
||||||
format!(
|
format!(
|
||||||
"the explicit type `{}`, where the type parameter `{}` is specified",
|
"the explicit type `{}`, where the {} parameter `{}` is specified",
|
||||||
ty, arg_data.name,
|
ty, param_type, arg_data.name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => "a type".to_string(),
|
_ => "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> {
|
struct ResolvedTypeParamEraser<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
level: usize,
|
level: usize,
|
||||||
|
@ -920,7 +935,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> {
|
||||||
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||||
ResolvedTypeParamEraser { tcx, level: 0 }
|
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> {
|
impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
|
@ -940,19 +966,12 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
|
||||||
.map(|(subst, param)| match &(subst.unpack(), ¶m.kind) {
|
.map(|(subst, param)| match &(subst.unpack(), ¶m.kind) {
|
||||||
(_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst,
|
(_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst,
|
||||||
(crate::infer::GenericArgKind::Const(c), _) => {
|
(crate::infer::GenericArgKind::Const(c), _) => {
|
||||||
match c.val {
|
self.replace_infers(c, param.index, param.name).into()
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => subst.super_fold_with(self),
|
_ => subst.super_fold_with(self),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if self.level == 1
|
let should_keep = |subst: &GenericArg<'_>| match subst.unpack() {
|
||||||
|| substs.iter().any(|subst| match subst.unpack() {
|
|
||||||
ty::subst::GenericArgKind::Type(t) => match t.kind() {
|
ty::subst::GenericArgKind::Type(t) => match t.kind() {
|
||||||
ty::Error(_) => false,
|
ty::Error(_) => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
|
@ -961,8 +980,8 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
|
||||||
// shows `_` instead of `Foo<{ _: u32 }>`
|
// shows `_` instead of `Foo<{ _: u32 }>`
|
||||||
ty::subst::GenericArgKind::Const(_) => true,
|
ty::subst::GenericArgKind::Const(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
};
|
||||||
{
|
if self.level == 1 || substs.iter().any(should_keep) {
|
||||||
let substs = self.tcx().intern_substs(&substs[..]);
|
let substs = self.tcx().intern_substs(&substs[..]);
|
||||||
self.tcx().mk_ty(ty::Adt(def, substs))
|
self.tcx().mk_ty(ty::Adt(def, substs))
|
||||||
} else {
|
} else {
|
||||||
|
@ -986,18 +1005,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
|
||||||
| ty::Opaque(..)
|
| ty::Opaque(..)
|
||||||
| ty::Projection(_)
|
| ty::Projection(_)
|
||||||
| ty::Never => t.super_fold_with(self),
|
| ty::Never => t.super_fold_with(self),
|
||||||
ty::Array(ty, c) => {
|
ty::Array(ty, c) => self
|
||||||
self.tcx().mk_ty(ty::Array(
|
.tcx()
|
||||||
self.fold_ty(ty),
|
.mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))),
|
||||||
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,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
// We don't want to hide type params that haven't been resolved yet.
|
// 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
|
// This would be the type that will be written out with the type param
|
||||||
// name in the output.
|
// name in the output.
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>`
|
||||||
LL | let foo = Foo::foo();
|
LL | let foo = Foo::foo();
|
||||||
| --- ^^^^^^^^ cannot infer the value of const parameter `N`
|
| --- ^^^^^^^^ cannot infer the value of const parameter `N`
|
||||||
| |
|
| |
|
||||||
| consider giving `foo` the explicit type `Foo<N>`, where the type parameter `N` is specified
|
| consider giving `foo` the explicit type `Foo<N>`, where the const parameter `N` is specified
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]`
|
||||||
LL | let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`!
|
LL | let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`!
|
||||||
| - ^^^ cannot infer the value of const parameter `N` declared on the function `foo`
|
| - ^^^ cannot infer the value of const parameter `N` declared on the function `foo`
|
||||||
| |
|
| |
|
||||||
| consider giving this pattern the explicit type `[_; N]`, where the type parameter `N` is specified
|
| consider giving this pattern the explicit type `[_; N]`, where the const parameter `N` is specified
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue