replace todo with fixme

This commit is contained in:
Aleksey Kladov 2019-03-23 10:53:48 +03:00
parent 2394a2ee35
commit 4fd8cfd6ad
29 changed files with 71 additions and 71 deletions

View file

@ -136,7 +136,7 @@ impl CrateGraph {
self.arena[&crate_id].edition
}
// TODO: this only finds one crate with the given root; we could have multiple
// FIXME: this only finds one crate with the given root; we could have multiple
pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
let (&crate_id, _) = self.arena.iter().find(|(_crate_id, data)| data.file_id == file_id)?;
Some(crate_id)

View file

@ -51,7 +51,7 @@ impl Crate {
crate_graph.edition(self.crate_id)
}
// TODO: should this be in source_binder?
// FIXME: should this be in source_binder?
pub fn source_root_crates(
db: &impl PersistentHirDatabase,
source_root: SourceRootId,
@ -301,7 +301,7 @@ impl Struct {
db.type_for_def((*self).into(), Namespace::Values)
}
// TODO move to a more general type
// FIXME move to a more general type
/// Builds a resolver for type references inside this struct.
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
// take the outer scope...
@ -361,7 +361,7 @@ impl Enum {
db.type_for_def((*self).into(), Namespace::Types)
}
// TODO: move to a more general type
// FIXME: move to a more general type
/// Builds a resolver for type references inside this struct.
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
// take the outer scope...
@ -513,7 +513,7 @@ impl Function {
ImplBlock::containing(module_impls, (*self).into())
}
// TODO: move to a more general type for 'body-having' items
// FIXME: move to a more general type for 'body-having' items
/// Builds a resolver for code inside this item.
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
// take the outer scope...
@ -558,7 +558,7 @@ impl Const {
ImplBlock::containing(module_impls, (*self).into())
}
// TODO: move to a more general type for 'body-having' items
// FIXME: move to a more general type for 'body-having' items
/// Builds a resolver for code inside this item.
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
// take the outer scope...

View file

@ -27,7 +27,7 @@ impl_arena_id!(ExprId);
/// The body of an item (function, const etc.).
#[derive(Debug, Eq, PartialEq)]
pub struct Body {
// TODO: this should be more general, consts & statics also have bodies
// FIXME: this should be more general, consts & statics also have bodies
/// The Function of the item this body belongs to
owner: Function,
exprs: Arena<ExprId, Expr>,
@ -406,7 +406,7 @@ pub enum Pat {
Struct {
path: Option<Path>,
args: Vec<FieldPat>,
// TODO: 'ellipsis' option
// FIXME: 'ellipsis' option
},
Range {
start: ExprId,
@ -547,7 +547,7 @@ impl ExprCollector {
if condition.pat().is_none() {
self.collect_expr_opt(condition.expr())
} else {
// TODO handle while let
// FIXME handle while let
return self.alloc_expr(Expr::Missing, syntax_ptr);
}
} else {
@ -610,7 +610,7 @@ impl ExprCollector {
self.alloc_expr(path, syntax_ptr)
}
ast::ExprKind::ContinueExpr(_e) => {
// TODO: labels
// FIXME: labels
self.alloc_expr(Expr::Continue, syntax_ptr)
}
ast::ExprKind::BreakExpr(e) => {
@ -751,7 +751,7 @@ impl ExprCollector {
self.alloc_expr(Expr::Literal(lit), syntax_ptr)
}
// TODO implement HIR for these:
// FIXME implement HIR for these:
ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
@ -844,7 +844,7 @@ impl ExprCollector {
Pat::Struct { path, args: fields }
}
// TODO: implement
// FIXME: implement
ast::PatKind::LiteralPat(_) => Pat::Missing,
ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
};
@ -910,7 +910,7 @@ pub(crate) fn body_with_source_map_query(
) -> (Arc<Body>, Arc<BodySourceMap>) {
let mut collector = ExprCollector::new(func);
// TODO: consts, etc.
// FIXME: consts, etc.
collector.collect_fn_body(&func.source(db).1);
let (body, source_map) = collector.finish();

View file

@ -39,7 +39,7 @@ pub struct ScopeData {
}
impl ExprScopes {
// TODO: This should take something more general than Function
// FIXME: This should take something more general than Function
pub(crate) fn expr_scopes_query(db: &impl HirDatabase, function: Function) -> Arc<ExprScopes> {
let body = db.body_hir(function);
let res = ExprScopes::new(body);
@ -148,7 +148,7 @@ impl ScopesWithSourceMap {
// XXX: during completion, cursor might be outside of any particular
// expression. Try to figure out the correct scope...
// TODO: move this to source binder?
// FIXME: move this to source binder?
fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId {
let r = ptr.range();
let child_scopes = self

View file

@ -15,7 +15,7 @@ use crate::{
/// Data about a generic parameter (to a function, struct, impl, ...).
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct GenericParam {
// TODO: give generic params proper IDs
// FIXME: give generic params proper IDs
pub(crate) idx: u32,
pub(crate) name: Name,
}

View file

@ -161,7 +161,7 @@ impl ImplData {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
//TODO: rename to ImplDef?
//FIXME: rename to ImplDef?
pub enum ImplItem {
Method(Function),
Const(Const),

View file

@ -296,7 +296,7 @@ impl CrateDefMap {
// plain import or absolute path in 2015: crate-relative with
// fallback to extern prelude (with the simplification in
// rust-lang/rust#57745)
// TODO there must be a nicer way to write this condition
// FIXME there must be a nicer way to write this condition
PathKind::Plain | PathKind::Abs
if self.edition == Edition::Edition2015
&& (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>

View file

@ -96,7 +96,7 @@ impl Path {
if let Some(q) = path.qualifier() {
return Some(q);
}
// TODO: this bottom up traversal is not too precise.
// FIXME: this bottom up traversal is not too precise.
// Should we handle do a top-down analysis, recording results?
let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
let use_tree = use_tree_list.parent_use_tree();
@ -166,7 +166,7 @@ fn expand_use_tree<'a>(
// or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
Some(path) => match convert_path(prefix, path) {
Some(it) => Some(it),
None => return, // TODO: report errors somewhere
None => return, // FIXME: report errors somewhere
},
};
for child_tree in use_tree_list.use_trees() {
@ -194,7 +194,7 @@ fn expand_use_tree<'a>(
cb(path, Some(segment), alias)
};
}
// TODO: report errors somewhere
// FIXME: report errors somewhere
// We get here if we do
}
}

View file

@ -19,7 +19,7 @@ pub struct Resolver {
scopes: Vec<Scope>,
}
// TODO how to store these best
// FIXME how to store these best
#[derive(Debug, Clone)]
pub(crate) struct ModuleItemMap {
crate_def_map: Arc<CrateDefMap>,
@ -260,7 +260,7 @@ impl Scope {
fn collect_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, PerNs<Resolution>)) {
match self {
Scope::ModuleScope(m) => {
// TODO: should we provide `self` here?
// FIXME: should we provide `self` here?
// f(
// Name::self_param(),
// PerNs::types(Resolution::Def {

View file

@ -164,7 +164,7 @@ pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> R
let scope = scopes.scope_for_offset(position.offset);
Some(expr::resolver_for_scope(func.body(db), db, scope))
} else {
// TODO const/static/array length
// FIXME const/static/array length
None
}
} else {
@ -184,7 +184,7 @@ pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNo
let scope = scopes.scope_for(&node);
Some(expr::resolver_for_scope(func.body(db), db, scope))
} else {
// TODO const/static/array length
// FIXME const/static/array length
None
}
} else {
@ -212,7 +212,7 @@ fn try_get_resolver_for_node(
} else if let Some(f) = ast::FnDef::cast(node) {
function_from_source(db, file_id, f).map(|f| f.resolver(db))
} else {
// TODO add missing cases
// FIXME add missing cases
None
}
}

View file

@ -15,7 +15,7 @@ impl Ty {
}
fn autoderef_step(&self, _db: &impl HirDatabase) -> Option<Ty> {
// TODO Deref::deref
// FIXME Deref::deref
self.builtin_deref()
}
}

View file

@ -207,7 +207,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
let ty = Ty::from_hir(
self.db,
// TODO use right resolver for block
// FIXME use right resolver for block
&self.resolver,
type_ref,
);
@ -414,11 +414,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
return None;
}
Resolution::GenericParam(..) => {
// TODO associated item of generic param
// FIXME associated item of generic param
return None;
}
Resolution::SelfType(_) => {
// TODO associated item of self type
// FIXME associated item of self type
return None;
}
};
@ -446,7 +446,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
}
}
// TODO: Resolve associated types
// FIXME: Resolve associated types
crate::ImplItem::TypeAlias(_) => None,
};
match matching_def {
@ -504,7 +504,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
return (Ty::Unknown, None);
}
Some(Resolution::SelfType(..)) => {
// TODO this is allowed in an impl for a struct, handle this
// FIXME this is allowed in an impl for a struct, handle this
return (Ty::Unknown, None);
}
None => return (Ty::Unknown, None),
@ -513,7 +513,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
None => return (Ty::Unknown, None),
Some(it) => it,
};
// TODO remove the duplication between here and `Ty::from_path`?
// FIXME remove the duplication between here and `Ty::from_path`?
let substs = Ty::substs_from_path(self.db, resolver, path, def);
match def {
TypableDef::Struct(s) => {
@ -590,7 +590,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
| Pat::Struct { .. }
| Pat::Range { .. }
| Pat::Slice { .. } => true,
// TODO: Path/Lit might actually evaluate to ref, but inference is unimplemented.
// FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
Pat::Path(..) | Pat::Lit(..) => true,
Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
};
@ -635,7 +635,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let expectation = match expected.as_reference() {
Some((inner_ty, exp_mut)) => {
if *mutability != exp_mut {
// TODO: emit type error?
// FIXME: emit type error?
}
inner_ty
}
@ -651,7 +651,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
self.infer_struct_pat(p.as_ref(), fields, expected, default_bm)
}
Pat::Path(path) => {
// TODO use correct resolver for the surrounding expression
// FIXME use correct resolver for the surrounding expression
let resolver = self.resolver.clone();
self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
}
@ -741,7 +741,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
Expr::Loop { body } => {
self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
// TODO handle break with value
// FIXME handle break with value
Ty::simple(TypeCtor::Never)
}
Expr::While { condition, body } => {
@ -769,7 +769,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
self.infer_pat(*arg_pat, &expected, BindingMode::default());
}
// TODO: infer lambda type etc.
// FIXME: infer lambda type etc.
let _body_ty = self.infer_expr(*body, &Expectation::none());
Ty::Unknown
}
@ -795,7 +795,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
},
_ => {
// not callable
// TODO report an error?
// FIXME report an error?
(Vec::new(), Ty::Unknown)
}
};
@ -894,14 +894,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
expected.ty
}
Expr::Path(p) => {
// TODO this could be more efficient...
// FIXME this could be more efficient...
let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr);
self.infer_path_expr(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
}
Expr::Continue => Ty::simple(TypeCtor::Never),
Expr::Break { expr } => {
if let Some(expr) = expr {
// TODO handle break with value
// FIXME handle break with value
self.infer_expr(*expr, &Expectation::none());
}
Ty::simple(TypeCtor::Never)
@ -957,21 +957,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Expr::Cast { expr, type_ref } => {
let _inner_ty = self.infer_expr(*expr, &Expectation::none());
let cast_ty = self.make_ty(type_ref);
// TODO check the cast...
// FIXME check the cast...
cast_ty
}
Expr::Ref { expr, mutability } => {
let expectation =
if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() {
if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared {
// TODO: throw type error - expected mut reference but found shared ref,
// FIXME: throw type error - expected mut reference but found shared ref,
// which cannot be coerced
}
Expectation::has_type(Ty::clone(exp_inner))
} else {
Expectation::none()
};
// TODO reference coercions etc.
// FIXME reference coercions etc.
let inner_ty = self.infer_expr(*expr, &expectation);
Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
}
@ -982,7 +982,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
if let Some(derefed_ty) = inner_ty.builtin_deref() {
derefed_ty
} else {
// TODO Deref::deref
// FIXME Deref::deref
Ty::Unknown
}
}
@ -1002,7 +1002,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => {
inner_ty
}
// TODO: resolve ops::Neg trait
// FIXME: resolve ops::Neg trait
_ => Ty::Unknown,
}
}
@ -1013,7 +1013,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
_ => Ty::Unknown,
},
Ty::Infer(InferTy::IntVar(..)) => inner_ty,
// TODO: resolve ops::Not trait for inner_ty
// FIXME: resolve ops::Not trait for inner_ty
_ => Ty::Unknown,
}
}
@ -1028,12 +1028,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
_ => Expectation::none(),
};
let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
// TODO: find implementation of trait corresponding to operation
// FIXME: find implementation of trait corresponding to operation
// symbol and resolve associated `Output` type
let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty);
let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
// TODO: similar as above, return ty is often associated trait type
// FIXME: similar as above, return ty is often associated trait type
op::binary_op_return_ty(*op, rhs_ty)
}
_ => Ty::Unknown,
@ -1227,7 +1227,7 @@ impl InferTy {
#[derive(Clone, PartialEq, Eq, Debug)]
struct Expectation {
ty: Ty,
// TODO: In some cases, we need to be aware whether the expectation is that
// FIXME: In some cases, we need to be aware whether the expectation is that
// the type match exactly what we passed, or whether it just needs to be
// coercible to the expected type. See Expectation::rvalue_hint in rustc.
}

View file

@ -60,7 +60,7 @@ impl Ty {
pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self {
if let Some(name) = path.as_ident() {
// TODO handle primitive type names in resolver as well?
// FIXME handle primitive type names in resolver as well?
if let Some(int_ty) = primitive::IntTy::from_type_name(name) {
return Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known(int_ty)));
} else if let Some(float_ty) = primitive::FloatTy::from_type_name(name) {
@ -87,7 +87,7 @@ impl Ty {
Some(Resolution::GenericParam(idx)) => {
return Ty::Param {
idx,
// TODO: maybe return name in resolution?
// FIXME: maybe return name in resolution?
name: path
.as_ident()
.expect("generic param should be single-segment path")
@ -139,7 +139,7 @@ impl Ty {
}
}
// add placeholders for args that were not provided
// TODO: handle defaults
// FIXME: handle defaults
let supplied_params = substs.len();
for _ in supplied_params..def_generics.count_params_including_parent() {
substs.push(Ty::Unknown);

View file

@ -120,7 +120,7 @@ fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
}
impl Ty {
// TODO: cache this as a query?
// FIXME: cache this as a query?
// - if so, what signature? (TyFingerprint, Name)?
// - or maybe cache all names and def_ids of methods per fingerprint?
/// Look up the method with the given name, returning the actual autoderefed

View file

@ -30,7 +30,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
acc.add_field(ctx, field, &a_ty.parameters);
}
}
// TODO unions
// FIXME unions
TypeCtor::Tuple => {
for (i, ty) in a_ty.parameters.iter().enumerate() {
acc.add_pos_field(ctx, i, ty);

View file

@ -5,7 +5,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.is_pat_binding {
return;
}
// TODO: ideally, we should look at the type we are matching against and
// FIXME: ideally, we should look at the type we are matching against and
// suggest variants + auto-imports
let names = ctx.resolver.all_names(ctx.db);
for (name, res) in names.into_iter() {

View file

@ -26,7 +26,7 @@ pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionCon
}
}
// TODO unions
// FIXME unions
AdtDef::Enum(_) => (),
};
}

View file

@ -117,7 +117,7 @@ pub(crate) fn reference_definition(
return Exact(nav);
}
Some(Resolution::GenericParam(..)) => {
// TODO: go to the generic param def
// FIXME: go to the generic param def
}
Some(Resolution::SelfType(impl_block)) => {
let ty = impl_block.target_ty(db);

View file

@ -204,7 +204,7 @@ impl NavigationTarget {
///
/// e.g. `struct Name`, `enum Name`, `fn Name`
fn description(&self, db: &RootDatabase) -> Option<String> {
// TODO: After type inference is done, add type information to improve the output
// FIXME: After type inference is done, add type information to improve the output
let node = self.node(db)?;
fn visit_ascribed_node<T>(node: &T, prefix: &str) -> Option<String>

View file

@ -77,7 +77,7 @@ impl LineIndex {
}
pub fn offset(&self, line_col: LineCol) -> TextUnit {
//TODO: return Result
//FIXME: return Result
let col = self.utf16_to_utf8_col(line_col.line, line_col.col_utf16);
self.newlines[line_col.line as usize] + col
}

View file

@ -68,7 +68,7 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex>
let symbols = source_file_to_file_symbols(&source_file, file_id);
// TODO: add macros here
// FIXME: add macros here
Arc::new(SymbolIndex::new(symbols))
}

View file

@ -11,7 +11,7 @@ pub(super) fn const_def(p: &mut Parser, m: Marker) {
fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
assert!(p.at(kw));
p.bump();
p.eat(MUT_KW); // TODO: validator to forbid const mut
p.eat(MUT_KW); // FIXME: validator to forbid const mut
name(p);
types::ascription(p);
if p.eat(EQ) {

View file

@ -15,7 +15,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
}
L_CURLY => named_field_def_list(p),
_ => {
//TODO: special case `(` error message
//FIXME: special case `(` error message
p.error("expected `;` or `{`");
}
}

View file

@ -49,7 +49,7 @@ pub(super) fn impl_block(p: &mut Parser) {
type_params::opt_type_param_list(p);
}
// TODO: never type
// FIXME: never type
// impl ! {}
// test impl_block_neg

View file

@ -21,7 +21,7 @@ fn use_tree(p: &mut Parser) {
// This does not handle cases such as `use some::path::*`
// N.B. in Rust 2015 `use *;` imports all from crate root
// however in Rust 2018 `use *;` errors: ('cannot glob-import all possible crates')
// TODO: Add this error (if not out of scope)
// FIXME: Add this error (if not out of scope)
// test use_star
// use *;
@ -33,7 +33,7 @@ fn use_tree(p: &mut Parser) {
// Parse `use ::*;`, which imports all from the crate root in Rust 2015
// This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`)
// but still parses and errors later: ('crate root in paths can only be used in start position')
// TODO: Add this error (if not out of scope)
// FIXME: Add this error (if not out of scope)
// In Rust 2018, it is always invalid (see above)
p.bump();
p.bump();

View file

@ -121,7 +121,7 @@ impl<'t> Parser<'t> {
/// final tree.
pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
if self.nth(0) == EOF {
// TODO: panic!?
// FIXME: panic!?
return;
}
self.do_bump(kind, 1);
@ -135,7 +135,7 @@ impl<'t> Parser<'t> {
}
/// Emit error with the `message`
/// TODO: this should be much more fancy and support
/// FIXME: this should be much more fancy and support
/// structured errors with spans and notes, like rustc
/// does.
pub(crate) fn error<T: Into<String>>(&mut self, message: T) {

View file

@ -23,7 +23,7 @@ pub use crate::{
sysroot::Sysroot,
};
// TODO use proper error enum
// FIXME use proper error enum
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
#[derive(Debug, Clone)]

View file

@ -85,7 +85,7 @@ pub(super) fn is_ascii_escape(code: char) -> bool {
fn validate_ascii_code_escape(text: &str, range: TextRange, errors: &mut Vec<SyntaxError>) {
// An AsciiCodeEscape has 4 chars, example: `\xDD`
if !text.is_ascii() {
// TODO: Give a more precise error message (say what the invalid character was)
// FIXME: Give a more precise error message (say what the invalid character was)
errors.push(SyntaxError::new(AsciiCodeEscapeOutOfRange, range));
} else if text.chars().count() < 4 {
errors.push(SyntaxError::new(TooShortAsciiCodeEscape, range));

View file

@ -61,7 +61,7 @@ fn reparse_fuzz_tests() {
}
/// Test that Rust-analyzer can parse and validate the rust-analyser
/// TODO: Use this as a benchmark
/// FIXME: Use this as a benchmark
#[test]
fn self_hosting_parsing() {
use std::ffi::OsStr;