From 78e88f46d60c5487946fc7632a7561bdff6b9fcc Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 8 Nov 2021 19:15:54 +0000 Subject: [PATCH 1/4] Only shown relevant type params in E0283 label When we point at a binding to suggest giving it a type, erase all the type for ADTs that have been resolved, leaving only the ones that could not be inferred. For small shallow types this is not a problem, but for big nested types with lots of params, this can otherwise cause a lot of unnecessary visual output. --- .../infer/error_reporting/need_type_info.rs | 100 +++++++++++++++++- .../defaults/doesnt_infer.stderr | 2 +- .../inference/erase-type-params-in-label.rs | 13 +++ .../erase-type-params-in-label.stderr | 22 ++++ src/test/ui/inference/issue-83606.stderr | 2 +- 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/inference/erase-type-params-in-label.rs create mode 100644 src/test/ui/inference/erase-type-params-in-label.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 32c02033dc9b9..6b9952ba5d684 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -11,7 +11,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}; +use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -629,6 +629,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!("the explicit type `{}`, with the type parameters specified", ty) } 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", @@ -908,3 +910,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } } + +/// Turn resolved type params into `[type error]` to signal we don't want to display them. +struct ResolvedTypeParamEraser<'tcx> { + tcx: TyCtxt<'tcx>, + level: usize, +} + +impl<'tcx> ResolvedTypeParamEraser<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + ResolvedTypeParamEraser { tcx, level: 0 } + } +} +impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + self.level += 1; + let t = match t.kind() { + // We'll hide this type only if all its type params are hidden as well. + ty::Adt(def, substs) => { + let generics = self.tcx().generics_of(def.did); + // Account for params with default values, like `Vec`, where we + // want to show `Vec`, not `Vec`. If we replaced that + // subst, then we'd get the incorrect output, so we passthrough. + let substs: Vec<_> = substs + .iter() + .zip(generics.params.iter()) + .map(|(subst, param)| match ¶m.kind { + ty::GenericParamDefKind::Type { has_default: true, .. } => subst, + _ => 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 substs = self.tcx().intern_substs(&substs[..]); + self.tcx().mk_ty(ty::Adt(def, substs)) + } else { + self.tcx().ty_error() + } + } + ty::Ref(_, ty, _) => { + let ty = self.fold_ty(ty); + match ty.kind() { + // Avoid `&_`, these can be safely presented as `_`. + ty::Error(_) => self.tcx().ty_error(), + _ => t.super_fold_with(self), + } + } + // We could account for `()` if we wanted to replace it, but it's assured to be short. + ty::Tuple(_) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Opaque(..) + | ty::Projection(_) + | ty::Never + | ty::Array(..) => t.super_fold_with(self), + // 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. + ty::Infer(_) => t, + // We don't want to hide the outermost type, only its type params. + _ if self.level == 1 => t.super_fold_with(self), + // Hide this type + _ => self.tcx().ty_error(), + }; + self.level -= 1; + t + } +} + +/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`. +struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>); +impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.0 + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.kind() { + ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), + _ => t.super_fold_with(self), + } + } +} diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index b57975e26f290..183be1b1517a7 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo<{_: u32}>`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo<{_: _}>`, where the type parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/erase-type-params-in-label.rs b/src/test/ui/inference/erase-type-params-in-label.rs new file mode 100644 index 0000000000000..4a163d0b81094 --- /dev/null +++ b/src/test/ui/inference/erase-type-params-in-label.rs @@ -0,0 +1,13 @@ +fn main() { + let foo = new(1, ""); //~ ERROR E0283 +} + +struct Bar { + t: T, + k: K, + n: N, +} + +fn new(t: T, k: K) -> Bar { + Bar { t, k, n: Default::default() } +} diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr new file mode 100644 index 0000000000000..b665fade9d88f --- /dev/null +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed for `Bar` + --> $DIR/erase-type-params-in-label.rs:2:15 + | +LL | let foo = new(1, ""); + | --- ^^^ cannot infer type for type parameter `Z` declared on the function `new` + | | + | consider giving `foo` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified + | + = note: cannot satisfy `_: Default` +note: required by a bound in `new` + --> $DIR/erase-type-params-in-label.rs:11:17 + | +LL | fn new(t: T, k: K) -> Bar { + | ^^^^^^^ required by this bound in `new` +help: consider specifying the type arguments in the function call + | +LL | let foo = new::(1, ""); + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index 65f3336b9358a..c66606b9c8304 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` | | - | consider giving this pattern the explicit type `[usize; _]`, where the type parameter `N` is specified + | consider giving this pattern the explicit type `[_; _]`, where the type parameter `N` is specified error: aborting due to previous error From 3fd15c8404626c6622555e66299c9f3442bf2322 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 8 Nov 2021 20:32:17 +0000 Subject: [PATCH 2/4] Refer to uninferred `const` params by their name, instead of `{ _: _ }` When the value of a const param isn't inferred, replace it with the param name from the definition. --- .../infer/error_reporting/need_type_info.rs | 31 +++++++++++++++---- .../defaults/doesnt_infer.stderr | 2 +- src/test/ui/inference/issue-83606.stderr | 2 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 6b9952ba5d684..56f0b5c192786 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1,6 +1,5 @@ use crate::infer::type_variable::TypeVariableOriginKind; -use crate::infer::InferCtxt; -use crate::rustc_middle::ty::TypeFoldable; +use crate::infer::{InferCtxt, Symbol}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; @@ -938,8 +937,17 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { let substs: Vec<_> = substs .iter() .zip(generics.params.iter()) - .map(|(subst, param)| match ¶m.kind { - ty::GenericParamDefKind::Type { has_default: true, .. } => subst, + .map(|(subst, param)| match &(subst.unpack(), ¶m.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, + } + } _ => subst.super_fold_with(self), }) .collect(); @@ -977,8 +985,19 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { | ty::FnPtr(_) | ty::Opaque(..) | ty::Projection(_) - | ty::Never - | ty::Array(..) => t.super_fold_with(self), + | 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, + }, + )) + } // 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. diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index 183be1b1517a7..10cd491b480c1 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo<{_: _}>`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo`, where the type parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index c66606b9c8304..0746b2491fbd6 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` | | - | consider giving this pattern the explicit type `[_; _]`, where the type parameter `N` is specified + | consider giving this pattern the explicit type `[_; N]`, where the type parameter `N` is specified error: aborting due to previous error From 6a691b1d92c0c34ee8b43a6d04df30c908c4d6a3 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Mon, 8 Nov 2021 21:10:00 +0000 Subject: [PATCH 3/4] Refer to const params as "const params" and not "type params" --- .../infer/error_reporting/need_type_info.rs | 82 +++++++++++-------- .../defaults/doesnt_infer.stderr | 2 +- src/test/ui/inference/issue-83606.stderr | 2 +- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 56f0b5c192786..739987e850a01 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -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(), ¶m.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. diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index 10cd491b480c1..d6c64d58be5f3 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<{_: u32}>` LL | let foo = Foo::foo(); | --- ^^^^^^^^ cannot infer the value of const parameter `N` | | - | consider giving `foo` the explicit type `Foo`, where the type parameter `N` is specified + | consider giving `foo` the explicit type `Foo`, where the const parameter `N` is specified error: aborting due to previous error diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index 0746b2491fbd6..9ca8f35fd545a 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; _]` LL | let _ = foo("foo"); //<- Do not suggest `foo::("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 From 7271d1f803ba4a2f850d19c570d04993b61881a9 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 19 Nov 2021 06:10:43 +0000 Subject: [PATCH 4/4] Add test with multiple type params failing inference --- .../infer/error_reporting/need_type_info.rs | 4 +- .../inference/erase-type-params-in-label.rs | 18 ++++++++- .../erase-type-params-in-label.stderr | 39 ++++++++++++++----- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 739987e850a01..9cf6cde259150 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -939,9 +939,7 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> { /// 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) - } + ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty), _ => c, } } diff --git a/src/test/ui/inference/erase-type-params-in-label.rs b/src/test/ui/inference/erase-type-params-in-label.rs index 4a163d0b81094..1fea2da92da94 100644 --- a/src/test/ui/inference/erase-type-params-in-label.rs +++ b/src/test/ui/inference/erase-type-params-in-label.rs @@ -1,5 +1,8 @@ fn main() { - let foo = new(1, ""); //~ ERROR E0283 + let foo = foo(1, ""); //~ ERROR E0283 +} +fn baz() { + let bar = bar(1, ""); //~ ERROR E0283 } struct Bar { @@ -8,6 +11,17 @@ struct Bar { n: N, } -fn new(t: T, k: K) -> Bar { +fn bar(t: T, k: K) -> Bar { Bar { t, k, n: Default::default() } } + +struct Foo { + t: T, + k: K, + n: N, + m: M, +} + +fn foo(t: T, k: K) -> Foo { + Foo { t, k, n: Default::default(), m: Default::default() } +} diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr index b665fade9d88f..d0b06cde9d63a 100644 --- a/src/test/ui/inference/erase-type-params-in-label.stderr +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -1,22 +1,41 @@ -error[E0283]: type annotations needed for `Bar` +error[E0283]: type annotations needed for `Foo` --> $DIR/erase-type-params-in-label.rs:2:15 | -LL | let foo = new(1, ""); - | --- ^^^ cannot infer type for type parameter `Z` declared on the function `new` +LL | let foo = foo(1, ""); + | --- ^^^ cannot infer type for type parameter `W` declared on the function `foo` + | | + | consider giving `foo` the explicit type `Foo<_, _, W, Z>`, where the type parameter `W` is specified + | + = note: cannot satisfy `_: Default` +note: required by a bound in `foo` + --> $DIR/erase-type-params-in-label.rs:25:17 + | +LL | fn foo(t: T, k: K) -> Foo { + | ^^^^^^^ required by this bound in `foo` +help: consider specifying the type arguments in the function call + | +LL | let foo = foo::(1, ""); + | ++++++++++++++ + +error[E0283]: type annotations needed for `Bar` + --> $DIR/erase-type-params-in-label.rs:5:15 + | +LL | let bar = bar(1, ""); + | --- ^^^ cannot infer type for type parameter `Z` declared on the function `bar` | | - | consider giving `foo` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified + | consider giving `bar` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified | = note: cannot satisfy `_: Default` -note: required by a bound in `new` - --> $DIR/erase-type-params-in-label.rs:11:17 +note: required by a bound in `bar` + --> $DIR/erase-type-params-in-label.rs:14:17 | -LL | fn new(t: T, k: K) -> Bar { - | ^^^^^^^ required by this bound in `new` +LL | fn bar(t: T, k: K) -> Bar { + | ^^^^^^^ required by this bound in `bar` help: consider specifying the type arguments in the function call | -LL | let foo = new::(1, ""); +LL | let bar = bar::(1, ""); | +++++++++++ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0283`.