mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 12:36:47 +00:00
Refactored a few bits:
- Firstly get all the information about generics matching out of the HIR - Secondly the labelling for the function is more coherent now - Lastly a few error message improvements
This commit is contained in:
parent
df93364057
commit
8a5245e7dd
@ -50,7 +50,7 @@ pub use rustc_error_messages::{
|
||||
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier,
|
||||
LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
|
||||
};
|
||||
pub use rustc_lint_defs::{a_or_an, display_list_with_comma_and, pluralize, Applicability};
|
||||
pub use rustc_lint_defs::{pluralize, Applicability};
|
||||
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
|
||||
pub use rustc_span::ErrorGuaranteed;
|
||||
pub use snippet::Style;
|
||||
@ -1946,6 +1946,39 @@ pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
|
||||
}
|
||||
}
|
||||
|
||||
/// Grammatical tool for displaying messages to end users in a nice form.
|
||||
///
|
||||
/// Returns "an" if the given string starts with a vowel, and "a" otherwise.
|
||||
pub fn a_or_an(s: &str) -> &'static str {
|
||||
let mut chars = s.chars();
|
||||
let Some(mut first_alpha_char) = chars.next() else {
|
||||
return "a";
|
||||
};
|
||||
if first_alpha_char == '`' {
|
||||
let Some(next) = chars.next() else {
|
||||
return "a";
|
||||
};
|
||||
first_alpha_char = next;
|
||||
}
|
||||
if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
|
||||
"an"
|
||||
} else {
|
||||
"a"
|
||||
}
|
||||
}
|
||||
|
||||
/// Grammatical tool for displaying messages to end users in a nice form.
|
||||
///
|
||||
/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c"
|
||||
pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
|
||||
match v.len() {
|
||||
0 => "".to_string(),
|
||||
1 => v[0].to_string(),
|
||||
2 => format!("{} and {}", v[0], v[1]),
|
||||
_ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum TerminalUrl {
|
||||
No,
|
||||
|
@ -18,7 +18,7 @@ use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{
|
||||
a_or_an, codes::*, display_list_with_comma_and, pluralize, Applicability, Diag,
|
||||
DiagnosticBuilder, ErrorGuaranteed, MultiSpan, StashKey,
|
||||
ErrorGuaranteed, MultiSpan, StashKey,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
@ -424,7 +424,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"expected formal_input_tys to be the same size as expected_input_tys"
|
||||
);
|
||||
let formal_and_expected_inputs = IndexVec::from_iter(
|
||||
formal_input_tys.iter().copied().zip_eq(expected_input_tys.iter().copied()),
|
||||
formal_input_tys
|
||||
.iter()
|
||||
.copied()
|
||||
.zip_eq(expected_input_tys.iter().copied())
|
||||
.map(|vars| self.resolve_vars_if_possible(vars)),
|
||||
);
|
||||
|
||||
self.set_tainted_by_errors(self.report_arg_errors(
|
||||
@ -639,8 +643,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
|
||||
let formal_input_ty = self.resolve_vars_if_possible(formal_input_ty);
|
||||
let expected_input_ty = self.resolve_vars_if_possible(expected_input_ty);
|
||||
// If either is an error type, we defy the usual convention and consider them to *not* be
|
||||
// coercible. This prevents our error message heuristic from trying to pass errors into
|
||||
// every argument.
|
||||
@ -713,7 +715,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Do we have as many extra provided arguments as the tuple's length?
|
||||
// If so, we might have just forgotten to wrap some args in a tuple.
|
||||
if let Some(ty::Tuple(tys)) =
|
||||
formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| self.resolve_vars_if_possible(tys.1).kind())
|
||||
formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
|
||||
// If the tuple is unit, we're not actually wrapping any arguments.
|
||||
&& !tys.is_empty()
|
||||
&& provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
|
||||
@ -732,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
|
||||
),
|
||||
) {
|
||||
if !self.can_coerce(provided_ty, self.resolve_vars_if_possible(*expected_ty)) {
|
||||
if !self.can_coerce(provided_ty, *expected_ty) {
|
||||
satisfied = false;
|
||||
break;
|
||||
}
|
||||
@ -751,14 +753,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if tys.len() == 1 {
|
||||
// A tuple wrap suggestion actually occurs within,
|
||||
// so don't do anything special here.
|
||||
let (formal_ty, expected_ty) =
|
||||
formal_and_expected_inputs[mismatch_idx.into()];
|
||||
let formal_ty = self.resolve_vars_if_possible(formal_ty);
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
err = self.err_ctxt().report_and_explain_type_error(
|
||||
mk_trace(
|
||||
*lo,
|
||||
(formal_ty, expected_ty),
|
||||
formal_and_expected_inputs[mismatch_idx.into()],
|
||||
provided_arg_tys[mismatch_idx.into()].0,
|
||||
),
|
||||
terr,
|
||||
@ -842,10 +840,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return true;
|
||||
};
|
||||
let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
|
||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
|
||||
let formal_ty = self.resolve_vars_if_possible(formal_ty);
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
|
||||
let trace =
|
||||
mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
|
||||
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
|
||||
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e);
|
||||
suggest_confusable(&mut err);
|
||||
@ -873,8 +869,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
] = &errors[..]
|
||||
{
|
||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
|
||||
let formal_ty = self.resolve_vars_if_possible(formal_ty);
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
|
||||
let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
|
||||
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
|
||||
@ -896,6 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&matched_inputs,
|
||||
&provided_arg_tys,
|
||||
&formal_and_expected_inputs,
|
||||
is_method,
|
||||
);
|
||||
|
||||
if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
|
||||
@ -1003,8 +998,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match error {
|
||||
Error::Invalid(provided_idx, expected_idx, compatibility) => {
|
||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
|
||||
let formal_ty = self.resolve_vars_if_possible(formal_ty);
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
|
||||
if let Compatibility::Incompatible(error) = compatibility {
|
||||
let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
|
||||
@ -1109,7 +1102,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match &missing_idxs[..] {
|
||||
&[expected_idx] => {
|
||||
let (_, input_ty) = formal_and_expected_inputs[expected_idx];
|
||||
let input_ty = self.resolve_vars_if_possible(input_ty);
|
||||
let span = if let Some((_, arg_span)) =
|
||||
provided_arg_tys.get(expected_idx.to_provided_idx())
|
||||
{
|
||||
@ -1132,10 +1124,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&[first_idx, second_idx] => {
|
||||
let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
|
||||
let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
|
||||
let first_expected_ty =
|
||||
self.resolve_vars_if_possible(first_expected_ty);
|
||||
let second_expected_ty =
|
||||
self.resolve_vars_if_possible(second_expected_ty);
|
||||
let span = if let (Some((_, first_span)), Some((_, second_span))) = (
|
||||
provided_arg_tys.get(first_idx.to_provided_idx()),
|
||||
provided_arg_tys.get(second_idx.to_provided_idx()),
|
||||
@ -1162,14 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
&[first_idx, second_idx, third_idx] => {
|
||||
let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
|
||||
let first_expected_ty =
|
||||
self.resolve_vars_if_possible(first_expected_ty);
|
||||
let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
|
||||
let second_expected_ty =
|
||||
self.resolve_vars_if_possible(second_expected_ty);
|
||||
let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
|
||||
let third_expected_ty =
|
||||
self.resolve_vars_if_possible(third_expected_ty);
|
||||
let span = if let (Some((_, first_span)), Some((_, third_span))) = (
|
||||
provided_arg_tys.get(first_idx.to_provided_idx()),
|
||||
provided_arg_tys.get(third_idx.to_provided_idx()),
|
||||
@ -1229,7 +1211,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
) => {
|
||||
let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
|
||||
let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
|
||||
let first_expected_ty = self.resolve_vars_if_possible(first_expected_ty);
|
||||
let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
|
||||
format!(", found `{first_provided_ty}`")
|
||||
} else {
|
||||
@ -1242,7 +1223,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
|
||||
let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
|
||||
let second_provided_ty = self.resolve_vars_if_possible(second_provided_ty);
|
||||
let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
|
||||
format!(", found `{second_provided_ty}`")
|
||||
} else {
|
||||
@ -1261,7 +1241,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Error::Permutation(args) => {
|
||||
for (dst_arg, dest_input) in args {
|
||||
let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
let (provided_ty, provided_span) = provided_arg_tys[dest_input];
|
||||
let provided_ty_name = if !has_error_or_infer([provided_ty]) {
|
||||
format!(", found `{provided_ty}`")
|
||||
@ -1288,6 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&matched_inputs,
|
||||
&provided_arg_tys,
|
||||
&formal_and_expected_inputs,
|
||||
is_method,
|
||||
);
|
||||
|
||||
// Incorporate the argument changes in the removal suggestion.
|
||||
@ -1325,7 +1305,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// To suggest a multipart suggestion when encountering `foo(1, "")` where the def
|
||||
// was `fn foo(())`.
|
||||
let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
|
||||
}
|
||||
}
|
||||
@ -1402,7 +1381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
// Propose a placeholder of the correct type
|
||||
let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
|
||||
let expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||
ty_to_snippet(expected_ty, expected_idx)
|
||||
};
|
||||
suggestion += &suggestion_text;
|
||||
@ -2202,118 +2180,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
{
|
||||
let mut spans: MultiSpan = def_span.into();
|
||||
|
||||
let param_generics: Vec<Option<&hir::GenericParam<'_>>> = self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.fn_decl())
|
||||
.into_iter()
|
||||
.flat_map(|decl| decl.inputs)
|
||||
.skip(if is_method { 1 } else { 0 })
|
||||
.map(|param| {
|
||||
if let hir::TyKind::Path(QPath::Resolved(
|
||||
_,
|
||||
hir::Path { res: Res::Def(_, res_def_id), .. },
|
||||
)) = param.kind
|
||||
{
|
||||
self.tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.generics())
|
||||
.into_iter()
|
||||
.flat_map(|generics| generics.params)
|
||||
.find(|gen| &gen.def_id.to_def_id() == res_def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let params_with_generics = self.get_hir_params_with_generics(def_id, is_method);
|
||||
let mut generics_with_unmatched_params = Vec::new();
|
||||
|
||||
let params: Vec<&hir::Param<'_>> = self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.body_id())
|
||||
.into_iter()
|
||||
.flat_map(|id| self.tcx.hir().body(id).params)
|
||||
.skip(if is_method { 1 } else { 0 })
|
||||
.collect();
|
||||
|
||||
if params.len() == param_generics.len() {
|
||||
let mut generics_map: Vec<(usize, &hir::GenericParam<'_>)> = Vec::new();
|
||||
// This is a map from the index of the generic to the index of the parameter and the
|
||||
// parameter
|
||||
let mut matched_params_map: Vec<(usize, usize, &hir::Param<'_>)> = Vec::new();
|
||||
let mut unmatched_params_map: Vec<(usize, &hir::Param<'_>)> = Vec::new();
|
||||
|
||||
for (idx, (param, generic)) in
|
||||
params.iter().zip_eq(param_generics.iter()).enumerate()
|
||||
let check_for_matched_generics = || {
|
||||
if matched_inputs.iter().any(|x| x.is_some())
|
||||
&& params_with_generics.iter().any(|x| x.0.is_some())
|
||||
{
|
||||
if matched_inputs[idx.into()].is_none() {
|
||||
spans.push_span_label(param.span, "");
|
||||
continue;
|
||||
}
|
||||
for (idx, (generic, _)) in params_with_generics.iter().enumerate() {
|
||||
// Param has to have a generic and be matched to be relevant
|
||||
if matched_inputs[idx.into()].is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(generic) = generic else {
|
||||
spans.push_span_label(param.span, "");
|
||||
continue;
|
||||
};
|
||||
let Some(generic) = generic else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut found_unmatched_generic_params = vec![];
|
||||
|
||||
for unmatching_idx in idx + 1..params.len() {
|
||||
if matched_inputs[unmatching_idx.into()].is_none()
|
||||
&& let Some(unmatched_idx_param_generic) =
|
||||
param_generics[unmatching_idx]
|
||||
&& unmatched_idx_param_generic.name.ident() == generic.name.ident()
|
||||
{
|
||||
found_unmatched_generic_params.push(params[unmatching_idx]);
|
||||
for unmatching_idx in idx + 1..params_with_generics.len() {
|
||||
if matched_inputs[unmatching_idx.into()].is_none()
|
||||
&& let Some(unmatched_idx_param_generic) =
|
||||
params_with_generics[unmatching_idx].0
|
||||
&& unmatched_idx_param_generic.name.ident() == generic.name.ident()
|
||||
{
|
||||
// We found a parameter that didn't match that needed to
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found_unmatched_generic_params.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let generics_idx = generics_map
|
||||
.iter()
|
||||
.filter(|x| x.1.name.ident() == generic.name.ident())
|
||||
.next()
|
||||
.map(|x| x.0);
|
||||
|
||||
let generics_idx = generics_idx.unwrap_or_else(|| {
|
||||
let generics_map_len = generics_map.len();
|
||||
generics_map.push((generics_map_len, generic));
|
||||
generics_map_len
|
||||
});
|
||||
matched_params_map.push((generics_idx, idx, param));
|
||||
if unmatched_params_map.iter().filter(|x| x.0 == generics_idx).count() > 0 {
|
||||
// Already processed the unmatched params
|
||||
continue;
|
||||
}
|
||||
for unmatched_param in &found_unmatched_generic_params {
|
||||
unmatched_params_map.push((generics_idx, unmatched_param));
|
||||
}
|
||||
}
|
||||
false
|
||||
};
|
||||
|
||||
for (generic_idx, generic) in &generics_map {
|
||||
let matched_params: Vec<(usize, &hir::Param<'_>)> = matched_params_map
|
||||
.iter()
|
||||
.filter(|x| x.0 == *generic_idx)
|
||||
.map(|x| (x.1, x.2))
|
||||
.collect();
|
||||
let unmatched_params: Vec<&hir::Param<'_>> = unmatched_params_map
|
||||
.iter()
|
||||
.filter(|x| x.0 == *generic_idx)
|
||||
.map(|x| x.1)
|
||||
.collect();
|
||||
let check_for_matched_generics = check_for_matched_generics();
|
||||
|
||||
let all_param_idents: Vec<String> = matched_params
|
||||
for (idx, (generic_param, param)) in
|
||||
params_with_generics.iter().enumerate().filter(|(idx, _)| {
|
||||
check_for_matched_generics
|
||||
|| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)
|
||||
})
|
||||
{
|
||||
let Some(generic_param) = generic_param else {
|
||||
spans.push_span_label(param.span, "");
|
||||
continue;
|
||||
};
|
||||
|
||||
let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(other_idx, (other_generic_param, _))| {
|
||||
if *other_idx == idx {
|
||||
return false;
|
||||
}
|
||||
let Some(other_generic_param) = other_generic_param else {
|
||||
return false;
|
||||
};
|
||||
if matched_inputs[idx.into()].is_none()
|
||||
&& matched_inputs[(*other_idx).into()].is_none()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if matched_inputs[idx.into()].is_some()
|
||||
&& matched_inputs[(*other_idx).into()].is_some()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
other_generic_param.name.ident() == generic_param.name.ident()
|
||||
})
|
||||
.map(|(other_idx, (_, other_param))| (other_idx, *other_param))
|
||||
.collect();
|
||||
|
||||
if !other_params_matched.is_empty() {
|
||||
let other_param_matched_names: Vec<String> = other_params_matched
|
||||
.iter()
|
||||
.map(|x| &x.1)
|
||||
.chain(unmatched_params.iter())
|
||||
.map(|x| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind {
|
||||
.map(|(_, other_param)| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = other_param.pat.kind {
|
||||
format!("`{ident}`")
|
||||
} else {
|
||||
"{unknown}".to_string()
|
||||
@ -2321,83 +2262,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
spans.push_span_label(
|
||||
generic.span,
|
||||
format!(
|
||||
"{} all reference this parameter {}",
|
||||
display_list_with_comma_and(&all_param_idents),
|
||||
generic.name.ident().name,
|
||||
),
|
||||
);
|
||||
|
||||
for unmatched_param in &unmatched_params {
|
||||
let idents: Vec<String> = matched_params
|
||||
.iter()
|
||||
.map(|x| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = x.1.pat.kind {
|
||||
format!("`{ident}`")
|
||||
} else {
|
||||
"{unknown}".to_string()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let matched_ty = matched_params
|
||||
.iter()
|
||||
.next()
|
||||
.map(|x| formal_and_expected_inputs[x.0.into()]);
|
||||
|
||||
if let Some(matched_ty) = matched_ty {
|
||||
let matched_ty =
|
||||
self.resolve_vars_if_possible(matched_ty.0).sort_string(self.tcx);
|
||||
spans.push_span_label(
|
||||
unmatched_param.span,
|
||||
format!(
|
||||
"this parameter needs to match the {} type of {}",
|
||||
matched_ty,
|
||||
display_list_with_comma_and(&idents)
|
||||
),
|
||||
);
|
||||
} else {
|
||||
spans.push_span_label(
|
||||
unmatched_param.span,
|
||||
format!(
|
||||
"this parameter needs to match the type of {}",
|
||||
display_list_with_comma_and(&idents)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for matched_param in &matched_params {
|
||||
let idents: Vec<String> = unmatched_params
|
||||
.iter()
|
||||
.map(|x| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind {
|
||||
format!("`{ident}`")
|
||||
} else {
|
||||
"{unknown}".to_string()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let matched_ty = self
|
||||
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
|
||||
.sort_string(self.tcx);
|
||||
|
||||
if matched_inputs[idx.into()].is_some() {
|
||||
spans.push_span_label(
|
||||
matched_param.1.span,
|
||||
param.span,
|
||||
format!(
|
||||
"{} needs to match the type of this parameter",
|
||||
display_list_with_comma_and(&idents)
|
||||
"{} {} to match the {} type of this parameter",
|
||||
display_list_with_comma_and(&other_param_matched_names),
|
||||
format!(
|
||||
"need{}",
|
||||
pluralize!(if other_param_matched_names.len() == 1 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
})
|
||||
),
|
||||
matched_ty,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
spans.push_span_label(
|
||||
param.span,
|
||||
format!(
|
||||
"this parameter needs to match the {} type of {}",
|
||||
matched_ty,
|
||||
display_list_with_comma_and(&other_param_matched_names),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (_, param) in params.iter().enumerate().filter(|(idx, _)| {
|
||||
expected_idx.map_or(true, |expected_idx| expected_idx == *idx)
|
||||
}) {
|
||||
generics_with_unmatched_params.push(generic_param);
|
||||
} else {
|
||||
spans.push_span_label(param.span, "");
|
||||
}
|
||||
}
|
||||
|
||||
for generic_param in self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.generics())
|
||||
.into_iter()
|
||||
.flat_map(|x| x.params)
|
||||
.filter(|x| {
|
||||
generics_with_unmatched_params.iter().any(|y| x.name.ident() == y.name.ident())
|
||||
})
|
||||
{
|
||||
let param_idents_matching: Vec<String> = params_with_generics
|
||||
.iter()
|
||||
.filter(|(generic, _)| {
|
||||
if let Some(generic) = generic {
|
||||
generic.name.ident() == generic_param.name.ident()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.map(|(_, param)| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind {
|
||||
format!("`{ident}`")
|
||||
} else {
|
||||
"{unknown}".to_string()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !param_idents_matching.is_empty() {
|
||||
spans.push_span_label(
|
||||
generic_param.span,
|
||||
format!(
|
||||
"{} all reference this parameter {}",
|
||||
display_list_with_comma_and(¶m_idents_matching),
|
||||
generic_param.name.ident().name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
|
||||
} else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
|
||||
&& let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
|
||||
@ -2464,115 +2406,112 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
fn label_generic_mismatches(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
err: &mut Diag<'_>,
|
||||
callable_def_id: Option<DefId>,
|
||||
matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
|
||||
provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
|
||||
formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
is_method: bool,
|
||||
) {
|
||||
let Some(def_id) = callable_def_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (matched_idx, matched_arg) in matched_inputs.iter_enumerated() {
|
||||
let Some(matched_input) = matched_arg else {
|
||||
let params_with_generics = self.get_hir_params_with_generics(def_id, is_method);
|
||||
|
||||
for (idx, (generic_param, _)) in params_with_generics.iter().enumerate() {
|
||||
if matched_inputs[idx.into()].is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.into()) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let (_, matched_arg_span) = provided_arg_tys[*matched_input];
|
||||
let (matched_formal_ty, _) = formal_and_expected_inputs[matched_idx];
|
||||
let ty::Infer(ty::TyVar(a)) = matched_formal_ty.kind() else {
|
||||
let Some(generic_param) = generic_param else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut formal_ty_idxs_matched: Vec<usize> = vec![];
|
||||
let mut expected_ty_matched = None;
|
||||
for (input_idx, (formal_ty, expected_ty)) in formal_and_expected_inputs
|
||||
.iter_enumerated()
|
||||
// Only care about args after the matched one we're checking.
|
||||
//
|
||||
// NB: Incompatible should always come after their matching generics.
|
||||
// e.g. if we have a function fn f(a: T, b: T, c: T) and we call it with
|
||||
// f(1, 2, 3.0) then the first will force T to be an integer, the second
|
||||
// then matches and the third is the incompatible argument.
|
||||
.filter(|(idx, _)| *idx > matched_idx)
|
||||
{
|
||||
if let ty::Infer(ty::TyVar(b)) = formal_ty.kind() {
|
||||
if self.root_var(*a) == self.root_var(*b) {
|
||||
formal_ty_idxs_matched.push(input_idx.into());
|
||||
if expected_ty_matched.is_none() {
|
||||
expected_ty_matched = Some(expected_ty);
|
||||
}
|
||||
let mut idxs_matched: Vec<usize> = vec![];
|
||||
for (other_idx, (_, _)) in params_with_generics.iter().enumerate().filter(
|
||||
|(other_idx, (other_generic_param, _))| {
|
||||
if *other_idx == idx {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let Some(other_generic_param) = other_generic_param else {
|
||||
return false;
|
||||
};
|
||||
if matched_inputs[(*other_idx).into()].is_some() {
|
||||
return false;
|
||||
}
|
||||
other_generic_param.name.ident() == generic_param.name.ident()
|
||||
},
|
||||
) {
|
||||
idxs_matched.push(other_idx.into());
|
||||
}
|
||||
|
||||
let Some(expected_ty) = expected_ty_matched else {
|
||||
if idxs_matched.is_empty() {
|
||||
continue;
|
||||
};
|
||||
|
||||
let params = self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.body_id())
|
||||
.into_iter()
|
||||
.flat_map(|id| self.tcx.hir().body(id).params);
|
||||
|
||||
let mut all_pats_matched: Vec<String> = vec![];
|
||||
let mut incompatible_pats_matched: Vec<String> = vec![];
|
||||
for (idx, param) in params
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.filter(|(idx, _)| formal_ty_idxs_matched.contains(idx))
|
||||
{
|
||||
let ident = if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind {
|
||||
format!("`{ident}`")
|
||||
} else {
|
||||
format!("`idx:{idx}`")
|
||||
};
|
||||
if matched_inputs[idx.into()].is_none() {
|
||||
incompatible_pats_matched.push(ident.clone());
|
||||
}
|
||||
all_pats_matched.push(ident);
|
||||
}
|
||||
|
||||
let expected_display_type =
|
||||
self.resolve_vars_if_possible(*expected_ty).sort_string(self.tcx);
|
||||
let label = if all_pats_matched.len() == 0 {
|
||||
let expected_display_type = self
|
||||
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
|
||||
.sort_string(self.tcx);
|
||||
let label = if idxs_matched.len() == params_with_generics.len() - 1 {
|
||||
format!(
|
||||
"expected all arguments to be {} because they need to match the type of this parameter",
|
||||
"expected all arguments to be this {} type because they need to match the type of this parameter",
|
||||
expected_display_type
|
||||
)
|
||||
} else if all_pats_matched.len() == incompatible_pats_matched.len() {
|
||||
format!(
|
||||
"expected {} {} to be {} {} because {} to match the type of this parameter",
|
||||
format!("argument{}", pluralize!(incompatible_pats_matched.len())),
|
||||
display_list_with_comma_and(&incompatible_pats_matched),
|
||||
a_or_an(&expected_display_type),
|
||||
expected_display_type,
|
||||
if all_pats_matched.len() == 1 {
|
||||
"that argument needs"
|
||||
} else {
|
||||
"those arguments need"
|
||||
}
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"expected {} {} to be {} {} because the {} {} {} to match the type of this parameter",
|
||||
format!("argument{}", pluralize!(incompatible_pats_matched.len())),
|
||||
display_list_with_comma_and(&incompatible_pats_matched),
|
||||
"expected some other arguments to be {} {} type to match the type of this parameter",
|
||||
a_or_an(&expected_display_type),
|
||||
expected_display_type,
|
||||
format!("argument{}", pluralize!(all_pats_matched.len())),
|
||||
display_list_with_comma_and(&all_pats_matched),
|
||||
format!("need{}", pluralize!(if all_pats_matched.len() == 1 { 0 } else { 1 })),
|
||||
)
|
||||
};
|
||||
|
||||
err.span_label(matched_arg_span, label);
|
||||
err.span_label(*matched_arg_span, label);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_hir_params_with_generics(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
is_method: bool,
|
||||
) -> Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)> {
|
||||
let fn_node = self.tcx.hir().get_if_local(def_id);
|
||||
|
||||
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_node
|
||||
.and_then(|node| node.fn_decl())
|
||||
.into_iter()
|
||||
.flat_map(|decl| decl.inputs)
|
||||
.skip(if is_method { 1 } else { 0 })
|
||||
.map(|param| {
|
||||
if let hir::TyKind::Path(QPath::Resolved(
|
||||
_,
|
||||
hir::Path { res: Res::Def(_, res_def_id), .. },
|
||||
)) = param.kind
|
||||
{
|
||||
fn_node
|
||||
.and_then(|node| node.generics())
|
||||
.into_iter()
|
||||
.flat_map(|generics| generics.params)
|
||||
.find(|gen| &gen.def_id.to_def_id() == res_def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let params: Vec<&hir::Param<'_>> = fn_node
|
||||
.and_then(|node| node.body_id())
|
||||
.into_iter()
|
||||
.flat_map(|id| self.tcx.hir().body(id).params)
|
||||
.skip(if is_method { 1 } else { 0 })
|
||||
.collect();
|
||||
|
||||
generic_params.into_iter().zip(params).collect()
|
||||
}
|
||||
}
|
||||
|
||||
struct FindClosureArg<'tcx> {
|
||||
|
@ -39,39 +39,6 @@ macro_rules! pluralize {
|
||||
};
|
||||
}
|
||||
|
||||
/// Grammatical tool for displaying messages to end users in a nice form.
|
||||
///
|
||||
/// Returns "an" if the given string starts with a vowel, and "a" otherwise.
|
||||
pub fn a_or_an(s: &str) -> &'static str {
|
||||
let mut chars = s.chars();
|
||||
let Some(mut first_alpha_char) = chars.next() else {
|
||||
return "a";
|
||||
};
|
||||
if first_alpha_char == '`' {
|
||||
let Some(next) = chars.next() else {
|
||||
return "a";
|
||||
};
|
||||
first_alpha_char = next;
|
||||
}
|
||||
if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
|
||||
"an"
|
||||
} else {
|
||||
"a"
|
||||
}
|
||||
}
|
||||
|
||||
/// Grammatical tool for displaying messages to end users in a nice form.
|
||||
///
|
||||
/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c"
|
||||
pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
|
||||
match v.len() {
|
||||
0 => "".to_string(),
|
||||
1 => v[0].to_string(),
|
||||
2 => format!("{} and {}", v[0], v[1]),
|
||||
_ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])),
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates the confidence in the correctness of a suggestion.
|
||||
///
|
||||
/// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion
|
||||
|
@ -45,7 +45,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> $DIR/extra_arguments.rs:23:3
|
||||
@ -60,7 +60,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
|
||||
error[E0061]: this function takes 1 argument but 3 arguments were supplied
|
||||
--> $DIR/extra_arguments.rs:24:3
|
||||
@ -74,7 +74,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
help: remove the extra arguments
|
||||
|
|
||||
LL - one_arg(1, "", 1.0);
|
||||
@ -319,7 +319,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> $DIR/extra_arguments.rs:54:3
|
||||
@ -334,7 +334,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> $DIR/extra_arguments.rs:55:3
|
||||
@ -349,7 +349,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> $DIR/extra_arguments.rs:60:3
|
||||
@ -364,7 +364,7 @@ note: function defined here
|
||||
--> $DIR/extra_arguments.rs:2:4
|
||||
|
|
||||
LL | fn one_arg<T>(_a: T) {}
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^ -----
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
|
||||
|
@ -24,7 +24,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:6:4
|
||||
|
|
||||
LL | fn two_arg_same(_a: i32, _b: i32) {}
|
||||
| ^^^^^^^^^^^^ ------- -------
|
||||
| ^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid_arguments.rs:17:16
|
||||
@ -38,7 +38,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:6:4
|
||||
|
|
||||
LL | fn two_arg_same(_a: i32, _b: i32) {}
|
||||
| ^^^^^^^^^^^^ ------- -------
|
||||
| ^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/invalid_arguments.rs:18:3
|
||||
@ -66,7 +66,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:7:4
|
||||
|
|
||||
LL | fn two_arg_diff(_a: i32, _b: f32) {}
|
||||
| ^^^^^^^^^^^^ ------- -------
|
||||
| ^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid_arguments.rs:20:16
|
||||
@ -80,7 +80,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:7:4
|
||||
|
|
||||
LL | fn two_arg_diff(_a: i32, _b: f32) {}
|
||||
| ^^^^^^^^^^^^ ------- -------
|
||||
| ^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/invalid_arguments.rs:21:3
|
||||
@ -108,7 +108,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:8:4
|
||||
|
|
||||
LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
|
||||
| ^^^^^^^^^^^^^^ ------- ------- --------
|
||||
| ^^^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid_arguments.rs:25:21
|
||||
@ -122,7 +122,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:8:4
|
||||
|
|
||||
LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
|
||||
| ^^^^^^^^^^^^^^ ------- ------- --------
|
||||
| ^^^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid_arguments.rs:26:26
|
||||
@ -136,7 +136,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:8:4
|
||||
|
|
||||
LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
|
||||
| ^^^^^^^^^^^^^^ ------- ------- --------
|
||||
| ^^^^^^^^^^^^^^ --------
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/invalid_arguments.rs:28:3
|
||||
@ -207,7 +207,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:9:4
|
||||
|
|
||||
LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
|
||||
| ^^^^^^^^^^^^^^^^ ------- ------- --------
|
||||
| ^^^^^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid_arguments.rs:35:23
|
||||
@ -221,7 +221,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:9:4
|
||||
|
|
||||
LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
|
||||
| ^^^^^^^^^^^^^^^^ ------- ------- --------
|
||||
| ^^^^^^^^^^^^^^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/invalid_arguments.rs:36:26
|
||||
@ -235,7 +235,7 @@ note: function defined here
|
||||
--> $DIR/invalid_arguments.rs:9:4
|
||||
|
|
||||
LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
|
||||
| ^^^^^^^^^^^^^^^^ ------- ------- --------
|
||||
| ^^^^^^^^^^^^^^^^ --------
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/invalid_arguments.rs:38:3
|
||||
|
@ -11,31 +11,9 @@ note: method defined here
|
||||
|
|
||||
LL | fn foo(
|
||||
| ^^^
|
||||
LL | &self,
|
||||
LL | a: i32,
|
||||
| ------
|
||||
LL | b: i32,
|
||||
| ------
|
||||
LL | c: i32,
|
||||
| ------
|
||||
LL | d: i32,
|
||||
| ------
|
||||
LL | e: i32,
|
||||
| ------
|
||||
...
|
||||
LL | f: i32,
|
||||
| ------
|
||||
LL | g: i32,
|
||||
| ------
|
||||
LL | h: i32,
|
||||
| ------
|
||||
LL | i: i32,
|
||||
| ------
|
||||
LL | j: i32,
|
||||
| ------
|
||||
LL | k: i32,
|
||||
| ------
|
||||
LL | l: i32,
|
||||
| ------
|
||||
help: consider dereferencing the borrow
|
||||
|
|
||||
LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l);
|
||||
|
@ -5,7 +5,7 @@ LL | fun(async {}, async {});
|
||||
| --- -------- ^^^^^^^^ expected `async` block, found a different `async` block
|
||||
| | |
|
||||
| | the expected `async` block
|
||||
| | expected argument `f2` to be an `async` block because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this `async` block type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}`
|
||||
@ -14,10 +14,9 @@ note: function defined here
|
||||
--> $DIR/coroutine-desc.rs:8:4
|
||||
|
|
||||
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
|
||||
| ^^^ - ----- -----
|
||||
| | | |
|
||||
| | | this parameter needs to match the `async` block type of `f1`
|
||||
| | `f2` needs to match the type of this parameter
|
||||
| ^^^ - ----- ----- this parameter needs to match the `async` block type of `f1`
|
||||
| | |
|
||||
| | `f2` needs to match the `async` block type of this parameter
|
||||
| `f1` and `f2` all reference this parameter F
|
||||
|
||||
error[E0308]: mismatched types
|
||||
@ -26,7 +25,7 @@ error[E0308]: mismatched types
|
||||
LL | fun(one(), two());
|
||||
| --- ----- ^^^^^ expected future, found a different future
|
||||
| | |
|
||||
| | expected argument `f2` to be a future because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this future type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= help: consider `await`ing on both `Future`s
|
||||
@ -35,10 +34,9 @@ note: function defined here
|
||||
--> $DIR/coroutine-desc.rs:8:4
|
||||
|
|
||||
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
|
||||
| ^^^ - ----- -----
|
||||
| | | |
|
||||
| | | this parameter needs to match the future type of `f1`
|
||||
| | `f2` needs to match the type of this parameter
|
||||
| ^^^ - ----- ----- this parameter needs to match the future type of `f1`
|
||||
| | |
|
||||
| | `f2` needs to match the future type of this parameter
|
||||
| `f1` and `f2` all reference this parameter F
|
||||
|
||||
error[E0308]: mismatched types
|
||||
@ -48,7 +46,7 @@ LL | fun((async || {})(), (async || {})());
|
||||
| --- --------------- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
|
||||
| | | |
|
||||
| | | the expected `async` closure body
|
||||
| | expected argument `f2` to be an `async` closure body because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this `async` closure body type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:19: 14:21}`
|
||||
@ -57,10 +55,9 @@ note: function defined here
|
||||
--> $DIR/coroutine-desc.rs:8:4
|
||||
|
|
||||
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
|
||||
| ^^^ - ----- -----
|
||||
| | | |
|
||||
| | | this parameter needs to match the `async` closure body type of `f1`
|
||||
| | `f2` needs to match the type of this parameter
|
||||
| ^^^ - ----- ----- this parameter needs to match the `async` closure body type of `f1`
|
||||
| | |
|
||||
| | `f2` needs to match the `async` closure body type of this parameter
|
||||
| `f1` and `f2` all reference this parameter F
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -4,7 +4,7 @@ error[E0308]: mismatched types
|
||||
LL | test(&mut 7, &7);
|
||||
| ---- ------ ^^ types differ in mutability
|
||||
| | |
|
||||
| | expected argument `_b` to be an `&mut {integer}` because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this `&mut {integer}` type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected mutable reference `&mut {integer}`
|
||||
@ -13,10 +13,9 @@ note: function defined here
|
||||
--> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4
|
||||
|
|
||||
LL | fn test<T>(_a: T, _b: T) {}
|
||||
| ^^^^ - ----- -----
|
||||
| | | |
|
||||
| | | this parameter needs to match the `&mut {integer}` type of `_a`
|
||||
| | `_b` needs to match the type of this parameter
|
||||
| ^^^^ - ----- ----- this parameter needs to match the `&mut {integer}` type of `_a`
|
||||
| | |
|
||||
| | `_b` needs to match the `&mut {integer}` type of this parameter
|
||||
| `_a` and `_b` all reference this parameter T
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -12,7 +12,7 @@ note: function defined here
|
||||
--> $DIR/coerce-to-bang.rs:3:4
|
||||
|
|
||||
LL | fn foo(x: usize, y: !, z: usize) { }
|
||||
| ^^^ -------- ---- --------
|
||||
| ^^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-to-bang.rs:18:13
|
||||
@ -28,7 +28,7 @@ note: function defined here
|
||||
--> $DIR/coerce-to-bang.rs:3:4
|
||||
|
|
||||
LL | fn foo(x: usize, y: !, z: usize) { }
|
||||
| ^^^ -------- ---- --------
|
||||
| ^^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-to-bang.rs:26:12
|
||||
@ -44,7 +44,7 @@ note: function defined here
|
||||
--> $DIR/coerce-to-bang.rs:3:4
|
||||
|
|
||||
LL | fn foo(x: usize, y: !, z: usize) { }
|
||||
| ^^^ -------- ---- --------
|
||||
| ^^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-to-bang.rs:36:12
|
||||
@ -60,7 +60,7 @@ note: function defined here
|
||||
--> $DIR/coerce-to-bang.rs:3:4
|
||||
|
|
||||
LL | fn foo(x: usize, y: !, z: usize) { }
|
||||
| ^^^ -------- ---- --------
|
||||
| ^^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-to-bang.rs:45:12
|
||||
@ -76,7 +76,7 @@ note: function defined here
|
||||
--> $DIR/coerce-to-bang.rs:3:4
|
||||
|
|
||||
LL | fn foo(x: usize, y: !, z: usize) { }
|
||||
| ^^^ -------- ---- --------
|
||||
| ^^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-to-bang.rs:50:21
|
||||
|
@ -4,7 +4,7 @@ error[E0308]: mismatched types
|
||||
LL | eq(foo::<u8>, bar::<u8>);
|
||||
| -- --------- ^^^^^^^^^ expected fn item, found a different fn item
|
||||
| | |
|
||||
| | expected argument `y` to be a fn item because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this fn item type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
@ -14,10 +14,9 @@ note: function defined here
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ - ---- ----
|
||||
| | | |
|
||||
| | | this parameter needs to match the fn item type of `x`
|
||||
| | `y` needs to match the type of this parameter
|
||||
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
|
||||
| | |
|
||||
| | `y` needs to match the fn item type of this parameter
|
||||
| `x` and `y` all reference this parameter T
|
||||
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
|
||||
|
||||
@ -27,7 +26,7 @@ error[E0308]: mismatched types
|
||||
LL | eq(foo::<u8>, foo::<i8>);
|
||||
| -- --------- ^^^^^^^^^ expected `u8`, found `i8`
|
||||
| | |
|
||||
| | expected argument `y` to be a fn item because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this fn item type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
@ -37,10 +36,9 @@ note: function defined here
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ - ---- ----
|
||||
| | | |
|
||||
| | | this parameter needs to match the fn item type of `x`
|
||||
| | `y` needs to match the type of this parameter
|
||||
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
|
||||
| | |
|
||||
| | `y` needs to match the fn item type of this parameter
|
||||
| `x` and `y` all reference this parameter T
|
||||
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
|
||||
|
||||
@ -50,7 +48,7 @@ error[E0308]: mismatched types
|
||||
LL | eq(bar::<String>, bar::<Vec<u8>>);
|
||||
| -- ------------- ^^^^^^^^^^^^^^ expected `String`, found `Vec<u8>`
|
||||
| | |
|
||||
| | expected argument `y` to be a fn item because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this fn item type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {bar::<String>}`
|
||||
@ -60,10 +58,9 @@ note: function defined here
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ - ---- ----
|
||||
| | | |
|
||||
| | | this parameter needs to match the fn item type of `x`
|
||||
| | `y` needs to match the type of this parameter
|
||||
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
|
||||
| | |
|
||||
| | `y` needs to match the fn item type of this parameter
|
||||
| `x` and `y` all reference this parameter T
|
||||
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
|
||||
|
||||
@ -73,7 +70,7 @@ error[E0308]: mismatched types
|
||||
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
| -- ---------------- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
|
||||
| | |
|
||||
| | expected argument `y` to be a fn item because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this fn item type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn item `fn() {<u8 as Foo>::foo}`
|
||||
@ -83,10 +80,9 @@ note: function defined here
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ - ---- ----
|
||||
| | | |
|
||||
| | | this parameter needs to match the fn item type of `x`
|
||||
| | `y` needs to match the type of this parameter
|
||||
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
|
||||
| | |
|
||||
| | `y` needs to match the fn item type of this parameter
|
||||
| `x` and `y` all reference this parameter T
|
||||
= help: consider casting both fn items to fn pointers using `as fn()`
|
||||
|
||||
@ -96,7 +92,7 @@ error[E0308]: mismatched types
|
||||
LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
||||
| -- --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
|
||||
| | |
|
||||
| | expected argument `y` to be a fn item because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this fn item type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
@ -106,10 +102,9 @@ note: function defined here
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ - ---- ----
|
||||
| | | |
|
||||
| | | this parameter needs to match the fn item type of `x`
|
||||
| | `y` needs to match the type of this parameter
|
||||
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
|
||||
| | |
|
||||
| | `y` needs to match the fn item type of this parameter
|
||||
| `x` and `y` all reference this parameter T
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
@ -9,4 +9,6 @@ fn main() {
|
||||
//~^ ERROR arguments to this function are incorrect
|
||||
foo_multi_generics("a", "b", "c", true, false, 32, 2.);
|
||||
//~^ ERROR arguments to this function are incorrect
|
||||
foo_multi_same("a", 1, 2, "d", "e", 32);
|
||||
//~^ ERROR arguments to this function are incorrect
|
||||
}
|
||||
|
@ -4,17 +4,16 @@ error[E0308]: mismatched types
|
||||
LL | foo(1, 2.);
|
||||
| --- - ^^ expected integer, found floating-point number
|
||||
| | |
|
||||
| | expected argument `b` to be an integer because that argument needs to match the type of this parameter
|
||||
| | expected all arguments to be this integer type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/generic-mismatch-reporting-issue-116615.rs:1:4
|
||||
|
|
||||
LL | fn foo<T>(a: T, b: T) {}
|
||||
| ^^^ - ---- ----
|
||||
| | | |
|
||||
| | | this parameter needs to match the integer type of `a`
|
||||
| | `b` needs to match the type of this parameter
|
||||
| ^^^ - ---- ---- this parameter needs to match the integer type of `a`
|
||||
| | |
|
||||
| | `b` needs to match the integer type of this parameter
|
||||
| `a` and `b` all reference this parameter T
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
@ -25,8 +24,8 @@ LL | foo_multi_same("a", "b", false, true, (), 32);
|
||||
| | | | |
|
||||
| | | | expected `&str`, found `bool`
|
||||
| | | expected `&str`, found `bool`
|
||||
| | expected arguments `c`, `d` and `e` to be an `&str` because those arguments need to match the type of this parameter
|
||||
| expected arguments `c`, `d` and `e` to be an `&str` because the arguments `b`, `c`, `d` and `e` need to match the type of this parameter
|
||||
| | expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
| expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/generic-mismatch-reporting-issue-116615.rs:2:4
|
||||
@ -37,8 +36,8 @@ LL | fn foo_multi_same<T>(a: T, b: T, c: T, d: T, e: T, f: i32) {}
|
||||
| | | | | | this parameter needs to match the `&str` type of `a` and `b`
|
||||
| | | | | this parameter needs to match the `&str` type of `a` and `b`
|
||||
| | | | this parameter needs to match the `&str` type of `a` and `b`
|
||||
| | | `c`, `d` and `e` needs to match the type of this parameter
|
||||
| | `c`, `d` and `e` needs to match the type of this parameter
|
||||
| | | `c`, `d` and `e` need to match the `&str` type of this parameter
|
||||
| | `c`, `d` and `e` need to match the `&str` type of this parameter
|
||||
| `a`, `b`, `c`, `d` and `e` all reference this parameter T
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
@ -47,29 +46,52 @@ error[E0308]: arguments to this function are incorrect
|
||||
LL | foo_multi_generics("a", "b", "c", true, false, 32, 2.);
|
||||
| ^^^^^^^^^^^^^^^^^^ --- --- --- ---- ----- -- -- expected integer, found floating-point number
|
||||
| | | | | | |
|
||||
| | | | | | expected argument `g` to be an integer because that argument needs to match the type of this parameter
|
||||
| | | | | | expected some other arguments to be an integer type to match the type of this parameter
|
||||
| | | | | expected `&str`, found `bool`
|
||||
| | | | expected `&str`, found `bool`
|
||||
| | | expected arguments `d` and `e` to be an `&str` because those arguments need to match the type of this parameter
|
||||
| | expected arguments `d` and `e` to be an `&str` because the arguments `c`, `d` and `e` need to match the type of this parameter
|
||||
| expected arguments `d` and `e` to be an `&str` because the arguments `b`, `c`, `d` and `e` need to match the type of this parameter
|
||||
| | | expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
| | expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
| expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/generic-mismatch-reporting-issue-116615.rs:3:4
|
||||
|
|
||||
LL | fn foo_multi_generics<S, T>(a: T, b: T, c: T, d: T, e: T, f: S, g: S) {}
|
||||
| ^^^^^^^^^^^^^^^^^^ - - ---- ---- ---- ---- ---- ---- ----
|
||||
| | | | | | | | | |
|
||||
| | | | | | | | | this parameter needs to match the integer type of `f`
|
||||
| | | | | | | | `g` needs to match the type of this parameter
|
||||
| ^^^^^^^^^^^^^^^^^^ - - ---- ---- ---- ---- ---- ---- ---- this parameter needs to match the integer type of `f`
|
||||
| | | | | | | | |
|
||||
| | | | | | | | `g` needs to match the integer type of this parameter
|
||||
| | | | | | | this parameter needs to match the `&str` type of `a`, `b` and `c`
|
||||
| | | | | | this parameter needs to match the `&str` type of `a`, `b` and `c`
|
||||
| | | | | `d` and `e` needs to match the type of this parameter
|
||||
| | | | `d` and `e` needs to match the type of this parameter
|
||||
| | | `d` and `e` needs to match the type of this parameter
|
||||
| | | | | `d` and `e` need to match the `&str` type of this parameter
|
||||
| | | | `d` and `e` need to match the `&str` type of this parameter
|
||||
| | | `d` and `e` need to match the `&str` type of this parameter
|
||||
| | `a`, `b`, `c`, `d` and `e` all reference this parameter T
|
||||
| `f` and `g` all reference this parameter S
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/generic-mismatch-reporting-issue-116615.rs:12:5
|
||||
|
|
||||
LL | foo_multi_same("a", 1, 2, "d", "e", 32);
|
||||
| ^^^^^^^^^^^^^^ --- - - --- --- expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
| | | | |
|
||||
| | | | expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
| | | expected `&str`, found integer
|
||||
| | expected `&str`, found integer
|
||||
| expected some other arguments to be an `&str` type to match the type of this parameter
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/generic-mismatch-reporting-issue-116615.rs:2:4
|
||||
|
|
||||
LL | fn foo_multi_same<T>(a: T, b: T, c: T, d: T, e: T, f: i32) {}
|
||||
| ^^^^^^^^^^^^^^ - ---- ---- ---- ---- ---- ------
|
||||
| | | | | | |
|
||||
| | | | | | `b` and `c` need to match the `&str` type of this parameter
|
||||
| | | | | `b` and `c` need to match the `&str` type of this parameter
|
||||
| | | | this parameter needs to match the `&str` type of `a`, `d` and `e`
|
||||
| | | this parameter needs to match the `&str` type of `a`, `d` and `e`
|
||||
| | `b` and `c` need to match the `&str` type of this parameter
|
||||
| `a`, `b`, `c`, `d` and `e` all reference this parameter T
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -21,7 +21,6 @@ LL | 0.....{loop{}1};
|
||||
| | |
|
||||
| | expected integer, found `RangeTo<{integer}>`
|
||||
| arguments to this function are incorrect
|
||||
| expected all arguments to be integer because they need to match the type of this parameter
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found struct `RangeTo<{integer}>`
|
||||
|
@ -43,7 +43,7 @@ note: function defined here
|
||||
--> $DIR/issue-93282.rs:7:4
|
||||
|
|
||||
LL | fn bar(a: usize, b: usize) -> usize {
|
||||
| ^^^ -------- --------
|
||||
| ^^^ --------
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -77,7 +77,7 @@ note: function defined here
|
||||
--> $DIR/issue-34264.rs:3:4
|
||||
|
|
||||
LL | fn bar(x, y: usize) {}
|
||||
| ^^^ - --------
|
||||
| ^^^ --------
|
||||
|
||||
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
|
||||
--> $DIR/issue-34264.rs:10:5
|
||||
|
@ -8,7 +8,7 @@ note: function defined here
|
||||
--> $DIR/add-tuple-within-arguments.rs:1:4
|
||||
|
|
||||
LL | fn foo(s: &str, a: (i32, i32), s2: &str) {}
|
||||
| ^^^ ------- ------------- --------
|
||||
| ^^^ -------------
|
||||
help: wrap these arguments in parentheses to construct a tuple
|
||||
|
|
||||
LL | foo("hi", (1, 2), "hi");
|
||||
@ -28,7 +28,7 @@ note: function defined here
|
||||
--> $DIR/add-tuple-within-arguments.rs:3:4
|
||||
|
|
||||
LL | fn bar(s: &str, a: (&str,), s2: &str) {}
|
||||
| ^^^ ------- ---------- --------
|
||||
| ^^^ ----------
|
||||
help: use a trailing comma to create a tuple with one element
|
||||
|
|
||||
LL | bar("hi", ("hi",), "hi");
|
||||
|
@ -74,7 +74,7 @@ note: function defined here
|
||||
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
|
||||
|
|
||||
LL | fn function<T>(x: T, y: bool) -> T {
|
||||
| ^^^^^^^^ ---- -------
|
||||
| ^^^^^^^^ ----
|
||||
help: change the type of the numeric literal from `u32` to `u16`
|
||||
|
|
||||
LL | let x: u16 = function(0u16, true);
|
||||
|
Loading…
Reference in New Issue
Block a user