Skip to content

Commit e0f261f

Browse files
bors[bot]philberty
andauthored
Merge #953
953: Refactor lang item mappings r=philberty a=philberty This refactors how we find our lang items so that during HIR lowering we have a generic outer attributes handler on Items. The old code only done lang item mappings during the type check pass and assumed all lang items are Traits which is not the case. To implement slices range syntax actually map to structs within libcore/ops/range.rs which have lang items on structs. This means we can have lang items on any Item. Co-authored-by: Philip Herron <[email protected]>
2 parents 265c223 + 865aa0a commit e0f261f

9 files changed

+551
-295
lines changed

gcc/rust/Make-lang.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ GRS_OBJS = \
7777
rust/rust-macro-invoc-lexer.o \
7878
rust/rust-hir-full-test.o \
7979
rust/rust-hir-map.o \
80+
rust/rust-attributes.o \
8081
rust/rust-abi.o \
8182
rust/rust-ast-lower.o \
8283
rust/rust-ast-lower-pattern.o \

gcc/rust/hir/rust-ast-lower-base.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "rust-ast-visitor.h"
2525
#include "rust-hir-map.h"
2626
#include "rust-hir-full.h"
27+
#include "rust-attributes.h"
2728

2829
namespace Rust {
2930
namespace HIR {
@@ -230,9 +231,13 @@ class ASTLoweringBase : public AST::ASTVisitor
230231
virtual void visit (AST::BareFunctionType &type) {}
231232

232233
protected:
233-
ASTLoweringBase () : mappings (Analysis::Mappings::get ()) {}
234+
ASTLoweringBase ()
235+
: mappings (Analysis::Mappings::get ()),
236+
attr_mappings (Analysis::BuiltinAttributeMappings::get ())
237+
{}
234238

235239
Analysis::Mappings *mappings;
240+
Analysis::BuiltinAttributeMappings *attr_mappings;
236241

237242
HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime)
238243
{
@@ -281,6 +286,16 @@ class ASTLoweringBase : public AST::ASTVisitor
281286

282287
HIR::FunctionQualifiers
283288
lower_qualifiers (const AST::FunctionQualifiers &qualifiers);
289+
290+
void handle_outer_attributes (const HIR::Item &item);
291+
292+
void handle_lang_item_attribute (const HIR::Item &item,
293+
const AST::Attribute &attr);
294+
295+
bool is_known_attribute (const std::string &attribute_path) const;
296+
297+
bool
298+
attribute_handled_in_another_pass (const std::string &attribute_path) const;
284299
};
285300

286301
} // namespace HIR

gcc/rust/hir/rust-ast-lower-item.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class ASTLoweringItem : public ASTLoweringBase
4444
{
4545
ASTLoweringItem resolver;
4646
item->accept_vis (resolver);
47+
48+
if (resolver.translated != nullptr)
49+
resolver.handle_outer_attributes (*resolver.translated);
50+
4751
return resolver.translated;
4852
}
4953

gcc/rust/hir/rust-ast-lower.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,5 +609,69 @@ ASTLoweringBase::lower_qualifiers (const AST::FunctionQualifiers &qualifiers)
609609
has_extern, extern_abi);
610610
}
611611

612+
void
613+
ASTLoweringBase::handle_outer_attributes (const HIR::Item &item)
614+
{
615+
for (const auto &attr : item.get_outer_attrs ())
616+
{
617+
const auto &str_path = attr.get_path ().as_string ();
618+
if (!is_known_attribute (str_path))
619+
{
620+
rust_error_at (attr.get_locus (), "unknown attribute");
621+
continue;
622+
}
623+
624+
bool is_lang_item = str_path.compare ("lang") == 0
625+
&& attr.has_attr_input ()
626+
&& attr.get_attr_input ().get_attr_input_type ()
627+
== AST::AttrInput::AttrInputType::LITERAL;
628+
629+
if (is_lang_item)
630+
handle_lang_item_attribute (item, attr);
631+
else if (!attribute_handled_in_another_pass (str_path))
632+
{
633+
rust_error_at (attr.get_locus (), "unhandled attribute: [%s]",
634+
attr.get_path ().as_string ().c_str ());
635+
}
636+
}
637+
}
638+
639+
void
640+
ASTLoweringBase::handle_lang_item_attribute (const HIR::Item &item,
641+
const AST::Attribute &attr)
642+
{
643+
auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
644+
const auto &lang_item_type_str = literal.get_literal ().as_string ();
645+
auto lang_item_type = Analysis::RustLangItem::Parse (lang_item_type_str);
646+
if (lang_item_type == Analysis::RustLangItem::ItemType::UNKNOWN)
647+
{
648+
rust_error_at (attr.get_locus (), "unknown lang item");
649+
return;
650+
}
651+
mappings->insert_lang_item (lang_item_type,
652+
item.get_mappings ().get_defid ());
653+
}
654+
655+
bool
656+
ASTLoweringBase::is_known_attribute (const std::string &attribute_path) const
657+
{
658+
const auto &lookup = attr_mappings->lookup_builtin (attribute_path);
659+
return !lookup.is_error ();
660+
}
661+
662+
bool
663+
ASTLoweringBase::attribute_handled_in_another_pass (
664+
const std::string &attribute_path) const
665+
{
666+
const auto &lookup = attr_mappings->lookup_builtin (attribute_path);
667+
if (lookup.is_error ())
668+
return false;
669+
670+
if (lookup.handler == Analysis::CompilerPass::UNKNOWN)
671+
return false;
672+
673+
return lookup.handler != Analysis::CompilerPass::HIR_LOWERING;
674+
}
675+
612676
} // namespace HIR
613677
} // namespace Rust

gcc/rust/typecheck/rust-hir-trait-resolve.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -207,31 +207,6 @@ class TraitResolver : public TypeCheckBase
207207
// loop of trying to resolve traits as required by the types
208208
tref->on_resolved ();
209209

210-
// does this have any lang-item attributes?
211-
for (auto &attr : trait_reference->get_outer_attrs ())
212-
{
213-
bool is_lang_item = attr.get_path ().as_string ().compare ("lang") == 0
214-
&& attr.has_attr_input ()
215-
&& attr.get_attr_input ().get_attr_input_type ()
216-
== AST::AttrInput::AttrInputType::LITERAL;
217-
if (is_lang_item)
218-
{
219-
auto &literal
220-
= static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
221-
const auto &lang_item_type_str
222-
= literal.get_literal ().as_string ();
223-
auto lang_item_type
224-
= Analysis::RustLangItem::Parse (lang_item_type_str);
225-
if (lang_item_type == Analysis::RustLangItem::ItemType::UNKNOWN)
226-
{
227-
rust_error_at (attr.get_locus (), "unknown lang item");
228-
return tref;
229-
}
230-
mappings->insert_lang_item (
231-
lang_item_type, trait_reference->get_mappings ().get_defid ());
232-
}
233-
}
234-
235210
return tref;
236211
}
237212

gcc/rust/util/rust-attributes.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-attributes.h"
20+
21+
namespace Rust {
22+
namespace Analysis {
23+
24+
// https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#256
25+
static const BuiltinAttrDefinition __definitions[] = {
26+
{"inline", CODE_GENERATION}, {"cfg", EXPANSION}, {"cfg_attr", EXPANSION},
27+
{"allow", STATIC_ANALYSIS}, {"lang", HIR_LOWERING},
28+
};
29+
30+
BuiltinAttributeMappings *
31+
BuiltinAttributeMappings::get ()
32+
{
33+
static BuiltinAttributeMappings *instance = nullptr;
34+
if (instance == nullptr)
35+
instance = new BuiltinAttributeMappings ();
36+
37+
return instance;
38+
}
39+
40+
const BuiltinAttrDefinition &
41+
BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
42+
{
43+
auto it = mappings.find (attr_name);
44+
if (it == mappings.end ())
45+
return BuiltinAttrDefinition::error_node ();
46+
47+
return it->second;
48+
}
49+
50+
BuiltinAttributeMappings::BuiltinAttributeMappings ()
51+
{
52+
size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
53+
for (size_t i = 0; i < ndefinitions; i++)
54+
{
55+
const BuiltinAttrDefinition &def = __definitions[i];
56+
mappings.insert ({def.name, def});
57+
}
58+
}
59+
60+
} // namespace Analysis
61+
} // namespace Rust

gcc/rust/util/rust-attributes.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-system.h"
20+
21+
namespace Rust {
22+
namespace Analysis {
23+
24+
enum CompilerPass
25+
{
26+
UNKNOWN,
27+
28+
EXPANSION,
29+
NAME_RESOLUTION,
30+
HIR_LOWERING,
31+
TYPE_CHECK,
32+
STATIC_ANALYSIS,
33+
CODE_GENERATION
34+
};
35+
36+
struct BuiltinAttrDefinition
37+
{
38+
std::string name;
39+
CompilerPass handler;
40+
41+
static BuiltinAttrDefinition get_error ()
42+
{
43+
return BuiltinAttrDefinition{"", UNKNOWN};
44+
}
45+
46+
static BuiltinAttrDefinition &error_node ()
47+
{
48+
static BuiltinAttrDefinition error_node = get_error ();
49+
return error_node;
50+
}
51+
52+
bool is_error () const { return name.empty (); }
53+
};
54+
55+
class BuiltinAttributeMappings
56+
{
57+
public:
58+
static BuiltinAttributeMappings *get ();
59+
60+
const BuiltinAttrDefinition &
61+
lookup_builtin (const std::string &attr_name) const;
62+
63+
private:
64+
BuiltinAttributeMappings ();
65+
66+
std::map<std::string, const BuiltinAttrDefinition> mappings;
67+
};
68+
69+
} // namespace Analysis
70+
} // namespace Rust

0 commit comments

Comments
 (0)