Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 <liushuyu011@gmail.com>
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
  • Loading branch information
3 people authored Apr 11, 2022
6 parents e5281ee + fed5a41 + 6fb118f + 8d3184e + 4413bc0 + 3513fa3 commit 2669e80
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 43 deletions.
16 changes: 16 additions & 0 deletions gcc/rust/backend/rust-mangle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ static const std::string kMangledSubstBegin = "$LT$";
static const std::string kMangledSubstEnd = "$GT$";
static const std::string kMangledSpace = "$u20$";
static const std::string kMangledRef = "$RF$";
static const std::string kMangledPtr = "$BP$";
static const std::string kMangledLeftSqParen = "$u5b$"; // [
static const std::string kMangledRightSqParen = "$u5d$"; // ]
static const std::string kQualPathBegin = "_" + kMangledSubstBegin;

namespace Rust {
Expand All @@ -29,8 +32,15 @@ legacy_mangle_name (const std::string &name)
// <example::Bar as example::A>::fooA:
// _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
//
// core::ptr::const_ptr::<impl *const T>::cast:
// _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
//
// core::ptr::const_ptr::<impl *const [T]>::as_ptr:
// _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
//
// example::Foo<T>::new:
// _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:

std::string buffer;
for (size_t i = 0; i < name.size (); i++)
{
Expand All @@ -47,6 +57,12 @@ legacy_mangle_name (const std::string &name)
m = kMangledSubstBegin;
else if (c == '>')
m = kMangledSubstEnd;
else if (c == '*')
m = kMangledPtr;
else if (c == '[')
m = kMangledLeftSqParen;
else if (c == ']')
m = kMangledRightSqParen;
else if (c == ':')
{
rust_assert (i + 1 < name.size ());
Expand Down
69 changes: 60 additions & 9 deletions gcc/rust/expand/rust-macro-builtins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,12 @@ make_string (Location locus, std::string value)
PrimitiveCoreType::CORETYPE_STR, {}, locus));
}

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

std::unique_ptr<AST::LiteralExpr>
parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
Location invoc_locus)
static inline TokenId
macro_end_token (AST::DelimTokenTree &invoc_token_tree,
Parser<MacroInvocLexer> &parser)
{
MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
Parser<MacroInvocLexer> parser (std::move (lex));

auto last_token_id = TokenId::RIGHT_CURLY;
switch (invoc_token_tree.get_delim_type ())
{
Expand All @@ -63,6 +58,22 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
break;
}

return last_token_id;
}

/* Parse a single string literal from the given delimited token tree,
and return the LiteralExpr for it. Allow for an optional trailing comma,
but otherwise enforce that these are the only tokens. */

std::unique_ptr<AST::LiteralExpr>
parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
Location invoc_locus)
{
MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
Parser<MacroInvocLexer> parser (std::move (lex));

auto last_token_id = macro_end_token (invoc_token_tree, parser);

std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr;

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

/* Expand builtin macro concat!(), which joins all the literal parameters
into a string with no delimiter. */

AST::ASTFragment
MacroBuiltin::concat (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto invoc_token_tree = invoc.get_delim_tok_tree ();
MacroInvocLexer lex (invoc_token_tree.to_token_stream ());
Parser<MacroInvocLexer> parser (std::move (lex));
auto str = std::string ();
bool has_error = false;

auto last_token_id = macro_end_token (invoc_token_tree, parser);

/* NOTE: concat! could accept no argument, so we don't have any checks here */
while (parser.peek_current_token ()->get_id () != last_token_id)
{
auto lit_expr = parser.parse_literal_expr ();
if (lit_expr)
{
str += lit_expr->as_string ();
}
else
{
rust_error_at (parser.peek_current_token ()->get_locus (),
"argument must be a constant literal");
has_error = true;
}
parser.maybe_skip_token (COMMA);
}

parser.skip_token (last_token_id);

if (has_error)
return AST::ASTFragment::create_error ();

auto node = AST::SingleASTNode (make_string (invoc_locus, str));
return AST::ASTFragment ({node});
}

} // namespace Rust
3 changes: 3 additions & 0 deletions gcc/rust/expand/rust-macro-builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class MacroBuiltin

static AST::ASTFragment compile_error (Location invoc_locus,
AST::MacroInvocData &invoc);

static AST::ASTFragment concat (Location invoc_locus,
AST::MacroInvocData &invoc);
};
} // namespace Rust

Expand Down
2 changes: 1 addition & 1 deletion gcc/rust/typecheck/rust-autoderef.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Adjuster::try_unsize_type (const TyTy::BaseType *ty)
TyTy::TyVar (slice_elem->get_ref ()));
context->insert_implicit_type (slice);

return Adjustment (Adjustment::AdjustmentType::INDIRECTION, slice);
return Adjustment (Adjustment::AdjustmentType::UNSIZE, slice);
}

static bool
Expand Down
25 changes: 22 additions & 3 deletions gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,26 @@ class OverlappingImplItemPass : public TypeCheckBase
continue;

if (query->can_eq (candidate, false))
possible_collision (it->second, iy->second);
{
// we might be in the case that we have:
//
// *const T vs *const [T]
//
// so lets use an equality check when the
// candidates are both generic to be sure we dont emit a false
// positive

bool a = query->is_concrete ();
bool b = candidate->is_concrete ();
bool both_generic = !a && !b;
if (both_generic)
{
if (!query->is_equal (*candidate))
continue;
}

possible_collision (it->second, iy->second);
}
}
}
}
Expand Down Expand Up @@ -152,8 +171,8 @@ class OverlappingImplItemPass : public TypeCheckBase
void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup,
const std::string &name)
{
RichLocation r (query->get_locus ());
r.add_range (dup->get_locus ());
RichLocation r (dup->get_locus ());
r.add_range (query->get_locus ());
rust_error_at (r, "duplicate definitions with name %s", name.c_str ());
}

Expand Down
5 changes: 4 additions & 1 deletion gcc/rust/typecheck/rust-hir-path-probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ class PathProbeType : public TypeCheckBase
return;

if (!receiver->can_eq (impl_block_ty, false))
return;
{
if (!impl_block_ty->can_eq (receiver, false))
return;
}

// lets visit the impl_item
item->accept_vis (*this);
Expand Down
5 changes: 4 additions & 1 deletion gcc/rust/typecheck/rust-tyty-bounds.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ TypeBoundsProbe::scan ()
return true;

if (!receiver->can_eq (impl_type, false))
return true;
{
if (!impl_type->can_eq (receiver, false))
return true;
}

possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl});
return true;
Expand Down
26 changes: 0 additions & 26 deletions gcc/rust/typecheck/rust-tyty-cmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,8 +886,6 @@ class ArrayCmp : public BaseCmp
ok = true;
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const ArrayType *base;
Expand Down Expand Up @@ -916,8 +914,6 @@ class SliceCmp : public BaseCmp
ok = true;
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const SliceType *base;
Expand All @@ -939,8 +935,6 @@ class BoolCmp : public BaseCmp
ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL;
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const BoolType *base;
Expand All @@ -965,8 +959,6 @@ class IntCmp : public BaseCmp
ok = type.get_int_kind () == base->get_int_kind ();
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const IntType *base;
Expand All @@ -991,8 +983,6 @@ class UintCmp : public BaseCmp
ok = type.get_uint_kind () == base->get_uint_kind ();
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const UintType *base;
Expand All @@ -1017,8 +1007,6 @@ class FloatCmp : public BaseCmp
ok = type.get_float_kind () == base->get_float_kind ();
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const FloatType *base;
Expand Down Expand Up @@ -1120,8 +1108,6 @@ class TupleCmp : public BaseCmp
ok = true;
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const TupleType *base;
Expand All @@ -1143,8 +1129,6 @@ class USizeCmp : public BaseCmp

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

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const USizeType *base;
Expand All @@ -1166,8 +1150,6 @@ class ISizeCmp : public BaseCmp

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

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const ISizeType *base;
Expand All @@ -1189,8 +1171,6 @@ class CharCmp : public BaseCmp

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

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const CharType *base;
Expand Down Expand Up @@ -1365,8 +1345,6 @@ class StrCmp : public BaseCmp

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

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const StrType *base;
Expand All @@ -1383,8 +1361,6 @@ class NeverCmp : public BaseCmp

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

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }
const NeverType *base;
Expand Down Expand Up @@ -1478,8 +1454,6 @@ class DynamicCmp : public BaseCmp
ok = base->bounds_compatible (type, ref_locus, false);
}

void visit (const ParamType &type) override { ok = true; }

private:
const BaseType *get_base () const override { return base; }

Expand Down
1 change: 1 addition & 0 deletions gcc/rust/util/rust-hir-map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
{"include_bytes", MacroBuiltin::include_bytes},
{"include_str", MacroBuiltin::include_str},
{"compile_error", MacroBuiltin::compile_error},
{"concat", MacroBuiltin::concat},
};

auto builtin = builtin_macros.find (macro->get_rule_name ());
Expand Down
9 changes: 9 additions & 0 deletions gcc/rust/util/rust-mapping-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ struct DefId
return ((uint64_t) this->crateNum << 32 | this->localDefId)
< ((uint64_t) other.crateNum << 32 | other.localDefId);
}

std::string as_string () const
{
std::string buf;
buf += std::to_string (crateNum);
buf += " "; // or anything else
buf += std::to_string (localDefId);
return buf;
}
};

#define UNKNOWN_CREATENUM ((uint32_t) (0))
Expand Down
15 changes: 15 additions & 0 deletions gcc/testsuite/rust/compile/builtin_macro_concat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
macro_rules! concat {
() => {{}};
}

fn main () {
let not_literal = "identifier";
concat! ();
concat! (,); // { dg-error "argument must be a constant literal" }
concat! (not_literal); // { dg-error "argument must be a constant literal" }
concat! ("message");
concat! ("message",);
concat! ("message",1, true, false, 1.0, 10usize, 2000u64);
concat! ("message",1, true, false, 1.0, 10usize, 2000u64,);
concat! ("m", not_literal); // { dg-error "argument must be a constant literal" }
}
2 changes: 1 addition & 1 deletion gcc/testsuite/rust/compile/generics7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Foo<char> {
}

impl<T> Foo<T> {
fn bar(self) -> T { // { dg-error "duplicate definitions with name bar" }
fn bar(self) -> T {
self.a
}
}
Expand Down
2 changes: 1 addition & 1 deletion gcc/testsuite/rust/compile/generics8.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
struct Foo<A, B>(A, B);

impl<T> Foo<i32, T> {
fn test(a: T) -> T { // { dg-error "duplicate definitions with name test" }
fn test(a: T) -> T {
a
}
}
Expand Down
Loading

0 comments on commit 2669e80

Please sign in to comment.