Skip to content

Commit 2669e80

Browse files
bors[bot]liushuyuphilberty
authored
1090: macros: add concat! macro r=philberty a=liushuyu - extracts parenthesis-matching logic into a function - adds `concat!` macro 1097: Support mangling *const ptr and slices like *const [T] r=philberty a=philberty The legacy mangling scheme needs to convert the canonical path containing * for pointers and the [] brackets representing slices into: * = $BP$ [ = $u5b$ ] = $u5d$ These symbols are not allowed in asm symbols. Addresses #849 1098: Ensure unsize method resolutions actually unsize r=philberty a=philberty This was a typo when unsized method resolution was added, where the adjustment was wrongly marked as an indirection. The enum is required so that the code generation adjustment takes place. Addresses #849 1099: Fix bad inherent overlap error r=philberty a=philberty When we examine HIR::ImplBlock's we determine if an impl might overlap another impl based on the Self type. So for example you might have a generic structure Foo<T>(T), and an associated impl block for Foo<i32>, but then go on to define an associated impl of Foo<T> the generic one will overlap any associated impl hiding the generic implementation. In this case we have two generic impl blocks *const [T] *const T This means the *const T might overlap with the slice one since it is generic. As bjorn3 pointed out in #1075 , the correct implementation is to observe that [T] is constrained by size but untill we have the auto trait of Sized we must example the two generic impls and just determine that they are not-equal so for now this is the best implementation we can do. Fixes #1075 1101: Add helper as_string for DefIds r=philberty a=philberty This just adds a useful helper to as_string DefId's directly Co-authored-by: liushuyu <[email protected]> Co-authored-by: Philip Herron <[email protected]>
6 parents e5281ee + fed5a41 + 6fb118f + 8d3184e + 4413bc0 + 3513fa3 commit 2669e80

15 files changed

+202
-43
lines changed

gcc/rust/backend/rust-mangle.cc

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ static const std::string kMangledSubstBegin = "$LT$";
1111
static const std::string kMangledSubstEnd = "$GT$";
1212
static const std::string kMangledSpace = "$u20$";
1313
static const std::string kMangledRef = "$RF$";
14+
static const std::string kMangledPtr = "$BP$";
15+
static const std::string kMangledLeftSqParen = "$u5b$"; // [
16+
static const std::string kMangledRightSqParen = "$u5d$"; // ]
1417
static const std::string kQualPathBegin = "_" + kMangledSubstBegin;
1518

1619
namespace Rust {
@@ -29,8 +32,15 @@ legacy_mangle_name (const std::string &name)
2932
// <example::Bar as example::A>::fooA:
3033
// _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
3134
//
35+
// core::ptr::const_ptr::<impl *const T>::cast:
36+
// _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
37+
//
38+
// core::ptr::const_ptr::<impl *const [T]>::as_ptr:
39+
// _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
40+
//
3241
// example::Foo<T>::new:
3342
// _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
43+
3444
std::string buffer;
3545
for (size_t i = 0; i < name.size (); i++)
3646
{
@@ -47,6 +57,12 @@ legacy_mangle_name (const std::string &name)
4757
m = kMangledSubstBegin;
4858
else if (c == '>')
4959
m = kMangledSubstEnd;
60+
else if (c == '*')
61+
m = kMangledPtr;
62+
else if (c == '[')
63+
m = kMangledLeftSqParen;
64+
else if (c == ']')
65+
m = kMangledRightSqParen;
5066
else if (c == ':')
5167
{
5268
rust_assert (i + 1 < name.size ());

gcc/rust/expand/rust-macro-builtins.cc

+60-9
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,12 @@ make_string (Location locus, std::string value)
3434
PrimitiveCoreType::CORETYPE_STR, {}, locus));
3535
}
3636

37-
/* Parse a single string literal from the given delimited token tree,
38-
and return the LiteralExpr for it. Allow for an optional trailing comma,
39-
but otherwise enforce that these are the only tokens. */
37+
/* Match the end token of a macro given the start delimiter of the macro */
4038

41-
std::unique_ptr<AST::LiteralExpr>
42-
parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
43-
Location invoc_locus)
39+
static inline TokenId
40+
macro_end_token (AST::DelimTokenTree &invoc_token_tree,
41+
Parser<MacroInvocLexer> &parser)
4442
{
45-
MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
46-
Parser<MacroInvocLexer> parser (std::move (lex));
47-
4843
auto last_token_id = TokenId::RIGHT_CURLY;
4944
switch (invoc_token_tree.get_delim_type ())
5045
{
@@ -63,6 +58,22 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
6358
break;
6459
}
6560

61+
return last_token_id;
62+
}
63+
64+
/* Parse a single string literal from the given delimited token tree,
65+
and return the LiteralExpr for it. Allow for an optional trailing comma,
66+
but otherwise enforce that these are the only tokens. */
67+
68+
std::unique_ptr<AST::LiteralExpr>
69+
parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
70+
Location invoc_locus)
71+
{
72+
MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
73+
Parser<MacroInvocLexer> parser (std::move (lex));
74+
75+
auto last_token_id = macro_end_token (invoc_token_tree, parser);
76+
6677
std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr;
6778

6879
if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
@@ -252,4 +263,44 @@ MacroBuiltin::compile_error (Location invoc_locus, AST::MacroInvocData &invoc)
252263
return AST::ASTFragment::create_error ();
253264
}
254265

266+
/* Expand builtin macro concat!(), which joins all the literal parameters
267+
into a string with no delimiter. */
268+
269+
AST::ASTFragment
270+
MacroBuiltin::concat (Location invoc_locus, AST::MacroInvocData &invoc)
271+
{
272+
auto invoc_token_tree = invoc.get_delim_tok_tree ();
273+
MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
274+
Parser<MacroInvocLexer> parser (std::move (lex));
275+
auto str = std::string ();
276+
bool has_error = false;
277+
278+
auto last_token_id = macro_end_token (invoc_token_tree, parser);
279+
280+
/* NOTE: concat! could accept no argument, so we don't have any checks here */
281+
while (parser.peek_current_token ()->get_id () != last_token_id)
282+
{
283+
auto lit_expr = parser.parse_literal_expr ();
284+
if (lit_expr)
285+
{
286+
str += lit_expr->as_string ();
287+
}
288+
else
289+
{
290+
rust_error_at (parser.peek_current_token ()->get_locus (),
291+
"argument must be a constant literal");
292+
has_error = true;
293+
}
294+
parser.maybe_skip_token (COMMA);
295+
}
296+
297+
parser.skip_token (last_token_id);
298+
299+
if (has_error)
300+
return AST::ASTFragment::create_error ();
301+
302+
auto node = AST::SingleASTNode (make_string (invoc_locus, str));
303+
return AST::ASTFragment ({node});
304+
}
305+
255306
} // namespace Rust

gcc/rust/expand/rust-macro-builtins.h

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ class MacroBuiltin
8080

8181
static AST::ASTFragment compile_error (Location invoc_locus,
8282
AST::MacroInvocData &invoc);
83+
84+
static AST::ASTFragment concat (Location invoc_locus,
85+
AST::MacroInvocData &invoc);
8386
};
8487
} // namespace Rust
8588

gcc/rust/typecheck/rust-autoderef.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ Adjuster::try_unsize_type (const TyTy::BaseType *ty)
116116
TyTy::TyVar (slice_elem->get_ref ()));
117117
context->insert_implicit_type (slice);
118118

119-
return Adjustment (Adjustment::AdjustmentType::INDIRECTION, slice);
119+
return Adjustment (Adjustment::AdjustmentType::UNSIZE, slice);
120120
}
121121

122122
static bool

gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h

+22-3
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,26 @@ class OverlappingImplItemPass : public TypeCheckBase
123123
continue;
124124

125125
if (query->can_eq (candidate, false))
126-
possible_collision (it->second, iy->second);
126+
{
127+
// we might be in the case that we have:
128+
//
129+
// *const T vs *const [T]
130+
//
131+
// so lets use an equality check when the
132+
// candidates are both generic to be sure we dont emit a false
133+
// positive
134+
135+
bool a = query->is_concrete ();
136+
bool b = candidate->is_concrete ();
137+
bool both_generic = !a && !b;
138+
if (both_generic)
139+
{
140+
if (!query->is_equal (*candidate))
141+
continue;
142+
}
143+
144+
possible_collision (it->second, iy->second);
145+
}
127146
}
128147
}
129148
}
@@ -152,8 +171,8 @@ class OverlappingImplItemPass : public TypeCheckBase
152171
void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup,
153172
const std::string &name)
154173
{
155-
RichLocation r (query->get_locus ());
156-
r.add_range (dup->get_locus ());
174+
RichLocation r (dup->get_locus ());
175+
r.add_range (query->get_locus ());
157176
rust_error_at (r, "duplicate definitions with name %s", name.c_str ());
158177
}
159178

gcc/rust/typecheck/rust-hir-path-probe.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,10 @@ class PathProbeType : public TypeCheckBase
284284
return;
285285

286286
if (!receiver->can_eq (impl_block_ty, false))
287-
return;
287+
{
288+
if (!impl_block_ty->can_eq (receiver, false))
289+
return;
290+
}
288291

289292
// lets visit the impl_item
290293
item->accept_vis (*this);

gcc/rust/typecheck/rust-tyty-bounds.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ TypeBoundsProbe::scan ()
4141
return true;
4242

4343
if (!receiver->can_eq (impl_type, false))
44-
return true;
44+
{
45+
if (!impl_type->can_eq (receiver, false))
46+
return true;
47+
}
4548

4649
possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl});
4750
return true;

gcc/rust/typecheck/rust-tyty-cmp.h

-26
Original file line numberDiff line numberDiff line change
@@ -886,8 +886,6 @@ class ArrayCmp : public BaseCmp
886886
ok = true;
887887
}
888888

889-
void visit (const ParamType &type) override { ok = true; }
890-
891889
private:
892890
const BaseType *get_base () const override { return base; }
893891
const ArrayType *base;
@@ -916,8 +914,6 @@ class SliceCmp : public BaseCmp
916914
ok = true;
917915
}
918916

919-
void visit (const ParamType &type) override { ok = true; }
920-
921917
private:
922918
const BaseType *get_base () const override { return base; }
923919
const SliceType *base;
@@ -939,8 +935,6 @@ class BoolCmp : public BaseCmp
939935
ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL;
940936
}
941937

942-
void visit (const ParamType &type) override { ok = true; }
943-
944938
private:
945939
const BaseType *get_base () const override { return base; }
946940
const BoolType *base;
@@ -965,8 +959,6 @@ class IntCmp : public BaseCmp
965959
ok = type.get_int_kind () == base->get_int_kind ();
966960
}
967961

968-
void visit (const ParamType &type) override { ok = true; }
969-
970962
private:
971963
const BaseType *get_base () const override { return base; }
972964
const IntType *base;
@@ -991,8 +983,6 @@ class UintCmp : public BaseCmp
991983
ok = type.get_uint_kind () == base->get_uint_kind ();
992984
}
993985

994-
void visit (const ParamType &type) override { ok = true; }
995-
996986
private:
997987
const BaseType *get_base () const override { return base; }
998988
const UintType *base;
@@ -1017,8 +1007,6 @@ class FloatCmp : public BaseCmp
10171007
ok = type.get_float_kind () == base->get_float_kind ();
10181008
}
10191009

1020-
void visit (const ParamType &type) override { ok = true; }
1021-
10221010
private:
10231011
const BaseType *get_base () const override { return base; }
10241012
const FloatType *base;
@@ -1120,8 +1108,6 @@ class TupleCmp : public BaseCmp
11201108
ok = true;
11211109
}
11221110

1123-
void visit (const ParamType &type) override { ok = true; }
1124-
11251111
private:
11261112
const BaseType *get_base () const override { return base; }
11271113
const TupleType *base;
@@ -1143,8 +1129,6 @@ class USizeCmp : public BaseCmp
11431129

11441130
void visit (const USizeType &type) override { ok = true; }
11451131

1146-
void visit (const ParamType &type) override { ok = true; }
1147-
11481132
private:
11491133
const BaseType *get_base () const override { return base; }
11501134
const USizeType *base;
@@ -1166,8 +1150,6 @@ class ISizeCmp : public BaseCmp
11661150

11671151
void visit (const ISizeType &type) override { ok = true; }
11681152

1169-
void visit (const ParamType &type) override { ok = true; }
1170-
11711153
private:
11721154
const BaseType *get_base () const override { return base; }
11731155
const ISizeType *base;
@@ -1189,8 +1171,6 @@ class CharCmp : public BaseCmp
11891171

11901172
void visit (const CharType &type) override { ok = true; }
11911173

1192-
void visit (const ParamType &type) override { ok = true; }
1193-
11941174
private:
11951175
const BaseType *get_base () const override { return base; }
11961176
const CharType *base;
@@ -1365,8 +1345,6 @@ class StrCmp : public BaseCmp
13651345

13661346
void visit (const StrType &type) override { ok = true; }
13671347

1368-
void visit (const ParamType &type) override { ok = true; }
1369-
13701348
private:
13711349
const BaseType *get_base () const override { return base; }
13721350
const StrType *base;
@@ -1383,8 +1361,6 @@ class NeverCmp : public BaseCmp
13831361

13841362
void visit (const NeverType &type) override { ok = true; }
13851363

1386-
void visit (const ParamType &type) override { ok = true; }
1387-
13881364
private:
13891365
const BaseType *get_base () const override { return base; }
13901366
const NeverType *base;
@@ -1478,8 +1454,6 @@ class DynamicCmp : public BaseCmp
14781454
ok = base->bounds_compatible (type, ref_locus, false);
14791455
}
14801456

1481-
void visit (const ParamType &type) override { ok = true; }
1482-
14831457
private:
14841458
const BaseType *get_base () const override { return base; }
14851459

gcc/rust/util/rust-hir-map.cc

+1
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
754754
{"include_bytes", MacroBuiltin::include_bytes},
755755
{"include_str", MacroBuiltin::include_str},
756756
{"compile_error", MacroBuiltin::compile_error},
757+
{"concat", MacroBuiltin::concat},
757758
};
758759

759760
auto builtin = builtin_macros.find (macro->get_rule_name ());

gcc/rust/util/rust-mapping-common.h

+9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ struct DefId
5050
return ((uint64_t) this->crateNum << 32 | this->localDefId)
5151
< ((uint64_t) other.crateNum << 32 | other.localDefId);
5252
}
53+
54+
std::string as_string () const
55+
{
56+
std::string buf;
57+
buf += std::to_string (crateNum);
58+
buf += " "; // or anything else
59+
buf += std::to_string (localDefId);
60+
return buf;
61+
}
5362
};
5463

5564
#define UNKNOWN_CREATENUM ((uint32_t) (0))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
macro_rules! concat {
2+
() => {{}};
3+
}
4+
5+
fn main () {
6+
let not_literal = "identifier";
7+
concat! ();
8+
concat! (,); // { dg-error "argument must be a constant literal" }
9+
concat! (not_literal); // { dg-error "argument must be a constant literal" }
10+
concat! ("message");
11+
concat! ("message",);
12+
concat! ("message",1, true, false, 1.0, 10usize, 2000u64);
13+
concat! ("message",1, true, false, 1.0, 10usize, 2000u64,);
14+
concat! ("m", not_literal); // { dg-error "argument must be a constant literal" }
15+
}

gcc/testsuite/rust/compile/generics7.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Foo<char> {
1515
}
1616

1717
impl<T> Foo<T> {
18-
fn bar(self) -> T { // { dg-error "duplicate definitions with name bar" }
18+
fn bar(self) -> T {
1919
self.a
2020
}
2121
}

gcc/testsuite/rust/compile/generics8.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
struct Foo<A, B>(A, B);
22

33
impl<T> Foo<i32, T> {
4-
fn test(a: T) -> T { // { dg-error "duplicate definitions with name test" }
4+
fn test(a: T) -> T {
55
a
66
}
77
}

0 commit comments

Comments
 (0)