From dec73f92912e00796b857cb61710a9af88479eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 4 Aug 2024 15:50:47 +0000 Subject: [PATCH] When annotations needed, look at impls for more accurate suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When encountering an expression that needs type annotations, if we have the trait `DefId` we look for all the `impl`s that could be satisfied by the expression we have (without looking at additional obligations) and suggest the fully qualified to specific impls. For left over type parameters, we replace them with `_`. ``` error[E0283]: type annotations needed --> $DIR/E0283.rs:35:24 | LL | let bar = foo_impl.into() * 1u32; | ^^^^ | note: multiple `impl`s satisfying `Impl: Into<_>` found --> $DIR/E0283.rs:17:1 | LL | impl Into for Impl { | ^^^^^^^^^^^^^^^^^^^^^^^ = note: and another `impl` found in the `core` crate: - impl Into for T where U: From; help: try using a fully qualified path to specify the expected types | LL | let bar = <_ as Into<_>>::into(foo_impl) * 1u32; | +++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let bar = >::into(foo_impl) * 1u32; | ++++++++++++++++++++++++++ ~ ``` This approach does not account for blanket-impls, so we can end up with suggestions like `<_ as Into<_>>::into(foo)`. It'd be nice to have a more complete mechanism that does account for all obligations when resolving methods. Do not suggest `path::to::method` In the pretty-printer, we have a weird way to display fully-qualified for non-local impls, where we show a regular path, but the section corresponding to the `` we use non-syntax for it like `path::to`. It should be ``, but this is only better when we are printing code to be suggested, not to find where the `impl` actually is, so we add a new flag to the printer for this. Special case `Into` suggestion to look for `From` `impl`s When we encounter a blanket `` `impl`, look at the `From` `impl`s so that we can suggest the appropriate `Other`: ``` error[E0284]: type annotations needed --> $DIR/issue-70082.rs:7:33 | LL | let y: f64 = 0.01f64 * 1i16.into(); | - ^^^^ | | | type must be known at this point | = note: cannot satisfy `>::Output == f64` help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | ++++++++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++ ~ help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++++++++ ~ ``` Suggest an appropriate type for a binding of method chain Do the same we do with fully-qualified type suggestions to the suggestion to specify a binding type: ``` error[E0282]: type annotations needed --> $DIR/slice-pattern-refutable.rs:14:9 | LL | let [a, b, c] = Zeroes.into() else { | ^^^^^^^^^ | help: consider giving this pattern a type | LL | let [a, b, c]: _ = Zeroes.into() else { | +++ help: consider giving this pattern a type | LL | let [a, b, c]: [usize; 3] = Zeroes.into() else { | ++++++++++++ ``` review comments - Pass `ParamEnv` through - Remove now-unnecessary `Formatter` mode - Rework the way we pick up the bounds Add naïve mechanism to filter `Into` suggestions involving math ops ``` error[E0284]: type annotations needed --> $DIR/issue-70082.rs:7:33 | LL | let y: f64 = 0.01f64 * 1i16.into(); | - ^^^^ | | | type must be known at this point | = note: cannot satisfy `>::Output == f64` help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++++ ~ ``` Note that we only suggest `Into`, and not `Into`, `Into`, `Into`, `Into`, `Into` or `Into`. Replace `_` with `/* Type */` in let binding type suggestion Rework the `predicate` "trafficking" to be more targetted Rename `predicate` to `originating_projection`. Pass in only the `ProjectionPredicate` instead of the `Predicate` to avoid needing to destructure as much. Use `prove`/`ObligationCtxt` instead of `can_eq` Account for impl/trait difference Do not suggest `<_ as Into<_>>` blanket impl We will usually have a better, more specific, alternative suggestion. --- .../src/attributes/rustc_internal.rs | 1 + .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 + compiler/rustc_hir_typeck/src/method/probe.rs | 2 + compiler/rustc_hir_typeck/src/opaque_types.rs | 2 + compiler/rustc_hir_typeck/src/writeback.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + .../error_reporting/infer/need_type_info.rs | 273 ++++++++++++++++-- .../src/error_reporting/traits/ambiguity.rs | 14 + library/core/src/convert/mod.rs | 1 + tests/ui/error-codes/E0283.rs | 1 + tests/ui/error-codes/E0283.stderr | 2 +- .../inference/ambiguous_type_parameter.stderr | 2 +- tests/ui/inference/issue-12028.stderr | 2 +- tests/ui/inference/issue-72616.stderr | 2 +- tests/ui/inference/issue-72690.stderr | 178 +++++++++++- tests/ui/inference/issue-80816.rs | 1 + tests/ui/inference/multiple-impl-apply-2.rs | 48 +++ .../ui/inference/multiple-impl-apply-2.stderr | 26 ++ tests/ui/inference/multiple-impl-apply.stderr | 8 +- ...od-ambig-one-trait-unknown-int-type.stderr | 7 +- .../infer-unwrap-none-issue-120786.stderr | 178 +++++++++++- .../ui/pattern/slice-pattern-refutable.stderr | 6 +- .../pattern/slice-patterns-ambiguity.stderr | 21 +- ...gument-with-unnecessary-method-call.stderr | 2 +- ...s-by-name-in-suggestion-issue-96292.stderr | 7 +- ...ggest-non-existing-fully-qualified-path.rs | 1 + ...t-non-existing-fully-qualified-path.stderr | 2 +- .../suggest-fully-qualified-closure.stderr | 7 +- ...ully-qualified-path-with-adjustment.stderr | 63 +++- ...y-qualified-path-without-adjustment.stderr | 77 ++++- ...nference-for-associated-types-69683.stderr | 4 +- 31 files changed, 869 insertions(+), 76 deletions(-) create mode 100644 tests/ui/inference/multiple-impl-apply-2.rs create mode 100644 tests/ui/inference/multiple-impl-apply-2.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 6e1060ea05ae9..eef830b1c2176 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -991,6 +991,7 @@ impl SingleAttributeParser for RustcDiagnosticItemParser { Allow(Target::Fn), Allow(Target::Const), Allow(Target::Mod), + Allow(Target::Impl { of_trait: true }), Allow(Target::Impl { of_trait: false }), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9530ff4ca9a3d..00b7a5c645625 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1500,6 +1500,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty.into(), TypeAnnotationNeeded::E0282, true, + self.param_env, + None, ) .emit() }); @@ -1526,6 +1528,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ct.into(), TypeAnnotationNeeded::E0282, true, + self.param_env, + None, ) .emit() }); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 4258896deec70..850d1e29780be 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -516,6 +516,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty.into(), TypeAnnotationNeeded::E0282, !raw_ptr_call, + self.param_env, + None, ); if raw_ptr_call { err.span_label(span, "cannot call a method on a raw pointer with an unknown pointee type"); diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index 3229ad161783b..3f5ca6d959a2b 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -191,6 +191,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { infer_var, TypeAnnotationNeeded::E0282, false, + self.param_env, + None, ) .emit() } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index ba5b55b43049f..a97c45528fc3a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -924,6 +924,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { p.into(), TypeAnnotationNeeded::E0282, false, + self.fcx.param_env, + None, ) .emit() } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fb433aef68cf8..162010567d074 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -526,6 +526,7 @@ symbols! { bitxor, bitxor_assign, black_box, + blanket_into_impl, block, blocking, bool, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 862628ceb422e..49540d4df606d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -29,6 +29,7 @@ use crate::errors::{ SourceKindMultiSuggestion, SourceKindSubdiag, }; use crate::infer::{InferCtxt, TyOrConstInferVar}; +use crate::traits::{ObligationCause, ObligationCtxt}; pub enum TypeAnnotationNeeded { /// ```compile_fail,E0282 @@ -77,6 +78,14 @@ pub enum UnderspecifiedArgKind { Const { is_parameter: bool }, } +enum InferenceSuggestionFormat { + /// The inference suggestion will the provided as the explicit type of a binding. + BindingType, + /// The inference suggestion will the provided in the same expression where the error occurred, + /// expanding method calls into fully-qualified paths specifying the self-type and trait. + FullyQualifiedMethodCall, +} + impl InferenceDiagnosticsData { fn can_add_more_info(&self) -> bool { !(self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. })) @@ -490,6 +499,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term: Term<'tcx>, error_code: TypeAnnotationNeeded, should_label_span: bool, + param_env: ty::ParamEnv<'tcx>, + originating_projection: Option>, ) -> Diag<'a> { self.emit_inference_failure_err_with_type_hint( body_def_id, @@ -497,6 +508,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term, error_code, should_label_span, + param_env, + originating_projection, None, ) } @@ -508,6 +521,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term: Term<'tcx>, error_code: TypeAnnotationNeeded, should_label_span: bool, + param_env: ty::ParamEnv<'tcx>, + originating_projection: Option>, ty: Option>, ) -> Diag<'a> { let term = self.resolve_vars_if_possible(term); @@ -565,17 +580,56 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut infer_subdiags = Vec::new(); let mut multi_suggestions = Vec::new(); match kind { - InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => { - infer_subdiags.push(SourceKindSubdiag::LetLike { - span: insert_span, - name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new), - x_kind: arg_data.where_x_is_kind(self.infcx, ty), - prefix_kind: arg_data.kind.clone(), - prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), - arg_name: arg_data.name, - kind: if pattern_name.is_some() { "with_pattern" } else { "other" }, - type_name: ty_to_string(self, ty, def_id), - }); + InferSourceKind::LetBinding { + insert_span, + pattern_name, + ty, + def_id, + init_expr_hir_id, + } => { + let mut paths = vec![]; + if let Some(trait_def_id) = def_id + && let Some(hir_id) = init_expr_hir_id + && let expr = self.infcx.tcx.hir_expect_expr(hir_id) + && let hir::ExprKind::MethodCall(_, rcvr, _, _) = expr.kind + && let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id) + { + paths = self.get_fully_qualified_path_suggestions_from_impls( + ty, + trait_def_id, + InferenceSuggestionFormat::BindingType, + param_env, + originating_projection, + ); + } + + if !(1..6).contains(&paths.len()) { + infer_subdiags.push(SourceKindSubdiag::LetLike { + span: insert_span, + name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new), + x_kind: arg_data.where_x_is_kind(self.infcx, ty), + prefix_kind: arg_data.kind.clone(), + prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), + arg_name: arg_data.name, + kind: if pattern_name.is_some() { "with_pattern" } else { "other" }, + type_name: ty_to_string(self, ty, trait_def_id), + }); + } else { + for type_name in paths { + infer_subdiags.push(SourceKindSubdiag::LetLike { + span: insert_span, + name: pattern_name + .map(|name| name.to_string()) + .unwrap_or_else(String::new), + x_kind: arg_data.where_x_is_kind(self.infcx, ty), + prefix_kind: arg_data.kind.clone(), + prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), + arg_name: arg_data.name.clone(), + kind: if pattern_name.is_some() { "with_pattern" } else { "other" }, + type_name, + }); + } + } } InferSourceKind::ClosureArg { insert_span, ty, .. } => { infer_subdiags.push(SourceKindSubdiag::LetLike { @@ -717,12 +771,35 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => "", }; - multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified( - receiver.span, - def_path, - adjustment, - successor, - )); + // Look for all the possible implementations to suggest, otherwise we'll show + // just suggest the syntax for the fully qualified path with placeholders. + let paths = self.get_fully_qualified_path_suggestions_from_impls( + args.type_at(0), + def_id, + InferenceSuggestionFormat::FullyQualifiedMethodCall, + param_env, + originating_projection, + ); + if !(1..6).contains(&paths.len()) { + // This will show the fallback impl, so the expression will have type + // parameter placeholders, but it's better than nothing. + multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified( + receiver.span, + def_path, + adjustment, + successor, + )); + } else { + // These are the paths to specific impls. + for path in paths { + multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified( + receiver.span, + path, + adjustment, + successor, + )); + } + } } } InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => { @@ -773,6 +850,159 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } err } + + /// Given a `self_ty` and a trait item `def_id`, find all relevant `impl`s and provide suitable + /// code for a suggestion. + /// + /// If `suggestion_style` corresponds to a method call expression, then we suggest the + /// fully-qualified path for the associated item. + /// + /// If `suggestion_style` corresponds to a let binding, then we suggest a type suitable for it + /// corresponding to the return type of the associated item. + /// + /// If `originating_projection` corresponds to a math operation, we restrict the suggestions to + /// only `impl`s for the same type that was expected (instead of showing every integer type, + /// mention only the one that is most likely to be relevant). + /// + /// `trait From` is treated specially, in order to look for suitable `Into` `impl`s as well. + fn get_fully_qualified_path_suggestions_from_impls( + &self, + self_ty: Ty<'tcx>, + def_id: DefId, + suggestion_style: InferenceSuggestionFormat, + param_env: ty::ParamEnv<'tcx>, + originating_projection: Option>, + ) -> Vec { + let tcx = self.infcx.tcx; + let mut paths = vec![]; + let name = tcx.item_name(def_id); + let trait_def_id = tcx.parent(def_id); + tcx.for_each_relevant_impl(trait_def_id, self_ty, |impl_def_id| { + let impl_args = self.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = + tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(); + let impl_self_ty = impl_trait_ref.self_ty(); + if self.probe(|_| { + ObligationCtxt::new(self.infcx) + .eq(&ObligationCause::dummy(), param_env, self_ty, impl_self_ty) + .is_ok() + }) { + // The expr's self type could conform to this impl's self type. + } else { + // Nope, don't bother. + return; + } + + let filter = None; + tracing::info!(?originating_projection); + // let filter = if let Some(ty::ProjectionPredicate { + // projection_term: ty::AliasTerm { def_id, .. }, + // term, + // }) = originating_projection + // && let ty::TermKind::Ty(assoc_ty) = term.kind() + // && tcx.item_name(def_id) == sym::Output + // && hir::lang_items::BINARY_OPERATORS + // .iter() + // .map(|&op| tcx.lang_items().get(op)) + // .any(|op| op == Some(tcx.parent(def_id))) + // { + // // If the predicate that failed to be inferred is an associated type called + // // "Output" (from one of the math traits), we will only mention the `Into` and + // // `From` impls that correspond to the self type as well, so as to avoid showing + // // multiple conversion options. + // Some(assoc_ty) + // } else { + // None + // }; + let assocs = tcx.associated_items(impl_def_id); + + if tcx.is_diagnostic_item(sym::blanket_into_impl, impl_def_id) + && let Some(did) = tcx.get_diagnostic_item(sym::From) + { + let mut found = false; + for (_ , def_ids) in tcx.trait_impls_of(did).non_blanket_impls().iter() { + for impl_def_id in def_ids { + // We had an `::into` and we've hit the blanket + // impl for `From`. So we try and look for the right `From` + // impls that *would* apply. We *could* do this in a generalized + // version by evaluating the `where` clauses, but that would be + // way too involved to implement. Instead we special case the + // arguably most common case of `expr.into()`. + let header = tcx.impl_trait_header(*impl_def_id); + let target = header.trait_ref.skip_binder().args.type_at(0); + if filter.is_some() && filter != Some(target) { + continue; + }; + let target = header.trait_ref.skip_binder().args.type_at(0); + let ty = header.trait_ref.skip_binder().args.type_at(1); + if ty == self_ty { + match suggestion_style { + InferenceSuggestionFormat::BindingType => { + paths.push(if let ty::Infer(_) = target.kind() { + "/* Type */".to_string() + } else { + format!("{target}") + }); + } + InferenceSuggestionFormat::FullyQualifiedMethodCall => { + paths.push(format!("<{self_ty} as Into<{target}>>::into")); + } + } + found = true; + } + } + } + if found { + return; + } + } + + // We're at the `impl` level, but we want to get the same method we + // called *on this `impl`*, in order to get the right DefId and args. + let assoc = if let Some(assoc) = assocs.filter_by_name_unhygienic(name).next() { + // Method in the `impl`. + assoc + } else { + let assocs = tcx.associated_items(trait_def_id); + if let Some(assoc) = assocs.filter_by_name_unhygienic(name).next() { + // Method in the `trait`. + assoc + } else { + // The method isn't in this `impl` or `trait`? Not useful to us then. + return; + } + }; + let Some(trait_assoc_item) = assoc.trait_item_def_id() else { + return; + }; + let args = impl_trait_ref + .args + .extend_to(tcx, trait_assoc_item, |def, _| self.var_for_def(DUMMY_SP, def)); + match suggestion_style { + InferenceSuggestionFormat::BindingType => { + let fn_sig = tcx.fn_sig(def_id).instantiate(tcx, args); + let ret = fn_sig.skip_binder().output(); + paths.push(if let ty::Infer(_) = ret.kind() { + "/* Type */".to_string() + } else { + format!("{ret}") + }); + } + InferenceSuggestionFormat::FullyQualifiedMethodCall => { + if let Some(did) = tcx.get_diagnostic_item(sym::Into) + && did == trait_def_id + && let Some(arg) = impl_args.types().skip(1).next() + && let ty::Infer(_) | ty::Param(_) = arg.kind() + { + // Skip `>` blanket + } else { + paths.push(self.tcx.value_path_str_with_args(def_id, args)); + } + } + } + }); + paths + } } #[derive(Debug)] @@ -788,6 +1018,7 @@ enum InferSourceKind<'tcx> { pattern_name: Option, ty: Ty<'tcx>, def_id: Option, + init_expr_hir_id: Option, }, ClosureArg { insert_span: Span, @@ -990,8 +1221,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { let cost = self.source_cost(&new_source) + self.attempt; debug!(?cost); self.attempt += 1; - if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, .. }, .. }) = - self.infer_source + if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, .. }, .. }) + | Some(InferSource { + kind: InferSourceKind::FullyQualifiedMethodCall { def_id: did, .. }, + .. + }) = self.infer_source && let InferSourceKind::LetBinding { ref ty, ref mut def_id, .. } = new_source.kind && ty.is_ty_or_numeric_infer() { @@ -1335,6 +1569,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { pattern_name: local.pat.simple_ident(), ty, def_id: local.init.and_then(|expr| get_did(self.typeck_results, expr)), + init_expr_hir_id: local.init.map(|e| e.hir_id), }, }); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 108262d507ef7..7259c7ed92741 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -233,6 +233,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_pred.self_ty().skip_binder().into(), TypeAnnotationNeeded::E0282, false, + obligation.param_env, + None, ) .emit(), Some(e) => e, @@ -287,6 +289,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term, TypeAnnotationNeeded::E0283, true, + obligation.param_env, + None, match &candidates[..] { [candidate] => Some(*candidate), _ => None, @@ -547,6 +551,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term, TypeAnnotationNeeded::E0282, false, + obligation.param_env, + None, ) } @@ -566,6 +572,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { a.into(), TypeAnnotationNeeded::E0282, true, + obligation.param_env, + None, ) } @@ -601,6 +609,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term, TypeAnnotationNeeded::E0284, true, + obligation.param_env, + Some(data), ) .with_note(format!("cannot satisfy `{predicate}`")) .with_long_ty_path(long_ty_path) @@ -633,6 +643,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term, TypeAnnotationNeeded::E0284, true, + obligation.param_env, + None, ) } else { // If we can't find a generic parameter, just print a generic error @@ -655,6 +667,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ct.into(), TypeAnnotationNeeded::E0284, true, + obligation.param_env, + None, ), ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 34cf9c5d0a5b2..84c28be5bed2d 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -764,6 +764,7 @@ where // From implies Into #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] +#[rustc_diagnostic_item = "blanket_into_impl"] const impl Into for T where U: [const] From, diff --git a/tests/ui/error-codes/E0283.rs b/tests/ui/error-codes/E0283.rs index 5134660e3f4bd..ab5e9094b910f 100644 --- a/tests/ui/error-codes/E0283.rs +++ b/tests/ui/error-codes/E0283.rs @@ -33,5 +33,6 @@ fn main() { fn buzz() { let foo_impl = Impl::new(); let bar = foo_impl.into() * 1u32; //~ ERROR E0283 + // let bar = >::into(foo_impl) * 1u32; foo(bar); } diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr index 29baae5f133a2..b680e71e1ad06 100644 --- a/tests/ui/error-codes/E0283.stderr +++ b/tests/ui/error-codes/E0283.stderr @@ -31,7 +31,7 @@ LL | impl Into for Impl { help: try using a fully qualified path to specify the expected types | LL - let bar = foo_impl.into() * 1u32; -LL + let bar = >::into(foo_impl) * 1u32; +LL + let bar = >::into(foo_impl) * 1u32; | error: aborting due to 2 previous errors diff --git a/tests/ui/inference/ambiguous_type_parameter.stderr b/tests/ui/inference/ambiguous_type_parameter.stderr index 835999121d611..2e0831321419a 100644 --- a/tests/ui/inference/ambiguous_type_parameter.stderr +++ b/tests/ui/inference/ambiguous_type_parameter.stderr @@ -7,7 +7,7 @@ LL | InMemoryStore.get_raw(&String::default()); help: try using a fully qualified path to specify the expected types | LL - InMemoryStore.get_raw(&String::default()); -LL + >>::get_raw(&InMemoryStore, &String::default()); +LL + >>::get_raw(&InMemoryStore, &String::default()); | error: aborting due to 1 previous error diff --git a/tests/ui/inference/issue-12028.stderr b/tests/ui/inference/issue-12028.stderr index 0d8ef1c938d4c..1015da37d3858 100644 --- a/tests/ui/inference/issue-12028.stderr +++ b/tests/ui/inference/issue-12028.stderr @@ -8,7 +8,7 @@ LL | self.input_stream(&mut stream); help: try using a fully qualified path to specify the expected types | LL - self.input_stream(&mut stream); -LL + >::input_stream(self, &mut stream); +LL + >::input_stream(self, &mut stream); | error: aborting due to 1 previous error diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr index 8eba3216a8464..afaaa1a9de1a6 100644 --- a/tests/ui/inference/issue-72616.stderr +++ b/tests/ui/inference/issue-72616.stderr @@ -16,7 +16,7 @@ LL | if String::from("a") == "a".try_into().unwrap() {} help: try using a fully qualified path to specify the expected types | LL - if String::from("a") == "a".try_into().unwrap() {} -LL + if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} +LL + if String::from("a") == <_ as TryInto<_>>::try_into("a").unwrap() {} | error: aborting due to 1 previous error diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr index 4926cf9e981ba..caf3bd1cd4a40 100644 --- a/tests/ui/inference/issue-72690.stderr +++ b/tests/ui/inference/issue-72690.stderr @@ -23,7 +23,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -51,7 +71,27 @@ LL | |x| String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - |x| String::from("x".as_ref()); -LL + |x| String::from(>::as_ref("x")); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); | error[E0283]: type annotations needed for `&_` @@ -68,7 +108,7 @@ LL | let _ = "x".as_ref(); - impl AsRef for str; help: consider giving this pattern a type, where the type for type parameter `T` is specified | -LL | let _: &T = "x".as_ref(); +LL | let _: &_ = "x".as_ref(); | ++++ error[E0283]: type annotations needed @@ -96,7 +136,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -124,7 +184,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -152,7 +232,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -180,7 +280,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -208,7 +328,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -236,7 +376,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error: aborting due to 17 previous errors diff --git a/tests/ui/inference/issue-80816.rs b/tests/ui/inference/issue-80816.rs index 4d319b44987e2..dfdea791ebbaa 100644 --- a/tests/ui/inference/issue-80816.rs +++ b/tests/ui/inference/issue-80816.rs @@ -50,6 +50,7 @@ pub fn foo() { let guard: Guard> = s.load(); //~^ ERROR: type annotations needed //~| HELP: try using a fully qualified path to specify the expected types + // let guard: Guard> = >> as Access>>::load(&s); } fn main() {} diff --git a/tests/ui/inference/multiple-impl-apply-2.rs b/tests/ui/inference/multiple-impl-apply-2.rs new file mode 100644 index 0000000000000..5cdd697d4df9f --- /dev/null +++ b/tests/ui/inference/multiple-impl-apply-2.rs @@ -0,0 +1,48 @@ +struct Foo { + inner: u32, +} + +struct Bar { + inner: u32, +} + +#[derive(Clone, Copy)] +struct Baz { + inner: u32, +} + +impl Into for Baz { + fn into (self) -> Bar { + Bar { + inner: self.inner, + } + } +} + +impl From for Foo { + fn from(other: Baz) -> Self { + Self { + inner: other.inner, + } + } +} + +fn main() { + let x: Baz = Baz { inner: 42 }; + + // DOESN'T Compile: Multiple options! + let y = x.into(); //~ ERROR E0283 + + let y_1: Foo = x.into(); + let y_2: Bar = x.into(); + + let z_1 = Foo::from(y_1); + let z_2 = Bar::from(y_2); + + // No type annotations needed, the compiler KNOWS the type must be `Foo`! + let m = magic_foo(x); +} + +fn magic_foo(arg: Baz) -> Foo { + arg.into() +} diff --git a/tests/ui/inference/multiple-impl-apply-2.stderr b/tests/ui/inference/multiple-impl-apply-2.stderr new file mode 100644 index 0000000000000..0bd23a4dec989 --- /dev/null +++ b/tests/ui/inference/multiple-impl-apply-2.stderr @@ -0,0 +1,26 @@ +error[E0283]: type annotations needed + --> $DIR/multiple-impl-apply-2.rs:34:9 + | +LL | let y = x.into(); + | ^ ---- type must be known at this point + | +note: multiple `impl`s satisfying `Baz: Into<_>` found + --> $DIR/multiple-impl-apply-2.rs:14:1 + | +LL | impl Into for Baz { + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: and another `impl` found in the `core` crate: + - impl Into for T + where U: From; +help: consider giving `y` an explicit type + | +LL | let y: Foo = x.into(); + | +++++ +help: consider giving `y` an explicit type + | +LL | let y: Bar = x.into(); + | +++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/multiple-impl-apply.stderr b/tests/ui/inference/multiple-impl-apply.stderr index 1a81955e1e88c..0b043675d855a 100644 --- a/tests/ui/inference/multiple-impl-apply.stderr +++ b/tests/ui/inference/multiple-impl-apply.stderr @@ -15,8 +15,12 @@ LL | impl From for Foo { = note: required for `Baz` to implement `Into<_>` help: consider giving `y` an explicit type | -LL | let y: /* Type */ = x.into(); - | ++++++++++++ +LL | let y: Bar = x.into(); + | +++++ +help: consider giving `y` an explicit type + | +LL | let y: Foo = x.into(); + | +++++ error: aborting due to 1 previous error diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index a5f1b76702f57..a1cdebdbe4023 100644 --- a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -26,7 +26,12 @@ LL | impl Foo for Vec { help: try using a fully qualified path to specify the expected types | LL - x.foo(); -LL + as Foo>::foo(&x); +LL + as Foo>::foo(&x); + | +help: try using a fully qualified path to specify the expected types + | +LL - x.foo(); +LL + as Foo>::foo(&x); | error[E0308]: mismatched types diff --git a/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr b/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr index 3be18fc59e737..0d800dc638fb5 100644 --- a/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr +++ b/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr @@ -34,7 +34,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -62,7 +82,27 @@ LL | |x| String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - |x| String::from("x".as_ref()); -LL + |x| String::from(>::as_ref("x")); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); | error[E0283]: type annotations needed for `&_` @@ -79,7 +119,7 @@ LL | let _ = "x".as_ref(); - impl AsRef for str; help: consider giving this pattern a type, where the type for type parameter `T` is specified | -LL | let _: &T = "x".as_ref(); +LL | let _: &_ = "x".as_ref(); | ++++ error[E0283]: type annotations needed @@ -107,7 +147,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -135,7 +195,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -163,7 +243,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -191,7 +291,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -219,7 +339,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error[E0283]: type annotations needed @@ -247,7 +387,27 @@ LL | String::from("x".as_ref()); help: try using a fully qualified path to specify the expected types | LL - String::from("x".as_ref()); -LL + String::from(>::as_ref("x")); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); | error: aborting due to 18 previous errors diff --git a/tests/ui/pattern/slice-pattern-refutable.stderr b/tests/ui/pattern/slice-pattern-refutable.stderr index ece5e0283e27e..27f9aae5918f9 100644 --- a/tests/ui/pattern/slice-pattern-refutable.stderr +++ b/tests/ui/pattern/slice-pattern-refutable.stderr @@ -9,7 +9,7 @@ LL | let [a, b, c] = Zeroes.into() else { help: try using a fully qualified path to specify the expected types | LL - let [a, b, c] = Zeroes.into() else { -LL + let [a, b, c] = >::into(Zeroes) else { +LL + let [a, b, c] = >::into(Zeroes) else { | error[E0282]: type annotations needed @@ -23,7 +23,7 @@ LL | if let [a, b, c] = Zeroes.into() { help: try using a fully qualified path to specify the expected types | LL - if let [a, b, c] = Zeroes.into() { -LL + if let [a, b, c] = >::into(Zeroes) { +LL + if let [a, b, c] = >::into(Zeroes) { | error[E0282]: type annotations needed @@ -37,7 +37,7 @@ LL | if let [a, b, c] = Zeroes.into() { help: try using a fully qualified path to specify the expected types | LL - if let [a, b, c] = Zeroes.into() { -LL + if let [a, b, c] = >::into(Zeroes) { +LL + if let [a, b, c] = >::into(Zeroes) { | error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/slice-patterns-ambiguity.stderr b/tests/ui/pattern/slice-patterns-ambiguity.stderr index 539afed0bc009..2a2426eb8c79a 100644 --- a/tests/ui/pattern/slice-patterns-ambiguity.stderr +++ b/tests/ui/pattern/slice-patterns-ambiguity.stderr @@ -9,7 +9,12 @@ LL | let &[a, b] = Zeroes.into() else { help: try using a fully qualified path to specify the expected types | LL - let &[a, b] = Zeroes.into() else { -LL + let &[a, b] = >::into(Zeroes) else { +LL + let &[a, b] = >::into(Zeroes) else { + | +help: try using a fully qualified path to specify the expected types + | +LL - let &[a, b] = Zeroes.into() else { +LL + let &[a, b] = >::into(Zeroes) else { | error[E0282]: type annotations needed @@ -23,7 +28,12 @@ LL | if let &[a, b] = Zeroes.into() { help: try using a fully qualified path to specify the expected types | LL - if let &[a, b] = Zeroes.into() { -LL + if let &[a, b] = >::into(Zeroes) { +LL + if let &[a, b] = >::into(Zeroes) { + | +help: try using a fully qualified path to specify the expected types + | +LL - if let &[a, b] = Zeroes.into() { +LL + if let &[a, b] = >::into(Zeroes) { | error[E0282]: type annotations needed @@ -37,7 +47,12 @@ LL | if let &[a, b] = Zeroes.into() { help: try using a fully qualified path to specify the expected types | LL - if let &[a, b] = Zeroes.into() { -LL + if let &[a, b] = >::into(Zeroes) { +LL + if let &[a, b] = >::into(Zeroes) { + | +help: try using a fully qualified path to specify the expected types + | +LL - if let &[a, b] = Zeroes.into() { +LL + if let &[a, b] = >::into(Zeroes) { | error: aborting due to 3 previous errors diff --git a/tests/ui/trait-bounds/argument-with-unnecessary-method-call.stderr b/tests/ui/trait-bounds/argument-with-unnecessary-method-call.stderr index 870a865f02dd6..21970e13045c4 100644 --- a/tests/ui/trait-bounds/argument-with-unnecessary-method-call.stderr +++ b/tests/ui/trait-bounds/argument-with-unnecessary-method-call.stderr @@ -15,7 +15,7 @@ LL | fn qux(_: impl From) {} help: try using a fully qualified path to specify the expected types | LL - qux(Bar.into()); -LL + qux(>::into(Bar)); +LL + qux(>::into(Bar)); | help: consider removing this method call, as the receiver has type `Bar` and `Bar: From` trivially holds | diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr index 139488d79f13b..2a5a521018aad 100644 --- a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -15,7 +15,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - thing.method(42); -LL + as Method>::method(thing, 42); +LL + as Method>::method(thing, 42); + | +help: try using a fully qualified path to specify the expected types + | +LL - thing.method(42); +LL + as Method>::method(thing, 42); | error: aborting due to 1 previous error diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs index e9e2f6b129017..ea56cbd5ab086 100644 --- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs @@ -19,4 +19,5 @@ where fn main() { let a = A(B); a.method(); //~ ERROR type annotations needed + // as V>::method(a); } diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr index 7a2db203ac3f8..d453f098219b7 100644 --- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -22,7 +22,7 @@ LL | T: I, help: try using a fully qualified path to specify the expected types | LL - a.method(); -LL + as V>::method(a); +LL + as V<_>>::method(a); | error: aborting due to 1 previous error diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr index 8975d04d5b3ed..e6a7c5709f415 100644 --- a/tests/ui/traits/suggest-fully-qualified-closure.stderr +++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr @@ -15,7 +15,12 @@ LL | impl MyTrait for Qqq{ help: try using a fully qualified path to specify the expected types | LL - q.lol(||()); -LL + >::lol::<_>(&q, ||()); +LL + >::lol::<_>(&q, ||()); + | +help: try using a fully qualified path to specify the expected types + | +LL - q.lol(||()); +LL + >::lol::<_>(&q, ||()); | error: aborting due to 1 previous error diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr index 0996227e69701..875099674613c 100644 --- a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr @@ -15,7 +15,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - thing.method(); -LL + >::method(&thing); +LL + >::method(&thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - thing.method(); +LL + >::method(&thing); | error[E0283]: type annotations needed @@ -35,7 +40,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - thing.mut_method(); -LL + >::mut_method(&mut thing); +LL + >::mut_method(&mut thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - thing.mut_method(); +LL + >::mut_method(&mut thing); | error[E0283]: type annotations needed @@ -55,7 +65,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - thing.by_self(); -LL + <&Thing as MethodRef>::by_self(&thing); +LL + <&Thing as MethodRef>::by_self(&thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - thing.by_self(); +LL + <&Thing as MethodRef>::by_self(&thing); | error[E0283]: type annotations needed @@ -75,7 +90,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_to.method(); -LL + >::method(&deref_to); +LL + >::method(&deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_to.method(); +LL + >::method(&deref_to); | error[E0283]: type annotations needed @@ -95,7 +115,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_to.mut_method(); -LL + >::mut_method(&mut deref_to); +LL + >::mut_method(&mut deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_to.mut_method(); +LL + >::mut_method(&mut deref_to); | error[E0283]: type annotations needed @@ -115,7 +140,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - deref_to.by_self(); -LL + <&Thing as MethodRef>::by_self(&deref_to); +LL + <&Thing as MethodRef>::by_self(&deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_to.by_self(); +LL + <&Thing as MethodRef>::by_self(&deref_to); | error[E0283]: type annotations needed @@ -135,7 +165,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_deref_to.method(); -LL + >::method(&deref_deref_to); +LL + >::method(&deref_deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_deref_to.method(); +LL + >::method(&deref_deref_to); | error[E0283]: type annotations needed @@ -155,7 +190,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_deref_to.mut_method(); -LL + >::mut_method(&mut deref_deref_to); +LL + >::mut_method(&mut deref_deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_deref_to.mut_method(); +LL + >::mut_method(&mut deref_deref_to); | error[E0283]: type annotations needed @@ -175,7 +215,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - deref_deref_to.by_self(); -LL + <&Thing as MethodRef>::by_self(&deref_deref_to); +LL + <&Thing as MethodRef>::by_self(&deref_deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_deref_to.by_self(); +LL + <&Thing as MethodRef>::by_self(&deref_deref_to); | error: aborting due to 9 previous errors diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr index 629904815f312..f06d43d1da376 100644 --- a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr @@ -15,7 +15,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - ref_thing.method(); -LL + >::method(ref_thing); +LL + >::method(ref_thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - ref_thing.method(); +LL + >::method(ref_thing); | error[E0283]: type annotations needed @@ -35,7 +40,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - ref_thing.by_self(); -LL + <&Thing as MethodRef>::by_self(ref_thing); +LL + <&Thing as MethodRef>::by_self(ref_thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - ref_thing.by_self(); +LL + <&Thing as MethodRef>::by_self(ref_thing); | error[E0283]: type annotations needed @@ -55,7 +65,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - mut_thing.method(); -LL + >::method(mut_thing); +LL + >::method(mut_thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - mut_thing.method(); +LL + >::method(mut_thing); | error[E0283]: type annotations needed @@ -75,7 +90,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - mut_thing.mut_method(); -LL + >::mut_method(mut_thing); +LL + >::mut_method(mut_thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - mut_thing.mut_method(); +LL + >::mut_method(mut_thing); | error[E0283]: type annotations needed @@ -95,7 +115,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - mut_thing.by_self(); -LL + <&Thing as MethodRef>::by_self(mut_thing); +LL + <&Thing as MethodRef>::by_self(mut_thing); + | +help: try using a fully qualified path to specify the expected types + | +LL - mut_thing.by_self(); +LL + <&Thing as MethodRef>::by_self(mut_thing); | error[E0283]: type annotations needed @@ -115,7 +140,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_to.method(); -LL + >::method(deref_to); +LL + >::method(deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_to.method(); +LL + >::method(deref_to); | error[E0283]: type annotations needed @@ -135,7 +165,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_to.mut_method(); -LL + >::mut_method(deref_to); +LL + >::mut_method(deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_to.mut_method(); +LL + >::mut_method(deref_to); | error[E0283]: type annotations needed @@ -155,7 +190,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - deref_to.by_self(); -LL + <&Thing as MethodRef>::by_self(deref_to); +LL + <&Thing as MethodRef>::by_self(deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_to.by_self(); +LL + <&Thing as MethodRef>::by_self(deref_to); | error[E0283]: type annotations needed @@ -175,7 +215,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_deref_to.method(); -LL + >::method(deref_deref_to); +LL + >::method(deref_deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_deref_to.method(); +LL + >::method(deref_deref_to); | error[E0283]: type annotations needed @@ -195,7 +240,12 @@ LL | impl Method for Thing { help: try using a fully qualified path to specify the expected types | LL - deref_deref_to.mut_method(); -LL + >::mut_method(deref_deref_to); +LL + >::mut_method(deref_deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_deref_to.mut_method(); +LL + >::mut_method(deref_deref_to); | error[E0283]: type annotations needed @@ -215,7 +265,12 @@ LL | impl MethodRef for &Thing { help: try using a fully qualified path to specify the expected types | LL - deref_deref_to.by_self(); -LL + <&Thing as MethodRef>::by_self(deref_deref_to); +LL + <&Thing as MethodRef>::by_self(deref_deref_to); + | +help: try using a fully qualified path to specify the expected types + | +LL - deref_deref_to.by_self(); +LL + <&Thing as MethodRef>::by_self(deref_deref_to); | error: aborting due to 11 previous errors diff --git a/tests/ui/typeck/type-inference-for-associated-types-69683.stderr b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr index 5d49d442c55d0..c3ca2b5ab79d0 100644 --- a/tests/ui/typeck/type-inference-for-associated-types-69683.stderr +++ b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr @@ -8,7 +8,7 @@ LL | 0u16.foo(b); help: try using a fully qualified path to specify the expected types | LL - 0u16.foo(b); -LL + >::foo(0u16, b); +LL + >::foo(0u16, b); | error[E0283]: type annotations needed @@ -36,7 +36,7 @@ LL | fn foo(self, x: >::Array); help: try using a fully qualified path to specify the expected types | LL - 0u16.foo(b); -LL + >::foo(0u16, b); +LL + >::foo(0u16, b); | error: aborting due to 2 previous errors