1
Fork 0

Implementing more sophisticated filter for fn in const or static

This commit is contained in:
Kevin Per 2021-02-10 15:49:23 +00:00
parent 49fc41f047
commit fba2f883f3
3 changed files with 59 additions and 17 deletions

View file

@ -2145,12 +2145,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
hir::TyKind::BareFn(ref bf) => { hir::TyKind::BareFn(ref bf) => {
require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
tcx.mk_fn_ptr(self.ty_of_fn( tcx.mk_fn_ptr(self.ty_of_fn(
bf.unsafety, bf.unsafety,
bf.abi, bf.abi,
&bf.decl, &bf.decl,
&hir::Generics::empty(), &hir::Generics::empty(),
None, None,
Some(ast_ty),
)) ))
} }
hir::TyKind::TraitObject(ref bounds, ref lifetime) => { hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
@ -2290,6 +2292,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
generics: &hir::Generics<'_>, generics: &hir::Generics<'_>,
ident_span: Option<Span>, ident_span: Option<Span>,
hir_ty: Option<&hir::Ty<'_>>,
) -> ty::PolyFnSig<'tcx> { ) -> ty::PolyFnSig<'tcx> {
debug!("ty_of_fn"); debug!("ty_of_fn");
@ -2321,13 +2324,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// only want to emit an error complaining about them if infer types (`_`) are not // only want to emit an error complaining about them if infer types (`_`) are not
// allowed. `allow_ty_infer` gates this behavior. We check for the presence of // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
crate::collect::placeholder_type_error( crate::collect::placeholder_type_error(
tcx, tcx,
ident_span.map(|sp| sp.shrink_to_hi()), ident_span.map(|sp| sp.shrink_to_hi()),
&generics.params[..], &generics.params[..],
visitor.0, visitor.0,
true, true,
true, hir_ty,
); );
} }

View file

@ -502,6 +502,7 @@ fn typeck_with_fallback<'tcx>(
decl, decl,
&hir::Generics::empty(), &hir::Generics::empty(),
None, None,
None,
) )
} else { } else {
tcx.fn_sig(def_id) tcx.fn_sig(def_id)

View file

@ -141,7 +141,7 @@ crate fn placeholder_type_error(
generics: &[hir::GenericParam<'_>], generics: &[hir::GenericParam<'_>],
placeholder_types: Vec<Span>, placeholder_types: Vec<Span>,
suggest: bool, suggest: bool,
is_fn: bool, hir_ty: Option<&hir::Ty<'_>>,
) { ) {
if placeholder_types.is_empty() { if placeholder_types.is_empty() {
return; return;
@ -173,14 +173,40 @@ crate fn placeholder_type_error(
let mut err = bad_placeholder_type(tcx, placeholder_types); let mut err = bad_placeholder_type(tcx, placeholder_types);
// Suggest, but only if it is not a function // Suggest, but only if it is not a function in const or static
if suggest && !is_fn { if suggest {
let mut is_fn = false;
let mut is_const = false;
let mut is_static = false;
if let Some(hir_ty) = hir_ty {
if let hir::TyKind::BareFn(_) = hir_ty.kind {
is_fn = true;
// Check if parent is const or static
let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
let parent_node = tcx.hir().get(parent_id);
if let hir::Node::Item(item) = parent_node {
if let hir::ItemKind::Const(_, _) = item.kind {
is_const = true;
} else if let hir::ItemKind::Static(_, _, _) = item.kind {
is_static = true;
}
}
}
}
// if function is wrapped around a const or static,
// then don't show the suggestion
if !(is_fn && (is_const || is_static)) {
err.multipart_suggestion( err.multipart_suggestion(
"use type parameters instead", "use type parameters instead",
sugg, sugg,
Applicability::HasPlaceholders, Applicability::HasPlaceholders,
); );
} }
}
err.emit(); err.emit();
} }
@ -207,7 +233,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
&generics.params[..], &generics.params[..],
visitor.0, visitor.0,
suggest, suggest,
false, None,
); );
} }
@ -648,6 +674,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
let it = tcx.hir().expect_item(item_id); let it = tcx.hir().expect_item(item_id);
debug!("convert: item {} with id {}", it.ident, it.hir_id); debug!("convert: item {} with id {}", it.ident, it.hir_id);
let def_id = tcx.hir().local_def_id(item_id); let def_id = tcx.hir().local_def_id(item_id);
match it.kind { match it.kind {
// These don't define types. // These don't define types.
hir::ItemKind::ExternCrate(_) hir::ItemKind::ExternCrate(_)
@ -753,7 +780,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
// Account for `const C: _;`. // Account for `const C: _;`.
let mut visitor = PlaceholderHirTyCollector::default(); let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_trait_item(trait_item); visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, false); placeholder_type_error(tcx, None, &[], visitor.0, false, None);
} }
hir::TraitItemKind::Type(_, Some(_)) => { hir::TraitItemKind::Type(_, Some(_)) => {
@ -762,7 +789,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
// Account for `type T = _;`. // Account for `type T = _;`.
let mut visitor = PlaceholderHirTyCollector::default(); let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_trait_item(trait_item); visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, false); placeholder_type_error(tcx, None, &[], visitor.0, false, None);
} }
hir::TraitItemKind::Type(_, None) => { hir::TraitItemKind::Type(_, None) => {
@ -771,7 +798,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
// even if there is no concrete type. // even if there is no concrete type.
let mut visitor = PlaceholderHirTyCollector::default(); let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_trait_item(trait_item); visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, false);
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
} }
}; };
@ -792,7 +820,8 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
// Account for `type T = _;` // Account for `type T = _;`
let mut visitor = PlaceholderHirTyCollector::default(); let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_impl_item(impl_item); visitor.visit_impl_item(impl_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, false);
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
} }
hir::ImplItemKind::Const(..) => {} hir::ImplItemKind::Const(..) => {}
} }
@ -1583,6 +1612,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
&sig.decl, &sig.decl,
&generics, &generics,
Some(ident.span), Some(ident.span),
None,
), ),
} }
} }
@ -1592,9 +1622,15 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
ident, ident,
generics, generics,
.. ..
}) => { }) => AstConv::ty_of_fn(
AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span)) &icx,
} header.unsafety,
header.abi,
decl,
&generics,
Some(ident.span),
None,
),
ForeignItem(&hir::ForeignItem { ForeignItem(&hir::ForeignItem {
kind: ForeignItemKind::Fn(ref fn_decl, _, _), kind: ForeignItemKind::Fn(ref fn_decl, _, _),
@ -2264,6 +2300,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
decl, decl,
&hir::Generics::empty(), &hir::Generics::empty(),
Some(ident.span), Some(ident.span),
None,
); );
// Feature gate SIMD types in FFI, since I am not sure that the // Feature gate SIMD types in FFI, since I am not sure that the