Skip to content

Commit a6809d0

Browse files
authored
Rollup merge of #81914 - kper:fixing-81885, r=estebank
Fixing bad suggestion for `_` in `const` type when a function #81885 Closes #81885 ``` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:13:22 | LL | const TEST4: fn() -> _ = 42; | ^ | | | not allowed in type signatures | help: use type parameters instead: `T` ``` Do not show the suggestion `help: use type parameters instead: T` when `fn`
2 parents 2531563 + 1adc6be commit a6809d0

File tree

7 files changed

+93
-21
lines changed

7 files changed

+93
-21
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2191,12 +2191,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
21912191
}
21922192
hir::TyKind::BareFn(ref bf) => {
21932193
require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
2194+
21942195
tcx.mk_fn_ptr(self.ty_of_fn(
21952196
bf.unsafety,
21962197
bf.abi,
21972198
&bf.decl,
21982199
&hir::Generics::empty(),
21992200
None,
2201+
Some(ast_ty),
22002202
))
22012203
}
22022204
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
@@ -2336,6 +2338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23362338
decl: &hir::FnDecl<'_>,
23372339
generics: &hir::Generics<'_>,
23382340
ident_span: Option<Span>,
2341+
hir_ty: Option<&hir::Ty<'_>>,
23392342
) -> ty::PolyFnSig<'tcx> {
23402343
debug!("ty_of_fn");
23412344

@@ -2367,12 +2370,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23672370
// only want to emit an error complaining about them if infer types (`_`) are not
23682371
// allowed. `allow_ty_infer` gates this behavior. We check for the presence of
23692372
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
2373+
23702374
crate::collect::placeholder_type_error(
23712375
tcx,
23722376
ident_span.map(|sp| sp.shrink_to_hi()),
23732377
&generics.params[..],
23742378
visitor.0,
23752379
true,
2380+
hir_ty,
23762381
);
23772382
}
23782383

compiler/rustc_typeck/src/check/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ fn typeck_with_fallback<'tcx>(
502502
decl,
503503
&hir::Generics::empty(),
504504
None,
505+
None,
505506
)
506507
} else {
507508
tcx.fn_sig(def_id)

compiler/rustc_typeck/src/collect.rs

+60-13
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ crate fn placeholder_type_error(
143143
generics: &[hir::GenericParam<'_>],
144144
placeholder_types: Vec<Span>,
145145
suggest: bool,
146+
hir_ty: Option<&hir::Ty<'_>>,
146147
) {
147148
if placeholder_types.is_empty() {
148149
return;
@@ -173,12 +174,40 @@ crate fn placeholder_type_error(
173174
}
174175

175176
let mut err = bad_placeholder_type(tcx, placeholder_types);
177+
178+
// Suggest, but only if it is not a function in const or static
176179
if suggest {
177-
err.multipart_suggestion(
178-
"use type parameters instead",
179-
sugg,
180-
Applicability::HasPlaceholders,
181-
);
180+
let mut is_fn = false;
181+
let mut is_const = false;
182+
let mut is_static = false;
183+
184+
if let Some(hir_ty) = hir_ty {
185+
if let hir::TyKind::BareFn(_) = hir_ty.kind {
186+
is_fn = true;
187+
188+
// Check if parent is const or static
189+
let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
190+
let parent_node = tcx.hir().get(parent_id);
191+
192+
if let hir::Node::Item(item) = parent_node {
193+
if let hir::ItemKind::Const(_, _) = item.kind {
194+
is_const = true;
195+
} else if let hir::ItemKind::Static(_, _, _) = item.kind {
196+
is_static = true;
197+
}
198+
}
199+
}
200+
}
201+
202+
// if function is wrapped around a const or static,
203+
// then don't show the suggestion
204+
if !(is_fn && (is_const || is_static)) {
205+
err.multipart_suggestion(
206+
"use type parameters instead",
207+
sugg,
208+
Applicability::HasPlaceholders,
209+
);
210+
}
182211
}
183212
err.emit();
184213
}
@@ -200,7 +229,14 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
200229
let mut visitor = PlaceholderHirTyCollector::default();
201230
visitor.visit_item(item);
202231

203-
placeholder_type_error(tcx, Some(generics.span), &generics.params[..], visitor.0, suggest);
232+
placeholder_type_error(
233+
tcx,
234+
Some(generics.span),
235+
&generics.params[..],
236+
visitor.0,
237+
suggest,
238+
None,
239+
);
204240
}
205241

206242
impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
@@ -682,6 +718,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
682718
let it = tcx.hir().expect_item(item_id);
683719
debug!("convert: item {} with id {}", it.ident, it.hir_id);
684720
let def_id = tcx.hir().local_def_id(item_id);
721+
685722
match it.kind {
686723
// These don't define types.
687724
hir::ItemKind::ExternCrate(_)
@@ -787,7 +824,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
787824
// Account for `const C: _;`.
788825
let mut visitor = PlaceholderHirTyCollector::default();
789826
visitor.visit_trait_item(trait_item);
790-
placeholder_type_error(tcx, None, &[], visitor.0, false);
827+
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
791828
}
792829

793830
hir::TraitItemKind::Type(_, Some(_)) => {
@@ -796,7 +833,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
796833
// Account for `type T = _;`.
797834
let mut visitor = PlaceholderHirTyCollector::default();
798835
visitor.visit_trait_item(trait_item);
799-
placeholder_type_error(tcx, None, &[], visitor.0, false);
836+
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
800837
}
801838

802839
hir::TraitItemKind::Type(_, None) => {
@@ -805,7 +842,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
805842
// even if there is no concrete type.
806843
let mut visitor = PlaceholderHirTyCollector::default();
807844
visitor.visit_trait_item(trait_item);
808-
placeholder_type_error(tcx, None, &[], visitor.0, false);
845+
846+
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
809847
}
810848
};
811849

@@ -826,7 +864,8 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
826864
// Account for `type T = _;`
827865
let mut visitor = PlaceholderHirTyCollector::default();
828866
visitor.visit_impl_item(impl_item);
829-
placeholder_type_error(tcx, None, &[], visitor.0, false);
867+
868+
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
830869
}
831870
hir::ImplItemKind::Const(..) => {}
832871
}
@@ -1654,6 +1693,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
16541693
&sig.decl,
16551694
&generics,
16561695
Some(ident.span),
1696+
None,
16571697
),
16581698
}
16591699
}
@@ -1663,9 +1703,15 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
16631703
ident,
16641704
generics,
16651705
..
1666-
}) => {
1667-
AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span))
1668-
}
1706+
}) => AstConv::ty_of_fn(
1707+
&icx,
1708+
header.unsafety,
1709+
header.abi,
1710+
decl,
1711+
&generics,
1712+
Some(ident.span),
1713+
None,
1714+
),
16691715

16701716
ForeignItem(&hir::ForeignItem {
16711717
kind: ForeignItemKind::Fn(ref fn_decl, _, _),
@@ -2335,6 +2381,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
23352381
decl,
23362382
&hir::Generics::empty(),
23372383
Some(ident.span),
2384+
None,
23382385
);
23392386

23402387
// Feature gate SIMD types in FFI, since I am not sure that the

src/test/ui/issues/issue-74086.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
22
--> $DIR/issue-74086.rs:2:20
33
|
44
LL | static BUG: fn(_) -> u8 = |_| 8;
5-
| ^
6-
| |
7-
| not allowed in type signatures
8-
| help: use type parameters instead: `T`
5+
| ^ not allowed in type signatures
96

107
error: aborting due to previous error
118

src/test/ui/issues/issue-81885.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const TEST4: fn() -> _ = 42;
2+
//~^ ERROR the type placeholder `_` is not allowed within types on item
3+
//signatures
4+
5+
fn main() {
6+
const TEST5: fn() -> _ = 42;
7+
//~^ ERROR the type placeholder `_` is not allowed within types on item
8+
//signatures
9+
10+
}

src/test/ui/issues/issue-81885.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
2+
--> $DIR/issue-81885.rs:1:22
3+
|
4+
LL | const TEST4: fn() -> _ = 42;
5+
| ^ not allowed in type signatures
6+
7+
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
8+
--> $DIR/issue-81885.rs:6:26
9+
|
10+
LL | const TEST5: fn() -> _ = 42;
11+
| ^ not allowed in type signatures
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0121`.

src/test/ui/typeck/typeck_type_placeholder_item_help.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
2929
--> $DIR/typeck_type_placeholder_item_help.rs:13:22
3030
|
3131
LL | const TEST4: fn() -> _ = 42;
32-
| ^
33-
| |
34-
| not allowed in type signatures
35-
| help: use type parameters instead: `T`
32+
| ^ not allowed in type signatures
3633

3734
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
3835
--> $DIR/typeck_type_placeholder_item_help.rs:17:18

0 commit comments

Comments
 (0)