Rollup merge of #136497 - Jarcho:fn_ctxt, r=compiler-errors
Report generic mismatches when calling bodyless trait functions Don't know if there's an open issue for this. Just happened to notice this when working in that area. The awkward extra spans added to the diagnostics of some tests (e.g. `trait-with-missing-associated-type-restriction`) is consistent with what happens for normal functions. Should probably be removed since that span doesn't seem to note anything useful. First and third commit are both cleanups removing some unnecessary work. Second commit has the actual fix. fixes #135124
This commit is contained in:
commit
29e1dddd83
9 changed files with 243 additions and 124 deletions
|
@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath};
|
|||
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
|
||||
use rustc_hir_analysis::check::potentially_plural_count;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
|
@ -21,7 +21,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
|
|||
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
|
||||
|
@ -126,7 +126,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Err(guar) => Err(guar),
|
||||
};
|
||||
if let Err(guar) = has_error {
|
||||
let err_inputs = self.err_args(args_no_rcvr.len(), guar);
|
||||
let err_inputs = self.err_args(
|
||||
method.map_or(args_no_rcvr.len(), |method| method.sig.inputs().len() - 1),
|
||||
guar,
|
||||
);
|
||||
let err_output = Ty::new_error(self.tcx, guar);
|
||||
|
||||
let err_inputs = match tuple_arguments {
|
||||
|
@ -2374,11 +2377,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let check_for_matched_generics = || {
|
||||
if matched_inputs.iter().any(|x| x.is_some())
|
||||
&& params_with_generics.iter().any(|x| x.1.is_some())
|
||||
&& params_with_generics.iter().any(|(x, _)| x.is_some())
|
||||
{
|
||||
for &(idx, generic, _) in ¶ms_with_generics {
|
||||
for (idx, (generic, _)) in params_with_generics.iter_enumerated() {
|
||||
// Param has to have a generic and be matched to be relevant
|
||||
if matched_inputs[idx.into()].is_none() {
|
||||
if matched_inputs[idx].is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2386,10 +2389,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
continue;
|
||||
};
|
||||
|
||||
for unmatching_idx in idx + 1..params_with_generics.len() {
|
||||
if matched_inputs[unmatching_idx.into()].is_none()
|
||||
for unmatching_idx in
|
||||
idx.plus(1)..ExpectedIdx::from_usize(params_with_generics.len())
|
||||
{
|
||||
if matched_inputs[unmatching_idx].is_none()
|
||||
&& let Some(unmatched_idx_param_generic) =
|
||||
params_with_generics[unmatching_idx].1
|
||||
params_with_generics[unmatching_idx].0
|
||||
&& unmatched_idx_param_generic.name.ident()
|
||||
== generic.name.ident()
|
||||
{
|
||||
|
@ -2404,61 +2409,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let check_for_matched_generics = check_for_matched_generics();
|
||||
|
||||
for &(idx, generic_param, param) in
|
||||
params_with_generics.iter().filter(|&(idx, _, _)| {
|
||||
for (idx, &(generic_param, param)) in
|
||||
params_with_generics.iter_enumerated().filter(|&(idx, _)| {
|
||||
check_for_matched_generics
|
||||
|| expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
|
||||
|| expected_idx
|
||||
.is_none_or(|expected_idx| expected_idx == idx.as_usize())
|
||||
})
|
||||
{
|
||||
let Some(generic_param) = generic_param else {
|
||||
spans.push_span_label(param.span, "");
|
||||
spans.push_span_label(param.span(), "");
|
||||
continue;
|
||||
};
|
||||
|
||||
let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics
|
||||
.iter()
|
||||
.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();
|
||||
let other_params_matched: Vec<(ExpectedIdx, FnParam<'_>)> =
|
||||
params_with_generics
|
||||
.iter_enumerated()
|
||||
.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].is_none()
|
||||
&& matched_inputs[other_idx].is_none()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if matched_inputs[idx].is_some()
|
||||
&& matched_inputs[other_idx].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(|(idx, other_param)| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = other_param.pat.kind
|
||||
{
|
||||
format!("`{ident}`")
|
||||
if let Some(name) = other_param.name() {
|
||||
format!("`{name}`")
|
||||
} else {
|
||||
format!("parameter #{}", idx + 1)
|
||||
format!("parameter #{}", idx.as_u32() + 1)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let matched_ty = self
|
||||
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
|
||||
.resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
|
||||
.sort_string(self.tcx);
|
||||
|
||||
if matched_inputs[idx.into()].is_some() {
|
||||
if matched_inputs[idx].is_some() {
|
||||
spans.push_span_label(
|
||||
param.span,
|
||||
param.span(),
|
||||
format!(
|
||||
"{} need{} to match the {} type of this parameter",
|
||||
listify(&other_param_matched_names, |n| n.to_string())
|
||||
|
@ -2473,7 +2479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
} else {
|
||||
spans.push_span_label(
|
||||
param.span,
|
||||
param.span(),
|
||||
format!(
|
||||
"this parameter needs to match the {} type of {}",
|
||||
matched_ty,
|
||||
|
@ -2484,7 +2490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
generics_with_unmatched_params.push(generic_param);
|
||||
} else {
|
||||
spans.push_span_label(param.span, "");
|
||||
spans.push_span_label(param.span(), "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2502,19 +2508,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
})
|
||||
{
|
||||
let param_idents_matching: Vec<String> = params_with_generics
|
||||
.iter()
|
||||
.filter(|(_, generic, _)| {
|
||||
.iter_enumerated()
|
||||
.filter(|&(_, &(generic, _))| {
|
||||
if let Some(generic) = generic {
|
||||
generic.name.ident() == generic_param.name.ident()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.map(|(idx, _, param)| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind {
|
||||
format!("`{ident}`")
|
||||
.map(|(idx, &(_, param))| {
|
||||
if let Some(name) = param.name() {
|
||||
format!("`{name}`")
|
||||
} else {
|
||||
format!("parameter #{}", idx + 1)
|
||||
format!("parameter #{}", idx.as_u32() + 1)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
@ -2607,12 +2613,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method) {
|
||||
debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
|
||||
for &(idx, generic_param, _) in ¶ms_with_generics {
|
||||
if matched_inputs[idx.into()].is_none() {
|
||||
for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
|
||||
if matched_inputs[idx].is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.into()) else {
|
||||
let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -2620,32 +2627,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
continue;
|
||||
};
|
||||
|
||||
let mut idxs_matched: Vec<usize> = vec![];
|
||||
for &(other_idx, _, _) in
|
||||
params_with_generics.iter().filter(|&&(other_idx, other_generic_param, _)| {
|
||||
let idxs_matched = params_with_generics
|
||||
.iter_enumerated()
|
||||
.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() {
|
||||
if matched_inputs[other_idx].is_some() {
|
||||
return false;
|
||||
}
|
||||
other_generic_param.name.ident() == generic_param.name.ident()
|
||||
})
|
||||
{
|
||||
idxs_matched.push(other_idx);
|
||||
}
|
||||
.count();
|
||||
|
||||
if idxs_matched.is_empty() {
|
||||
if idxs_matched == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 {
|
||||
let label = if idxs_matched == params_with_generics.len() - 1 {
|
||||
format!(
|
||||
"expected all arguments to be this {} type because they need to match the type of this parameter",
|
||||
expected_display_type
|
||||
|
@ -2664,62 +2669,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Returns the parameters of a function, with their generic parameters if those are the full
|
||||
/// type of that parameter. Returns `None` if the function body is unavailable (eg is an instrinsic).
|
||||
/// type of that parameter. Returns `None` if the function has no generics or the body is
|
||||
/// unavailable (eg is an instrinsic).
|
||||
fn get_hir_params_with_generics(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
is_method: bool,
|
||||
) -> Option<Vec<(usize, Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
|
||||
let fn_node = self.tcx.hir().get_if_local(def_id)?;
|
||||
let fn_decl = fn_node.fn_decl()?;
|
||||
|
||||
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
|
||||
.inputs
|
||||
.into_iter()
|
||||
.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
|
||||
.generics()
|
||||
.into_iter()
|
||||
.flat_map(|generics| generics.params)
|
||||
.find(|param| ¶m.def_id.to_def_id() == res_def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
) -> Option<IndexVec<ExpectedIdx, (Option<&hir::GenericParam<'_>>, FnParam<'_>)>> {
|
||||
let (sig, generics, body_id, param_names) = match self.tcx.hir().get_if_local(def_id)? {
|
||||
hir::Node::TraitItem(&hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Fn(sig, trait_fn),
|
||||
..
|
||||
}) => match trait_fn {
|
||||
hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
|
||||
hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
|
||||
},
|
||||
hir::Node::ImplItem(&hir::ImplItem {
|
||||
generics,
|
||||
kind: hir::ImplItemKind::Fn(sig, body),
|
||||
..
|
||||
})
|
||||
.collect();
|
||||
| hir::Node::Item(&hir::Item {
|
||||
kind: hir::ItemKind::Fn { sig, generics, body, .. },
|
||||
..
|
||||
}) => (sig, generics, Some(body), None),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let mut params: Vec<&hir::Param<'_>> = self
|
||||
.tcx
|
||||
.hir()
|
||||
.body(fn_node.body_id()?)
|
||||
.params
|
||||
.into_iter()
|
||||
.skip(if is_method { 1 } else { 0 })
|
||||
.collect();
|
||||
|
||||
// The surrounding code expects variadic functions to not have a parameter representing
|
||||
// the "..." parameter. This is already true of the FnDecl but not of the body params, so
|
||||
// we drop it if it exists.
|
||||
|
||||
if fn_decl.c_variadic {
|
||||
params.pop();
|
||||
// Make sure to remove both the receiver and variadic argument. Both are removed
|
||||
// when matching parameter types.
|
||||
let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
|
||||
if let hir::TyKind::Path(QPath::Resolved(
|
||||
_,
|
||||
&hir::Path { res: Res::Def(_, res_def_id), .. },
|
||||
)) = param.kind
|
||||
{
|
||||
generics.params.iter().find(|param| param.def_id.to_def_id() == res_def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
match (body_id, param_names) {
|
||||
(Some(_), Some(_)) | (None, None) => unreachable!(),
|
||||
(Some(body), None) => {
|
||||
let params = self.tcx.hir().body(body).params;
|
||||
let params =
|
||||
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
|
||||
debug_assert_eq!(params.len(), fn_inputs.len());
|
||||
Some(fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect())
|
||||
}
|
||||
(None, Some(params)) => {
|
||||
let params = params.get(is_method as usize..)?;
|
||||
debug_assert_eq!(params.len(), fn_inputs.len());
|
||||
Some(fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect())
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert_eq!(params.len(), generic_params.len());
|
||||
Some(
|
||||
generic_params
|
||||
.into_iter()
|
||||
.zip(params)
|
||||
.enumerate()
|
||||
.map(|(a, (b, c))| (a, b, c))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2742,3 +2747,27 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
|
|||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum FnParam<'hir> {
|
||||
Param(&'hir hir::Param<'hir>),
|
||||
Name(&'hir Ident),
|
||||
}
|
||||
impl FnParam<'_> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Param(x) => x.span,
|
||||
Self::Name(x) => x.span,
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<Symbol> {
|
||||
match self {
|
||||
Self::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => {
|
||||
Some(ident.name)
|
||||
}
|
||||
Self::Name(x) if x.name != kw::Empty => Some(x.name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
//@ known-bug: #135124
|
||||
trait A {
|
||||
fn y(&self)
|
||||
{
|
||||
fn call() -> impl Sized {}
|
||||
self.fold(call());
|
||||
}
|
||||
fn fold(&self, &self._) {}
|
||||
}
|
20
tests/ui/fn/error-recovery-mismatch.rs
Normal file
20
tests/ui/fn/error-recovery-mismatch.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Used to ICE due to a size mismatch between the actual fake signature of `fold` and the
|
||||
// generated signature used reporting the parameter mismatch at the call site.
|
||||
// See issue #135124
|
||||
|
||||
trait A {
|
||||
fn y(&self)
|
||||
{
|
||||
fn call() -> impl Sized {}
|
||||
self.fold(call(), call());
|
||||
}
|
||||
fn fold<T>(&self, _: T, &self._) {}
|
||||
//~^ ERROR unexpected `self` parameter in function
|
||||
//~| ERROR expected one of `)` or `,`, found `.`
|
||||
//~| ERROR identifier `self` is bound more than once in this parameter list
|
||||
//~| WARNING anonymous parameters are deprecated
|
||||
//~| WARNING this is accepted in the current edition
|
||||
//~| ERROR the placeholder `_` is not allowed within types
|
||||
}
|
||||
|
||||
fn main() {}
|
46
tests/ui/fn/error-recovery-mismatch.stderr
Normal file
46
tests/ui/fn/error-recovery-mismatch.stderr
Normal file
|
@ -0,0 +1,46 @@
|
|||
error: unexpected `self` parameter in function
|
||||
--> $DIR/error-recovery-mismatch.rs:11:29
|
||||
|
|
||||
LL | fn fold<T>(&self, _: T, &self._) {}
|
||||
| ^^^^^ must be the first parameter of an associated function
|
||||
|
||||
error: expected one of `)` or `,`, found `.`
|
||||
--> $DIR/error-recovery-mismatch.rs:11:34
|
||||
|
|
||||
LL | fn fold<T>(&self, _: T, &self._) {}
|
||||
| ^
|
||||
| |
|
||||
| expected one of `)` or `,`
|
||||
| help: missing `,`
|
||||
|
||||
error[E0415]: identifier `self` is bound more than once in this parameter list
|
||||
--> $DIR/error-recovery-mismatch.rs:11:30
|
||||
|
|
||||
LL | fn fold<T>(&self, _: T, &self._) {}
|
||||
| ^^^^ used as parameter more than once
|
||||
|
||||
warning: anonymous parameters are deprecated and will be removed in the next edition
|
||||
--> $DIR/error-recovery-mismatch.rs:11:35
|
||||
|
|
||||
LL | fn fold<T>(&self, _: T, &self._) {}
|
||||
| ^ help: try naming the parameter or explicitly ignoring it: `_: _`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
|
||||
= note: `#[warn(anonymous_parameters)]` on by default
|
||||
|
||||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
||||
--> $DIR/error-recovery-mismatch.rs:11:35
|
||||
|
|
||||
LL | fn fold<T>(&self, _: T, &self._) {}
|
||||
| ^ not allowed in type signatures
|
||||
|
|
||||
help: use type parameters instead
|
||||
|
|
||||
LL | fn fold<T, U>(&self, _: T, &self.U) {}
|
||||
| +++ ~
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0121, E0415.
|
||||
For more information about an error, try `rustc --explain E0121`.
|
10
tests/ui/fn/param-mismatch-trait-fn.rs
Normal file
10
tests/ui/fn/param-mismatch-trait-fn.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
trait Foo {
|
||||
fn same_type<T>(_: T, _: T);
|
||||
}
|
||||
|
||||
fn f<T: Foo, X, Y>(x: X, y: Y) {
|
||||
T::same_type([x], Some(y));
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
23
tests/ui/fn/param-mismatch-trait-fn.stderr
Normal file
23
tests/ui/fn/param-mismatch-trait-fn.stderr
Normal file
|
@ -0,0 +1,23 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/param-mismatch-trait-fn.rs:6:23
|
||||
|
|
||||
LL | T::same_type([x], Some(y));
|
||||
| ------------ --- ^^^^^^^ expected `[X; 1]`, found `Option<Y>`
|
||||
| | |
|
||||
| | expected all arguments to be this `[X; 1]` type because they need to match the type of this parameter
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected array `[X; 1]`
|
||||
found enum `Option<Y>`
|
||||
note: associated function defined here
|
||||
--> $DIR/param-mismatch-trait-fn.rs:2:8
|
||||
|
|
||||
LL | fn same_type<T>(_: T, _: T);
|
||||
| ^^^^^^^^^ - - - this parameter needs to match the `[X; 1]` type of parameter #1
|
||||
| | |
|
||||
| | parameter #2 needs to match the `[X; 1]` type of this parameter
|
||||
| parameter #1 and parameter #2 both reference this parameter `T`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -32,7 +32,7 @@ note: method defined here
|
|||
--> $DIR/issue-61525.rs:2:8
|
||||
|
|
||||
LL | fn query<Q>(self, q: Q);
|
||||
| ^^^^^
|
||||
| ^^^^^ -
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ note: method defined here
|
|||
--> $DIR/trait-with-missing-associated-type-restriction.rs:9:8
|
||||
|
|
||||
LL | fn funk(&self, _: Self::A);
|
||||
| ^^^^
|
||||
| ^^^^ -
|
||||
help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}`
|
||||
|
|
||||
LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) {
|
||||
|
|
|
@ -22,7 +22,7 @@ note: method defined here
|
|||
--> $DIR/issue-52893.rs:11:8
|
||||
|
|
||||
LL | fn push(self, other: T) -> Self::PushRes;
|
||||
| ^^^^
|
||||
| ^^^^ -----
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue