Skip to content

Remove clean::Function::header and calculate it on-demand #91217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3273,9 +3273,7 @@ impl<'hir> Node<'hir> {
_ => None,
},
Node::TraitItem(ti) => match ti.kind {
TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => {
Some(FnKind::Method(ti.ident, sig, None))
}
TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig, None)),
_ => None,
},
Node::ImplItem(ii) => match ii.kind {
Expand All @@ -3286,6 +3284,10 @@ impl<'hir> Node<'hir> {
ExprKind::Closure(..) => Some(FnKind::Closure),
_ => None,
},
Node::ForeignItem(fi) => match fi.kind {
ForeignItemKind::Fn(..) => Some(FnKind::ForeignFn(fi.ident)),
_ => None,
},
_ => None,
}
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ pub enum FnKind<'a> {

/// `|x, y| {}`
Closure,

/// `extern "C" { pub fn foo(); }`
ForeignFn(Ident),
Comment on lines +111 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new variant shouldn't be necessary - if you look at ItemFn above it allows for an ABI field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it requires a FnHeader, which is not available for ForeignItem functions.
Should I just create a header with all items such as asyncness and constness set to false?

Copy link
Member

@jyn514 jyn514 Nov 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good question for petrochenkov, I'm not sure. https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.ForeignItemKind.html has a FnDecl but not FnHeader. Maybe try implementing that for now and we can change it later if necessary.

}

impl<'a> FnKind<'a> {
Expand All @@ -115,6 +118,7 @@ impl<'a> FnKind<'a> {
FnKind::ItemFn(_, _, ref header, _) => Some(header),
FnKind::Method(_, ref sig, _) => Some(&sig.header),
FnKind::Closure => None,
FnKind::ForeignFn(_) => None,
}
}

Expand Down Expand Up @@ -979,7 +983,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
FnKind::ItemFn(_, generics, ..) => {
visitor.visit_generics(generics);
}
FnKind::Method(..) | FnKind::Closure => {}
FnKind::Method(..) | FnKind::Closure | FnKind::ForeignFn(_) => {}
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/nonstandard_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
}
self.check_snake_case(cx, "function", ident);
}
FnKind::Closure => (),
FnKind::Closure | FnKind::ForeignFn(_) => (),
}
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_passes/src/naked_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
let fn_header;

match fk {
FnKind::Closure => {
// Closures with a naked attribute are rejected during attribute
// check. Don't validate them any further.
FnKind::Closure | FnKind::ForeignFn(_) => {
// Closures and Foreign Functions with a naked attribute are
// rejected during attribute check. Don't validate them any further.
return;
}
FnKind::ItemFn(ident, _, ref header, ..) => {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_resolve/src/late/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,15 +692,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::FnKind::ItemFn(id, _, _, _) => id.as_str(),
intravisit::FnKind::Method(id, _, _) => id.as_str(),
intravisit::FnKind::Closure => Symbol::intern("closure").as_str(),
intravisit::FnKind::ForeignFn(id) => id.as_str(),
};
let name: &str = &name;
let span = span!(Level::DEBUG, "visit_fn", name);
let _enter = span.enter();
match fk {
// Any `Binders` are handled elsewhere
intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => {
intravisit::walk_fn(self, fk, fd, b, s, hir_id)
}
intravisit::FnKind::ItemFn(..)
| intravisit::FnKind::Method(..)
| intravisit::FnKind::ForeignFn(..) => intravisit::walk_fn(self, fk, fd, b, s, hir_id),
intravisit::FnKind::Closure => {
self.map.late_bound_vars.insert(hir_id, vec![]);
let scope = Scope::Binder {
Expand Down
10 changes: 1 addition & 9 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,12 @@ crate fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Tra

fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Function {
let sig = cx.tcx.fn_sig(did);

let constness =
if cx.tcx.is_const_fn_raw(did) { hir::Constness::Const } else { hir::Constness::NotConst };
let asyncness = cx.tcx.asyncness(did);
let predicates = cx.tcx.predicates_of(did);
let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
// NOTE: generics need to be cleaned before the decl!
((cx.tcx.generics_of(did), predicates).clean(cx), (did, sig).clean(cx))
});
clean::Function {
decl,
generics,
header: hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness },
}
clean::Function { decl, generics }
}

fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
Expand Down
82 changes: 8 additions & 74 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ crate mod utils;

use rustc_ast as ast;
use rustc_attr as attr;
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
Expand All @@ -25,8 +24,6 @@ use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{AstPass, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, ExpnKind};
use rustc_target::spec::abi::Abi;
use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
use rustc_typeck::hir_ty_to_ty;

use std::assert_matches::assert_matches;
Expand Down Expand Up @@ -747,14 +744,7 @@ fn clean_fn_or_proc_macro(
ProcMacroItem(ProcMacro { kind, helpers })
}
None => {
let mut func = (sig, generics, body_id).clean(cx);
let def_id = item.def_id.to_def_id();
func.header.constness =
if cx.tcx.is_const_fn(def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
let func = (sig, generics, body_id).clean(cx);
FunctionItem(func)
}
}
Expand All @@ -769,7 +759,7 @@ impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::Bo
let decl = clean_fn_decl_with_args(cx, self.0.decl, args);
(generics, decl)
});
Function { decl, generics, header: self.0.header }
Function { decl, generics }
}
}

Expand Down Expand Up @@ -885,12 +875,7 @@ impl Clean<Item> for hir::TraitItem<'_> {
AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx.tcx, e)))
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let mut m = (sig, &self.generics, body).clean(cx);
if m.header.constness == hir::Constness::Const
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
{
m.header.constness = hir::Constness::NotConst;
}
let m = (sig, &self.generics, body).clean(cx);
MethodItem(m, None)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
Expand All @@ -901,12 +886,7 @@ impl Clean<Item> for hir::TraitItem<'_> {
let decl = clean_fn_decl_with_args(cx, sig.decl, args);
(generics, decl)
});
let mut t = Function { header: sig.header, decl, generics };
if t.header.constness == hir::Constness::Const
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
{
t.header.constness = hir::Constness::NotConst;
}
let t = Function { decl, generics };
TyMethodItem(t)
}
hir::TraitItemKind::Type(bounds, ref default) => {
Expand All @@ -932,12 +912,7 @@ impl Clean<Item> for hir::ImplItem<'_> {
AssocConstItem(ty.clean(cx), Some(print_const_expr(cx.tcx, expr)))
}
hir::ImplItemKind::Fn(ref sig, body) => {
let mut m = (sig, &self.generics, body).clean(cx);
if m.header.constness == hir::Constness::Const
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
{
m.header.constness = hir::Constness::NotConst;
}
let m = (sig, &self.generics, body).clean(cx);
MethodItem(m, Some(self.defaultness))
}
hir::ImplItemKind::TyAlias(ref hir_ty) => {
Expand Down Expand Up @@ -1017,40 +992,13 @@ impl Clean<Item> for ty::AssocItem {
ty::TraitContainer(_) => self.defaultness.has_value(),
};
if provided {
let constness = if tcx.is_const_fn_raw(self.def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
let asyncness = tcx.asyncness(self.def_id);
let defaultness = match self.container {
ty::ImplContainer(_) => Some(self.defaultness),
ty::TraitContainer(_) => None,
};
MethodItem(
Function {
generics,
decl,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness,
asyncness,
},
},
defaultness,
)
MethodItem(Function { generics, decl }, defaultness)
} else {
TyMethodItem(Function {
generics,
decl,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
})
TyMethodItem(Function { generics, decl })
}
}
ty::AssocKind::Type => {
Expand Down Expand Up @@ -2020,28 +1968,14 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
hir::ForeignItemKind::Fn(decl, names, ref generics) => {
let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
let (generics, decl) = enter_impl_trait(cx, |cx| {
// NOTE: generics must be cleaned before args
let generics = generics.clean(cx);
let args = (decl.inputs, names).clean(cx);
let decl = clean_fn_decl_with_args(cx, decl, args);
(generics, decl)
});
ForeignFunctionItem(Function {
decl,
generics,
header: hir::FnHeader {
unsafety: if abi == Abi::RustIntrinsic {
intrinsic_operation_unsafety(item.ident.name)
} else {
hir::Unsafety::Unsafe
},
abi,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
})
ForeignFunctionItem(Function { decl, generics })
}
hir::ForeignItemKind::Static(ref ty, mutability) => {
ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,6 @@ crate struct Generics {
crate struct Function {
crate decl: FnDecl,
crate generics: Generics,
crate header: hir::FnHeader,
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
Expand Down
28 changes: 15 additions & 13 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,14 +873,21 @@ fn render_assoc_item(
fn method(
w: &mut Buffer,
meth: &clean::Item,
header: hir::FnHeader,
g: &clean::Generics,
d: &clean::FnDecl,
link: AssocItemLink<'_>,
parent: ItemType,
cx: &Context<'_>,
) {
let tcx = cx.tcx();
let name = meth.name.as_ref().unwrap();
let did = meth.def_id.expect_def_id();
let sig = tcx.fn_sig(did);
let meth_constness =
if tcx.is_const_fn_raw(did) { hir::Constness::Const } else { hir::Constness::NotConst };
let meth_asyncness = tcx.asyncness(did);
let meth_unsafety = sig.unsafety();

let href = match link {
AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{}", id)),
AssocItemLink::Anchor(None) => Some(format!("#{}.{}", meth.type_(), name)),
Expand All @@ -901,12 +908,11 @@ fn render_assoc_item(
}
};
let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
let constness =
print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()));
let asyncness = header.asyncness.print_with_space();
let unsafety = header.unsafety.print_with_space();
let constness = print_constness_with_space(&meth_constness, meth.const_stability(tcx));
let asyncness = meth_asyncness.print_with_space();
let unsafety = meth_unsafety.print_with_space();
let defaultness = print_default_space(meth.is_default());
let abi = print_abi_with_space(header.abi).to_string();
let abi = print_abi_with_space(sig.abi()).to_string();

// NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
let generics_len = format!("{:#}", g.print(cx)).len();
Expand Down Expand Up @@ -945,19 +951,15 @@ fn render_assoc_item(
href = href.map(|href| format!("href=\"{}\"", href)).unwrap_or_else(|| "".to_string()),
name = name,
generics = g.print(cx),
decl = d.full_print(header_len, indent, header.asyncness, cx),
decl = d.full_print(header_len, indent, meth_asyncness, cx),
notable_traits = notable_traits_decl(d, cx),
where_clause = print_where_clause(g, cx, indent, end_newline),
)
}
match *item.kind {
clean::StrippedItem(..) => {}
clean::TyMethodItem(ref m) => {
method(w, item, m.header, &m.generics, &m.decl, link, parent, cx)
}
clean::MethodItem(ref m, _) => {
method(w, item, m.header, &m.generics, &m.decl, link, parent, cx)
}
clean::TyMethodItem(ref m) => method(w, item, &m.generics, &m.decl, link, parent, cx),
clean::MethodItem(ref m, _) => method(w, item, &m.generics, &m.decl, link, parent, cx),
clean::AssocConstItem(ref ty, ref default) => assoc_const(
w,
item,
Expand Down
23 changes: 16 additions & 7 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,9 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
}

let unsafety_flag = match *myitem.kind {
clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
if func.header.unsafety == hir::Unsafety::Unsafe =>
clean::FunctionItem(_) | clean::ForeignFunctionItem(_)
if cx.tcx().fn_sig(myitem.def_id.expect_def_id()).unsafety()
== hir::Unsafety::Unsafe =>
{
"<a title=\"unsafe function\" href=\"#\"><sup>⚠</sup></a>"
}
Expand Down Expand Up @@ -465,11 +466,19 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
}

fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
let tcx = cx.tcx();
let did = it.def_id.expect_def_id();
let sig = tcx.fn_sig(did);
let it_constness =
if tcx.is_const_fn_raw(did) { hir::Constness::Const } else { hir::Constness::NotConst };
let it_asyncness = tcx.asyncness(did);
let it_unsafety = sig.unsafety();

let vis = it.visibility.print_with_space(it.def_id, cx).to_string();
let constness = print_constness_with_space(&f.header.constness, it.const_stability(cx.tcx()));
let asyncness = f.header.asyncness.print_with_space();
let unsafety = f.header.unsafety.print_with_space();
let abi = print_abi_with_space(f.header.abi).to_string();
let constness = print_constness_with_space(&it_constness, it.const_stability(tcx));
let asyncness = it_asyncness.print_with_space();
let unsafety = it_unsafety.print_with_space();
let abi = print_abi_with_space(sig.abi()).to_string();
let name = it.name.as_ref().unwrap();

let generics_len = format!("{:#}", f.generics.print(cx)).len();
Expand Down Expand Up @@ -498,7 +507,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
name = name,
generics = f.generics.print(cx),
where_clause = print_where_clause(&f.generics, cx, 0, true),
decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx),
decl = f.decl.full_print(header_len, 0, it_asyncness, cx),
notable_traits = notable_traits_decl(&f.decl, cx),
);
});
Expand Down
Loading