Auto merge of #130444 - matthiaskrgr:rollup-onlrjva, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - #130033 (Don't call `fn_arg_names` query for non-`fn` foreign items in resolver) - #130282 (Do not report an excessive number of overflow errors for an ever-growing deref impl) - #130437 (Avoid crashing on variadic functions when producing arg-mismatch errors) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c52c23b6f4
@ -1049,7 +1049,7 @@ pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<
|
|||||||
/// trait or region sub-obligations. (presumably we could, but it's not
|
/// trait or region sub-obligations. (presumably we could, but it's not
|
||||||
/// particularly important for diagnostics...)
|
/// particularly important for diagnostics...)
|
||||||
pub(crate) fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
pub(crate) fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||||
self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
|
self.autoderef(DUMMY_SP, expr_ty).silence_errors().nth(1).and_then(|(deref_ty, _)| {
|
||||||
self.infcx
|
self.infcx
|
||||||
.type_implements_trait(
|
.type_implements_trait(
|
||||||
self.tcx.lang_items().deref_mut_trait()?,
|
self.tcx.lang_items().deref_mut_trait()?,
|
||||||
|
@ -2864,13 +2864,13 @@ fn no_such_field_err(&self, field: Ident, expr_t: Ty<'tcx>, id: HirId) -> Diag<'
|
|||||||
(expr_t, "")
|
(expr_t, "")
|
||||||
};
|
};
|
||||||
for (found_fields, args) in
|
for (found_fields, args) in
|
||||||
self.get_field_candidates_considering_privacy(span, ty, mod_id, id)
|
self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, id)
|
||||||
{
|
{
|
||||||
let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
|
let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
|
||||||
let mut candidate_fields: Vec<_> = found_fields
|
let mut candidate_fields: Vec<_> = found_fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|candidate_field| {
|
.filter_map(|candidate_field| {
|
||||||
self.check_for_nested_field_satisfying(
|
self.check_for_nested_field_satisfying_condition_for_diag(
|
||||||
span,
|
span,
|
||||||
&|candidate_field, _| candidate_field.ident(self.tcx()) == field,
|
&|candidate_field, _| candidate_field.ident(self.tcx()) == field,
|
||||||
candidate_field,
|
candidate_field,
|
||||||
@ -2933,7 +2933,7 @@ fn private_field_err(&self, field: Ident, base_did: DefId) -> Diag<'_> {
|
|||||||
.with_span_label(field.span, "private field")
|
.with_span_label(field.span, "private field")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_field_candidates_considering_privacy(
|
pub(crate) fn get_field_candidates_considering_privacy_for_diag(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
base_ty: Ty<'tcx>,
|
base_ty: Ty<'tcx>,
|
||||||
@ -2942,7 +2942,18 @@ pub(crate) fn get_field_candidates_considering_privacy(
|
|||||||
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
|
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
|
||||||
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
|
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
|
||||||
|
|
||||||
self.autoderef(span, base_ty)
|
let mut autoderef = self.autoderef(span, base_ty).silence_errors();
|
||||||
|
let deref_chain: Vec<_> = autoderef.by_ref().collect();
|
||||||
|
|
||||||
|
// Don't probe if we hit the recursion limit, since it may result in
|
||||||
|
// quadratic blowup if we then try to further deref the results of this
|
||||||
|
// function. This is a best-effort method, after all.
|
||||||
|
if autoderef.reached_recursion_limit() {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_chain
|
||||||
|
.into_iter()
|
||||||
.filter_map(move |(base_t, _)| {
|
.filter_map(move |(base_t, _)| {
|
||||||
match base_t.kind() {
|
match base_t.kind() {
|
||||||
ty::Adt(base_def, args) if !base_def.is_enum() => {
|
ty::Adt(base_def, args) if !base_def.is_enum() => {
|
||||||
@ -2975,7 +2986,7 @@ pub(crate) fn get_field_candidates_considering_privacy(
|
|||||||
|
|
||||||
/// This method is called after we have encountered a missing field error to recursively
|
/// This method is called after we have encountered a missing field error to recursively
|
||||||
/// search for the field
|
/// search for the field
|
||||||
pub(crate) fn check_for_nested_field_satisfying(
|
pub(crate) fn check_for_nested_field_satisfying_condition_for_diag(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
|
matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
|
||||||
@ -3000,20 +3011,24 @@ pub(crate) fn check_for_nested_field_satisfying(
|
|||||||
if matches(candidate_field, field_ty) {
|
if matches(candidate_field, field_ty) {
|
||||||
return Some(field_path);
|
return Some(field_path);
|
||||||
} else {
|
} else {
|
||||||
for (nested_fields, subst) in
|
for (nested_fields, subst) in self
|
||||||
self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id)
|
.get_field_candidates_considering_privacy_for_diag(
|
||||||
|
span, field_ty, mod_id, hir_id,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// recursively search fields of `candidate_field` if it's a ty::Adt
|
// recursively search fields of `candidate_field` if it's a ty::Adt
|
||||||
for field in nested_fields {
|
for field in nested_fields {
|
||||||
if let Some(field_path) = self.check_for_nested_field_satisfying(
|
if let Some(field_path) = self
|
||||||
span,
|
.check_for_nested_field_satisfying_condition_for_diag(
|
||||||
matches,
|
span,
|
||||||
field,
|
matches,
|
||||||
subst,
|
field,
|
||||||
field_path.clone(),
|
subst,
|
||||||
mod_id,
|
field_path.clone(),
|
||||||
hir_id,
|
mod_id,
|
||||||
) {
|
hir_id,
|
||||||
|
)
|
||||||
|
{
|
||||||
return Some(field_path);
|
return Some(field_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2619,9 +2619,9 @@ fn get_hir_params_with_generics(
|
|||||||
is_method: bool,
|
is_method: bool,
|
||||||
) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
|
) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
|
||||||
let fn_node = self.tcx.hir().get_if_local(def_id)?;
|
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_node
|
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
|
||||||
.fn_decl()?
|
|
||||||
.inputs
|
.inputs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.skip(if is_method { 1 } else { 0 })
|
.skip(if is_method { 1 } else { 0 })
|
||||||
@ -2642,7 +2642,7 @@ fn get_hir_params_with_generics(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let params: Vec<&hir::Param<'_>> = self
|
let mut params: Vec<&hir::Param<'_>> = self
|
||||||
.tcx
|
.tcx
|
||||||
.hir()
|
.hir()
|
||||||
.body(fn_node.body_id()?)
|
.body(fn_node.body_id()?)
|
||||||
@ -2651,7 +2651,16 @@ fn get_hir_params_with_generics(
|
|||||||
.skip(if is_method { 1 } else { 0 })
|
.skip(if is_method { 1 } else { 0 })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Some(generic_params.into_iter().zip_eq(params).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();
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert_eq!(params.len(), generic_params.len());
|
||||||
|
Some(generic_params.into_iter().zip(params).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +375,7 @@ pub(crate) fn probe_op<OP, R>(
|
|||||||
// If our autoderef loop had reached the recursion limit,
|
// If our autoderef loop had reached the recursion limit,
|
||||||
// report an overflow error, but continue going on with
|
// report an overflow error, but continue going on with
|
||||||
// the truncated autoderef list.
|
// the truncated autoderef list.
|
||||||
if steps.reached_recursion_limit {
|
if steps.reached_recursion_limit && !is_suggestion.0 {
|
||||||
self.probe(|_| {
|
self.probe(|_| {
|
||||||
let ty = &steps
|
let ty = &steps
|
||||||
.steps
|
.steps
|
||||||
|
@ -62,14 +62,14 @@ fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
|||||||
// It might seem that we can use `predicate_must_hold_modulo_regions`,
|
// It might seem that we can use `predicate_must_hold_modulo_regions`,
|
||||||
// but since a Dummy binder is used to fill in the FnOnce trait's arguments,
|
// but since a Dummy binder is used to fill in the FnOnce trait's arguments,
|
||||||
// type resolution always gives a "maybe" here.
|
// type resolution always gives a "maybe" here.
|
||||||
if self.autoderef(span, ty).any(|(ty, _)| {
|
if self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
|
||||||
info!("check deref {:?} error", ty);
|
info!("check deref {:?} error", ty);
|
||||||
matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
|
matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
|
||||||
}) {
|
}) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.autoderef(span, ty).any(|(ty, _)| {
|
self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
|
||||||
info!("check deref {:?} impl FnOnce", ty);
|
info!("check deref {:?} impl FnOnce", ty);
|
||||||
self.probe(|_| {
|
self.probe(|_| {
|
||||||
let trait_ref =
|
let trait_ref =
|
||||||
@ -90,7 +90,9 @@ fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||||
self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
self.autoderef(span, ty)
|
||||||
|
.silence_errors()
|
||||||
|
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_into_iterator_should_be_iterator(
|
fn impl_into_iterator_should_be_iterator(
|
||||||
@ -672,7 +674,7 @@ fn report_no_match_method_error(
|
|||||||
let mut ty_str_reported = ty_str.clone();
|
let mut ty_str_reported = ty_str.clone();
|
||||||
if let ty::Adt(_, generics) = rcvr_ty.kind() {
|
if let ty::Adt(_, generics) = rcvr_ty.kind() {
|
||||||
if generics.len() > 0 {
|
if generics.len() > 0 {
|
||||||
let mut autoderef = self.autoderef(span, rcvr_ty);
|
let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
|
||||||
let candidate_found = autoderef.any(|(ty, _)| {
|
let candidate_found = autoderef.any(|(ty, _)| {
|
||||||
if let ty::Adt(adt_def, _) = ty.kind() {
|
if let ty::Adt(adt_def, _) = ty.kind() {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -2237,6 +2239,7 @@ fn suggest_associated_call_syntax(
|
|||||||
let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
|
let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
|
||||||
let target_ty = self
|
let target_ty = self
|
||||||
.autoderef(sugg_span, rcvr_ty)
|
.autoderef(sugg_span, rcvr_ty)
|
||||||
|
.silence_errors()
|
||||||
.find(|(rcvr_ty, _)| {
|
.find(|(rcvr_ty, _)| {
|
||||||
DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
|
DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
|
||||||
})
|
})
|
||||||
@ -2352,17 +2355,18 @@ fn suggest_calling_field_as_fn(
|
|||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
|
let field_receiver =
|
||||||
ty::Adt(def, args) if !def.is_enum() => {
|
self.autoderef(span, rcvr_ty).silence_errors().find_map(|(ty, _)| match ty.kind() {
|
||||||
let variant = &def.non_enum_variant();
|
ty::Adt(def, args) if !def.is_enum() => {
|
||||||
tcx.find_field_index(item_name, variant).map(|index| {
|
let variant = &def.non_enum_variant();
|
||||||
let field = &variant.fields[index];
|
tcx.find_field_index(item_name, variant).map(|index| {
|
||||||
let field_ty = field.ty(tcx, args);
|
let field = &variant.fields[index];
|
||||||
(field, field_ty)
|
let field_ty = field.ty(tcx, args);
|
||||||
})
|
(field, field_ty)
|
||||||
}
|
})
|
||||||
_ => None,
|
}
|
||||||
});
|
_ => None,
|
||||||
|
});
|
||||||
if let Some((field, field_ty)) = field_receiver {
|
if let Some((field, field_ty)) = field_receiver {
|
||||||
let scope = tcx.parent_module_from_def_id(self.body_id);
|
let scope = tcx.parent_module_from_def_id(self.body_id);
|
||||||
let is_accessible = field.vis.is_accessible_from(scope, tcx);
|
let is_accessible = field.vis.is_accessible_from(scope, tcx);
|
||||||
@ -2675,9 +2679,12 @@ fn suggest_calling_method_on_field(
|
|||||||
) {
|
) {
|
||||||
if let SelfSource::MethodCall(expr) = source {
|
if let SelfSource::MethodCall(expr) = source {
|
||||||
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
|
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
|
||||||
for (fields, args) in
|
for (fields, args) in self.get_field_candidates_considering_privacy_for_diag(
|
||||||
self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id)
|
span,
|
||||||
{
|
actual,
|
||||||
|
mod_id,
|
||||||
|
expr.hir_id,
|
||||||
|
) {
|
||||||
let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
|
let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
|
||||||
|
|
||||||
let lang_items = self.tcx.lang_items();
|
let lang_items = self.tcx.lang_items();
|
||||||
@ -2693,7 +2700,7 @@ fn suggest_calling_method_on_field(
|
|||||||
let mut candidate_fields: Vec<_> = fields
|
let mut candidate_fields: Vec<_> = fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|candidate_field| {
|
.filter_map(|candidate_field| {
|
||||||
self.check_for_nested_field_satisfying(
|
self.check_for_nested_field_satisfying_condition_for_diag(
|
||||||
span,
|
span,
|
||||||
&|_, field_ty| {
|
&|_, field_ty| {
|
||||||
self.lookup_probe_for_diagnostic(
|
self.lookup_probe_for_diagnostic(
|
||||||
@ -3195,7 +3202,7 @@ fn note_derefed_ty_has_method(
|
|||||||
let SelfSource::QPath(ty) = self_source else {
|
let SelfSource::QPath(ty) = self_source else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).skip(1) {
|
for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).silence_errors().skip(1) {
|
||||||
if let Ok(pick) = self.probe_for_name(
|
if let Ok(pick) = self.probe_for_name(
|
||||||
Mode::Path,
|
Mode::Path,
|
||||||
item_name,
|
item_name,
|
||||||
@ -4221,7 +4228,7 @@ fn is_local(ty: Ty<'_>) -> bool {
|
|||||||
return is_local(rcvr_ty);
|
return is_local(rcvr_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
|
self.autoderef(span, rcvr_ty).silence_errors().any(|(ty, _)| is_local(ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2533,6 +2533,7 @@ fn error_expected_array_or_slice(
|
|||||||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
||||||
} else if self
|
} else if self
|
||||||
.autoderef(span, expected_ty)
|
.autoderef(span, expected_ty)
|
||||||
|
.silence_errors()
|
||||||
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
||||||
&& let Some(span) = ti.span
|
&& let Some(span) = ti.span
|
||||||
&& let Some(_) = ti.origin_expr
|
&& let Some(_) = ti.origin_expr
|
||||||
|
@ -2068,33 +2068,34 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
|||||||
) {
|
) {
|
||||||
let res = binding.res();
|
let res = binding.res();
|
||||||
if filter_fn(res) {
|
if filter_fn(res) {
|
||||||
let def_id = res.def_id();
|
match res {
|
||||||
let has_self = match def_id.as_local() {
|
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => {
|
||||||
Some(def_id) => {
|
let has_self = match def_id.as_local() {
|
||||||
self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
|
Some(def_id) => self
|
||||||
}
|
.r
|
||||||
None => self
|
.delegation_fn_sigs
|
||||||
.r
|
.get(&def_id)
|
||||||
.tcx
|
.map_or(false, |sig| sig.has_self),
|
||||||
.fn_arg_names(def_id)
|
None => self
|
||||||
.first()
|
.r
|
||||||
.is_some_and(|ident| ident.name == kw::SelfLower),
|
.tcx
|
||||||
};
|
.fn_arg_names(def_id)
|
||||||
if has_self {
|
.first()
|
||||||
return Some(AssocSuggestion::MethodWithSelf { called });
|
.is_some_and(|ident| ident.name == kw::SelfLower),
|
||||||
} else {
|
};
|
||||||
match res {
|
if has_self {
|
||||||
Res::Def(DefKind::AssocFn, _) => {
|
return Some(AssocSuggestion::MethodWithSelf { called });
|
||||||
|
} else {
|
||||||
return Some(AssocSuggestion::AssocFn { called });
|
return Some(AssocSuggestion::AssocFn { called });
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::AssocConst, _) => {
|
|
||||||
return Some(AssocSuggestion::AssocConst);
|
|
||||||
}
|
|
||||||
Res::Def(DefKind::AssocTy, _) => {
|
|
||||||
return Some(AssocSuggestion::AssocType);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
Res::Def(DefKind::AssocConst, _) => {
|
||||||
|
return Some(AssocSuggestion::AssocConst);
|
||||||
|
}
|
||||||
|
Res::Def(DefKind::AssocTy, _) => {
|
||||||
|
return Some(AssocSuggestion::AssocType);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
//@ known-bug: rust-lang/rust#130372
|
|
||||||
|
|
||||||
pub fn variadic_fn(n: usize, mut args: ...) {}
|
|
||||||
|
|
||||||
reuse variadic_fn;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
variadic_fn();
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
//@ known-bug: rust-lang/rust#130372
|
|
||||||
|
|
||||||
pub fn test_va_copy(_: u64, mut ap: ...) {}
|
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
unsafe {
|
|
||||||
test_va_copy();
|
|
||||||
|
|
||||||
call(x);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
//@ known-bug: rust-lang/rust#130372
|
|
||||||
|
|
||||||
fn bar() -> impl Fn() {
|
|
||||||
wrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wrap(...: impl ...) -> impl Fn() {}
|
|
16
tests/ui/methods/probe-error-on-infinite-deref.rs
Normal file
16
tests/ui/methods/probe-error-on-infinite-deref.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
// Make sure that method probe error reporting doesn't get too tangled up
|
||||||
|
// on this infinite deref impl. See #130224.
|
||||||
|
|
||||||
|
struct Wrap<T>(T);
|
||||||
|
impl<T> Deref for Wrap<T> {
|
||||||
|
type Target = Wrap<Wrap<T>>;
|
||||||
|
fn deref(&self) -> &Wrap<Wrap<T>> { todo!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
Wrap(1).lmao();
|
||||||
|
//~^ ERROR reached the recursion limit
|
||||||
|
//~| ERROR no method named `lmao`
|
||||||
|
}
|
21
tests/ui/methods/probe-error-on-infinite-deref.stderr
Normal file
21
tests/ui/methods/probe-error-on-infinite-deref.stderr
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<{integer}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
|
||||||
|
--> $DIR/probe-error-on-infinite-deref.rs:13:13
|
||||||
|
|
|
||||||
|
LL | Wrap(1).lmao();
|
||||||
|
| ^^^^ deref recursion limit reached
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
|
||||||
|
|
||||||
|
error[E0599]: no method named `lmao` found for struct `Wrap<{integer}>` in the current scope
|
||||||
|
--> $DIR/probe-error-on-infinite-deref.rs:13:13
|
||||||
|
|
|
||||||
|
LL | struct Wrap<T>(T);
|
||||||
|
| -------------- method `lmao` not found for this struct
|
||||||
|
...
|
||||||
|
LL | Wrap(1).lmao();
|
||||||
|
| ^^^^ method not found in `Wrap<{integer}>`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0055, E0599.
|
||||||
|
For more information about an error, try `rustc --explain E0055`.
|
@ -0,0 +1,12 @@
|
|||||||
|
#![feature(c_variadic)]
|
||||||
|
|
||||||
|
// Regression test that covers all 3 cases of https://github.com/rust-lang/rust/issues/130372
|
||||||
|
|
||||||
|
unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
unsafe {
|
||||||
|
test_va_copy();
|
||||||
|
//~^ ERROR this function takes at least 1 argument but 0 arguments were supplied
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
|
||||||
|
--> $DIR/mismatch-args-vargs-issue-130372.rs:9:9
|
||||||
|
|
|
||||||
|
LL | test_va_copy();
|
||||||
|
| ^^^^^^^^^^^^-- argument #1 of type `u64` is missing
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/mismatch-args-vargs-issue-130372.rs:5:22
|
||||||
|
|
|
||||||
|
LL | unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
|
||||||
|
| ^^^^^^^^^^^^ ------
|
||||||
|
help: provide the argument
|
||||||
|
|
|
||||||
|
LL | test_va_copy(/* u64 */);
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0060`.
|
3
tests/ui/resolve/auxiliary/foreign-trait-with-assoc.rs
Normal file
3
tests/ui/resolve/auxiliary/foreign-trait-with-assoc.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub trait Foo {
|
||||||
|
type Bar;
|
||||||
|
}
|
11
tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs
Normal file
11
tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//@ aux-build:foreign-trait-with-assoc.rs
|
||||||
|
|
||||||
|
extern crate foreign_trait_with_assoc;
|
||||||
|
use foreign_trait_with_assoc::Foo;
|
||||||
|
|
||||||
|
// Make sure we don't try to call `fn_arg_names` on a non-fn item.
|
||||||
|
|
||||||
|
impl Foo for Bar {}
|
||||||
|
//~^ ERROR cannot find type `Bar` in this scope
|
||||||
|
|
||||||
|
fn main() {}
|
14
tests/ui/resolve/dont-compute-arg-names-for-non-fn.stderr
Normal file
14
tests/ui/resolve/dont-compute-arg-names-for-non-fn.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error[E0412]: cannot find type `Bar` in this scope
|
||||||
|
--> $DIR/dont-compute-arg-names-for-non-fn.rs:8:14
|
||||||
|
|
|
||||||
|
LL | impl Foo for Bar {}
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
help: you might have meant to use the associated type
|
||||||
|
|
|
||||||
|
LL | impl Foo for Self::Bar {}
|
||||||
|
| ++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0412`.
|
Loading…
Reference in New Issue
Block a user