blob: f9731a451a3a8d98785f60b58db85eabcb975568 [file] [log] [blame]
// Copyright (C) 2020-2024 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include "optional.h"
#include "rust-ast-full.h"
#include "rust-late-name-resolver-2.0.h"
#include "rust-default-resolver.h"
#include "rust-path.h"
#include "rust-tyty.h"
#include "rust-hir-type-check.h"
namespace Rust {
namespace Resolver2_0 {
Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
void
Late::setup_builtin_types ()
{
auto next_id = [this] () { return ctx.mappings.get_next_hir_id (); };
static const std::pair<std::string, TyTy::BaseType *> builtins[] = {
{"u8", new TyTy::UintType (next_id (), TyTy::UintType::U8)},
{"u16", new TyTy::UintType (next_id (), TyTy::UintType::U16)},
{"u32", new TyTy::UintType (next_id (), TyTy::UintType::U32)},
{"u64", new TyTy::UintType (next_id (), TyTy::UintType::U64)},
{"u128", new TyTy::UintType (next_id (), TyTy::UintType::U128)},
{"i8", new TyTy::IntType (next_id (), TyTy::IntType::I8)},
{"i16", new TyTy::IntType (next_id (), TyTy::IntType::I16)},
{"i32", new TyTy::IntType (next_id (), TyTy::IntType::I32)},
{"i64", new TyTy::IntType (next_id (), TyTy::IntType::I64)},
{"i128", new TyTy::IntType (next_id (), TyTy::IntType::I128)},
{"f32", new TyTy::FloatType (next_id (), TyTy::FloatType::F32)},
{"f64", new TyTy::FloatType (next_id (), TyTy::FloatType::F64)},
{"usize", new TyTy::USizeType (next_id ())},
{"isize", new TyTy::ISizeType (next_id ())},
// missing char, str, never, ()
// does name resolution play a part for this? or is it all at typechecking?
// yeah it seems to be name resolution as well, which makes sense
};
for (const auto &builtin : builtins)
{
// we should be able to use `insert_at_root` or `insert` here, since we're
// at the root :) hopefully!
auto ok
= ctx.types.insert (builtin.first, builtin.second->get_ref ()
/* FIXME: Invalid! This returns an *HirId* */);
rust_assert (ok);
}
}
void
Late::go (AST::Crate &crate)
{
setup_builtin_types ();
for (auto &item : crate.items)
item->accept_vis (*this);
}
void
Late::new_label (Identifier name, NodeId id)
{
// labels can always shadow, so `insert` should never fail. if it does, we're
// in big trouble!
auto ok = ctx.labels.insert (name, id);
rust_assert (ok);
}
void
Late::visit (AST::LetStmt &let)
{
// so we don't need that method
DefaultResolver::visit (let);
// how do we deal with the fact that `let a = blipbloup` should look for a
// label and cannot go through function ribs, but `let a = blipbloup()` can?
// how do we insert ribs here, and only pop them when we exit the current
// function?
// keep a list of ribs to pop when a scope exits? so only for blocks?
// how do we pop ribs that need to be popped not in order?
// I think it's not important if we have shadowing, correct?
// if we have shadowing, it should work! we'll see
// ctx.insert(Identifier name, NodeId id, Namespace ns)
// ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
// Namespace::Labels,
// let.get_node_id (), [] () {});
}
void
Late::visit (AST::IdentifierPattern &identifier)
{
// do we insert in labels or in values
// but values does not allow shadowing... since functions cannot shadow
// do we insert functions in labels as well?
new_label (identifier.get_ident (), identifier.get_node_id ());
}
void
Late::visit (AST::IdentifierExpr &expr)
{
// TODO: same thing as visit(PathInExpression) here?
tl::optional<NodeId> resolved = tl::nullopt;
auto label = ctx.labels.get (expr.get_ident ());
auto value = ctx.values.get (expr.get_ident ());
if (label)
resolved = label;
else if (value)
resolved = value;
// TODO: else emit error?
ctx.map_usage (expr.get_node_id (), *resolved);
// in the old resolver, resolutions are kept in the resolver, not the mappings
// :/ how do we deal with that?
// ctx.mappings.insert_resolved_name(expr, resolved);
// For empty types, do we perform a lookup in ctx.types or should the
// toplevel instead insert a name in ctx.values? (like it currently does)
}
void
Late::visit (AST::PathInExpression &expr)
{
// TODO: How do we have a nice error with `can't capture dynamic environment
// in a function item` error here?
// do we emit it in `get<Namespace::Labels>`?
auto label = ctx.labels.resolve_path (expr.get_segments ());
auto value = ctx.values.resolve_path (expr.get_segments ());
}
void
Late::visit (AST::TypePath &type)
{
// should we add type path resolution in `ForeverStack` directly? Since it's
// quite more complicated.
// maybe we can overload `resolve_path<Namespace::Types>` to only do
// typepath-like path resolution? that sounds good
auto resolved = ctx.types.get (type.get_segments ().back ()->as_string ());
ctx.map_usage (type.get_node_id (), *resolved);
}
} // namespace Resolver2_0
} // namespace Rust